QTSS_Error ProcessRTSPRequest(QTSS_StandardRTSP_Params* inParams) { QTSS_RTSPMethod* theMethod = NULL; UInt32 theMethodLen = 0; if ((QTSS_GetValuePtr(inParams->inRTSPRequest, qtssRTSPReqMethod, 0, (void**)&theMethod, &theMethodLen) != QTSS_NoErr) || (theMethodLen != sizeof(QTSS_RTSPMethod))) { Assert(0); return QTSS_RequestFailed; } switch (*theMethod) { case qtssDescribeMethod: return DoDescribe(inParams); case qtssSetupMethod: return DoSetup(inParams); case qtssPlayMethod: return DoPlay(inParams); case qtssTeardownMethod: // Tell the server that this session should be killed, and send a TEARDOWN response (void)QTSS_Teardown(inParams->inClientSession); (void)QTSS_SendStandardRTSPResponse(inParams->inRTSPRequest, inParams->inClientSession, 0); break; case qtssPauseMethod: (void)QTSS_Pause(inParams->inClientSession); (void)QTSS_SendStandardRTSPResponse(inParams->inRTSPRequest, inParams->inClientSession, 0); break; default: break; } return QTSS_NoErr; }
QTSS_Error ProcessRTSPRequest(QTSS_StandardRTSP_Params* inParams) { QTSS_RTSPMethod* theMethod = NULL; UInt32 theLen = 0; if ((QTSS_GetValuePtr(inParams->inRTSPRequest, qtssRTSPReqMethod, 0, (void**)&theMethod, &theLen) != QTSS_NoErr) || (theLen != sizeof(QTSS_RTSPMethod))) { Assert(0); return QTSS_RequestFailed; } if (*theMethod == qtssDescribeMethod) return DoDescribe(inParams); if (*theMethod == qtssSetupMethod) return DoSetup(inParams); RTPSessionOutput** theOutput = NULL; QTSS_Error theErr = QTSS_GetValuePtr(inParams->inClientSession, sOutputAttr, 0, (void**)&theOutput, &theLen); if ((theErr != QTSS_NoErr) || (theLen != sizeof(RTPSessionOutput*))) // a broadcaster push session { if (*theMethod == qtssPlayMethod || *theMethod == qtssRecordMethod) return DoPlay(inParams, NULL); else return QTSS_RequestFailed; } switch (*theMethod) { case qtssPlayMethod: return DoPlay(inParams, (*theOutput)->GetReflectorSession()); case qtssTeardownMethod: // Tell the server that this session should be killed, and send a TEARDOWN response (void)QTSS_Teardown(inParams->inClientSession); (void)QTSS_SendStandardRTSPResponse(inParams->inRTSPRequest, inParams->inClientSession, 0); break; case qtssPauseMethod: (void)QTSS_Pause(inParams->inClientSession); (void)QTSS_SendStandardRTSPResponse(inParams->inRTSPRequest, inParams->inClientSession, 0); break; default: break; } return QTSS_NoErr; }
void RTPSessionOutput::TearDown() { QTSS_CliSesTeardownReason reason = qtssCliSesTearDownBroadcastEnded; (void)QTSS_SetValue(fClientSession, qtssCliTeardownReason, 0, &reason, sizeof(reason)); (void)QTSS_Teardown(fClientSession); }
QTSS_Error DoDescribe(QTSS_StandardRTSP_Params* inParamBlock) { // Check and see if this is a request we should handle. We handle all requests with URLs that // end in a '.rtp' char* theFullPathStr = NULL; QTSS_Error theError = QTSS_GetValueAsString(inParamBlock->inRTSPRequest, qtssRTSPReqLocalPath, 0, &theFullPathStr); QTSSCharArrayDeleter theFullPathDeleter(theFullPathStr); Assert(theError == QTSS_NoErr); StrPtrLen theFullPath(theFullPathStr); if ((theFullPath.Len <= sRTPSuffix.Len) || (!sRTPSuffix.NumEqualIgnoreCase(&theFullPath.Ptr[theFullPath.Len - sRTPSuffix.Len], sRTPSuffix.Len))) return QTSS_RequestFailed; // It is, so let's set everything up... // // Get the FileSession for this DESCRIBE, if any. UInt32 theLen = sizeof(FileSession*); FileSession* theFile = NULL; QTSS_Error theErr = QTSS_NoErr; (void)QTSS_GetValue(inParamBlock->inClientSession, sFileSessionAttr, 0, (void*)&theFile, &theLen); if ( theFile != NULL ) { // // There is already a file for this session. This can happen if there are multiple DESCRIBES, // or a DESCRIBE has been issued with a Session ID, or some such thing. if ( !theFullPath.Equal( *theFile->fFile.GetMoviePath() ) ) { delete theFile; theFile = NULL; // NULL out the attribute value, just in case. (void)QTSS_SetValue(inParamBlock->inClientSession, sFileSessionAttr, 0, &theFile, sizeof(theFile)); } } if ( theFile == NULL ) { theErr = CreateRTPFileSession(inParamBlock, theFullPath, &theFile); if (theErr != QTSS_NoErr) { (void)QTSS_Teardown(inParamBlock->inClientSession); return theErr; } // Store this newly created file object in the RTP session. theErr = QTSS_SetValue(inParamBlock->inClientSession, sFileSessionAttr, 0, &theFile, sizeof(theFile)); } //generate the SDP. UInt32 totalSDPLength = sSDPHeader1.Len; iovec theSDPVec[10];//1 for the RTSP header, 6 for the sdp header, 1 for the sdp body theSDPVec[1].iov_base = sSDPHeader1.Ptr; theSDPVec[1].iov_len = sSDPHeader1.Len; //filename goes here //(void)QTSS_GetValuePtr(inParamBlock->inRTSPRequest, qtssRTSPReqFilePath, 0, (void**)&theSDPVec[2].iov_base, (UInt32*)&theSDPVec[2].iov_len); char* filenameStr = NULL; (void)QTSS_GetValueAsString(inParamBlock->inRTSPRequest, qtssRTSPReqFilePath, 0, &filenameStr); QTSSCharArrayDeleter filenameStrDeleter(filenameStr); theSDPVec[2].iov_base = filenameStr; theSDPVec[2].iov_len = ::strlen(filenameStr); totalSDPLength += theSDPVec[2].iov_len; //url & admin email goes here theSDPVec[3].iov_base = sSDPHeader2.Ptr; theSDPVec[3].iov_len = sSDPHeader2.Len; totalSDPLength += sSDPHeader2.Len; //connection header theSDPVec[4].iov_base = sSDPHeader3.Ptr; theSDPVec[4].iov_len = sSDPHeader3.Len; totalSDPLength += sSDPHeader3.Len; //append IP addr (void)QTSS_GetValuePtr(inParamBlock->inRTSPSession, qtssRTSPSesLocalAddrStr, 0, (void**)&theSDPVec[5].iov_base, (UInt32*)&theSDPVec[5].iov_len); totalSDPLength += theSDPVec[5].iov_len; //last static sdp line theSDPVec[6].iov_base = sSDPHeader4.Ptr; theSDPVec[6].iov_len = sSDPHeader4.Len; totalSDPLength += sSDPHeader4.Len; //now append content-determined sdp theSDPVec[7].iov_base = theFile->fFile.GetSDPFile()->Ptr; theSDPVec[7].iov_len = theFile->fFile.GetSDPFile()->Len; totalSDPLength += theSDPVec[7].iov_len; Assert(theSDPVec[2].iov_base != NULL); // Append the Last Modified header to be a good caching proxy citizen before sending the Describe //(void)QTSS_AppendRTSPHeader(inParamBlock->inRTSPRequest, qtssLastModifiedHeader, // theFile->fFile.GetQTFile()->GetModDateStr(), DateBuffer::kDateBufferLen); (void)QTSS_AppendRTSPHeader(inParamBlock->inRTSPRequest, qtssCacheControlHeader, kCacheControlHeader.Ptr, kCacheControlHeader.Len); //ok, we have a filled out iovec. Let's send it! QTSSModuleUtils::SendDescribeResponse(inParamBlock->inRTSPRequest, inParamBlock->inClientSession, &theSDPVec[0], 8, totalSDPLength); return QTSS_NoErr; }