Bool16 StillFlushing(QTSS_Filter_Params* inParams,Bool16 flushing) { QTSS_Error err = QTSS_NoErr; if (flushing) { err = QTSS_Flush(inParams->inRTSPRequest); //qtss_printf("Flushing session=%"_U32BITARG_" QTSS_Flush err =%"_S32BITARG_"\n",sSessID,err); } if (err == QTSS_WouldBlock) // more to flush later { sFlushing = true; (void) QTSS_SetValue(inParams->inRTSPRequest, sFlushingID, 0, (void*)&sFlushing, sFlushingLen); err = QTSS_RequestEvent(inParams->inRTSPRequest, QTSS_WriteableEvent); KeepSession(inParams->inRTSPRequest,true); //qtss_printf("Flushing session=%"_U32BITARG_" QTSS_RequestEvent err =%"_S32BITARG_"\n",sSessID,err); } else { sFlushing = false; (void) QTSS_SetValue(inParams->inRTSPRequest, sFlushingID, 0, (void*)&sFlushing, sFlushingLen); KeepSession(inParams->inRTSPRequest,false); if (flushing) // we were flushing so reset the LastRequestTime { sLastRequestTime = QTSS_Milliseconds(); //qtss_printf("Done Flushing session=%"_U32BITARG_"\n",sSessID); return true; } } return sFlushing; }
QTSS_Error QTSSModuleUtils::SendErrorResponseWithMessage( QTSS_RTSPRequestObject inRequest, QTSS_RTSPStatusCode inStatusCode, StrPtrLen* inErrorMessagePtr) { static Bool16 sFalse = false; //set RTSP headers necessary for this error response message (void)QTSS_SetValue(inRequest, qtssRTSPReqStatusCode, 0, &inStatusCode, sizeof(inStatusCode)); (void)QTSS_SetValue(inRequest, qtssRTSPReqRespKeepAlive, 0, &sFalse, sizeof(sFalse)); StrPtrLen theErrorMessage(NULL, 0); if (sEnableRTSPErrorMsg) { Assert(inErrorMessagePtr != NULL); //Assert(inErrorMessagePtr->Ptr != NULL); //Assert(inErrorMessagePtr->Len != 0); theErrorMessage.Set(inErrorMessagePtr->Ptr, inErrorMessagePtr->Len); char buff[32]; qtss_sprintf(buff,"%"_U32BITARG_"",inErrorMessagePtr->Len); (void)QTSS_AppendRTSPHeader(inRequest, qtssContentLengthHeader, buff, ::strlen(buff)); } //send the response header. In all situations where errors could happen, we //don't really care, cause there's nothing we can do anyway! (void)QTSS_SendRTSPHeaders(inRequest); // // Now that we've formatted the message into the temporary buffer, // write it out to the request stream and the Client Session object (void)QTSS_Write(inRequest, theErrorMessage.Ptr, theErrorMessage.Len, NULL, 0); (void)QTSS_SetValue(inRequest, qtssRTSPReqRespMsg, 0, theErrorMessage.Ptr, theErrorMessage.Len); return QTSS_RequestFailed; }
QTSS_Error RereadPrefs() { delete [] sVersionHeader; sVersionHeader = QTSSModuleUtils::GetStringAttribute(sServer, "qtssSvrRTSPServerHeader", kDefaultHeader); delete [] sIPAccessList; sIPAccessList = QTSSModuleUtils::GetStringAttribute(sModulePrefs, "IPAccessList", sLocalLoopBackAddress); sIPAccessListID = QTSSModuleUtils::GetAttrID(sModulePrefs, "IPAccessList"); QTSSModuleUtils::GetAttribute(sModulePrefs, "Authenticate", qtssAttrDataTypeBool16, &sAuthenticationEnabled, &sDefaultAuthenticationEnabled, sizeof(sAuthenticationEnabled)); QTSSModuleUtils::GetAttribute(sModulePrefs, "LocalAccessOnly", qtssAttrDataTypeBool16, &sLocalLoopBackOnlyEnabled, &sDefaultLocalLoopBackOnlyEnabled, sizeof(sLocalLoopBackOnlyEnabled)); QTSSModuleUtils::GetAttribute(sModulePrefs, "RequestTimeIntervalMilli", qtssAttrDataTypeUInt32, &sRequestTimeIntervalMilli, &sDefaultRequestTimeIntervalMilli, sizeof(sRequestTimeIntervalMilli)); QTSSModuleUtils::GetAttribute(sModulePrefs, "enable_remote_admin", qtssAttrDataTypeBool16, &sEnableRemoteAdmin, &sDefaultEnableRemoteAdmin, sizeof(sDefaultEnableRemoteAdmin)); QTSSModuleUtils::GetAttribute(sModulePrefs, "http_port", qtssAttrDataTypeUInt16, &sHttpPort, &sDefaultHttpPort, sizeof(sHttpPort)); delete [] sDocumentRoot; sDocumentRoot = QTSSModuleUtils::GetStringAttribute(sModulePrefs, "document_root", sDefaultDocumentRoot); delete [] sAdministratorGroup; sAdministratorGroup = QTSSModuleUtils::GetStringAttribute(sModulePrefs, "AdministratorGroup", sDefaultAdministratorGroup); if (sRequestTimeIntervalMilli > kMaxRequestTimeIntervalMilli) { sRequestTimeIntervalMilli = kMaxRequestTimeIntervalMilli; } (void)QTSS_SetValue(sModule, qtssModDesc, 0, sDesc, strlen(sDesc)+1); (void)QTSS_SetValue(sModule, qtssModVersion, 0, &sVersion, sizeof(sVersion)); return QTSS_NoErr; }
QTSS_Error OpenFile(QTSS_OpenFile_Params* inParams) { OSFileSource* theFileSource = NEW OSFileSource(inParams->inPath); UInt64 theLength = theFileSource->GetLength(); // // OSFileSource returns mod date as a time_t. // This is the same as a QTSS_TimeVal, except the latter is in msec QTSS_TimeVal theModDate = (QTSS_TimeVal)theFileSource->GetModDate(); theModDate *= 1000; // // Check to see if the file actually exists if (theLength == 0) { delete theFileSource; return QTSS_FileNotFound; } // // Add this new file source object to the file object QTSS_Error theErr = QTSS_SetValue(inParams->inFileObject, sOSFileSourceAttr, 0, &theFileSource, sizeof(theFileSource)); if (theErr != QTSS_NoErr) { delete theFileSource; return QTSS_RequestFailed; } // // If caller wants async I/O, at this point we should set up the EventContext if (inParams->inFlags & qtssOpenFileAsync) { EventContext* theEventContext = NEW EventContext(EventContext::kInvalidFileDesc, Socket::GetEventThread()); theEventContext->InitNonBlocking(theFileSource->GetFD()); theErr = QTSS_SetValue(inParams->inFileObject, sEventContextAttr, 0, &theEventContext, sizeof(theEventContext)); if (theErr != QTSS_NoErr) { delete theFileSource; delete theEventContext; return QTSS_RequestFailed; } } // // Set up the other attribute values in the file object (void)QTSS_SetValue(inParams->inFileObject, qtssFlObjLength, 0, &theLength, sizeof(theLength)); (void)QTSS_SetValue(inParams->inFileObject, qtssFlObjModDate, 0, &theModDate, sizeof(theModDate)); return QTSS_NoErr; }
QTSS_Error AuthorizeAdminRequest(QTSS_RTSPRequestObject request) { Bool16 allowed = false; // get the resource path // if the path does not match the admin path, don't handle the request char* resourcePath = QTSSModuleUtils::GetLocalPath_Copy(request); OSCharArrayDeleter resourcePathDeleter(resourcePath); if(strcmp(sAuthResourceLocalPath, resourcePath) != 0) return QTSS_NoErr; // get the type of request QTSS_ActionFlags action = QTSSModuleUtils::GetRequestActions(request); if(!(action & qtssActionFlagsAdmin)) return QTSS_RequestFailed; QTSS_UserProfileObject theUserProfile = QTSSModuleUtils::GetUserProfileObject(request); if (NULL == theUserProfile) return QTSS_RequestFailed; (void) QTSS_SetValue(request,qtssRTSPReqURLRealm, 0, sAuthRealm, ::strlen(sAuthRealm)); // Authorize the user if the user belongs to the AdministratorGroup (this is an admin module pref) UInt32 numGroups = 0; char** groupsArray = QTSSModuleUtils::GetGroupsArray_Copy(theUserProfile, &numGroups); if ((groupsArray != NULL) && (numGroups != 0)) { UInt32 index = 0; for (index = 0; index < numGroups; index++) { if(strcmp(sAdministratorGroup, groupsArray[index]) == 0) { allowed = true; break; } } // delete the memory allocated in QTSSModuleUtils::GetGroupsArray_Copy call delete [] groupsArray; } if(!allowed) { if (QTSS_NoErr != QTSS_SetValue(request,qtssRTSPReqUserAllowed, 0, &allowed, sizeof(allowed))) return QTSS_RequestFailed; // Bail on the request. The Server will handle the error } return QTSS_NoErr; }
/* Content报文读取与解析 同步进行报文处理,构造回复报文 */ QTSS_Error CServiceSession::SetupRequest() { //解析请求报文 QTSS_Error theErr = fRequest->Parse(); if (theErr != QTSS_NoErr) return QTSS_BadArgument; QTSS_RTSPStatusCode statusCode = qtssSuccessOK; char *body = NULL; UInt32 bodySizeBytes = 0; //获取具体Content json数据部分 //1、获取json部分长度 StrPtrLen* lengthPtr = fRequest->GetHeaderValue(httpContentLengthHeader); StringParser theContentLenParser(lengthPtr); theContentLenParser.ConsumeWhitespace(); UInt32 content_length = theContentLenParser.ConsumeInteger(NULL); qtss_printf("ServiceSession read content-length:%d \n", content_length); if (content_length <= 0) return QTSS_BadArgument; // // Check for the existence of 2 attributes in the request: a pointer to our buffer for // the request body, and the current offset in that buffer. If these attributes exist, // then we've already been here for this request. If they don't exist, add them. UInt32 theBufferOffset = 0; char* theRequestBody = NULL; UInt32 theLen = 0; theLen = sizeof(theRequestBody); theErr = QTSS_GetValue(this, qtssEasySesContentBody, 0, &theRequestBody, &theLen); if (theErr != QTSS_NoErr) { // First time we've been here for this request. Create a buffer for the content body and // shove it in the request. theRequestBody = NEW char[content_length + 1]; memset(theRequestBody,0,content_length + 1); theLen = sizeof(theRequestBody); theErr = QTSS_SetValue(this, qtssEasySesContentBody, 0, &theRequestBody, theLen);// SetValue creates an internal copy. Assert(theErr == QTSS_NoErr); // Also store the offset in the buffer theLen = sizeof(theBufferOffset); theErr = QTSS_SetValue(this, qtssEasySesContentBodyOffset, 0, &theBufferOffset, theLen); Assert(theErr == QTSS_NoErr); }
void InitializeDictionaryItems(QTSS_RTPStreamObject inStream) { UInt32* theValue = NULL; UInt32 theValueLen = 0; QTSS_Error theErr = QTSS_GetValuePtr(inStream, sNumLossesAboveTolAttr, 0, (void**)&theValue, &theValueLen); if (theErr != QTSS_NoErr) { // The dictionary parameters haven't been initialized yet. Just set them all to 0. (void)QTSS_SetValue(inStream, sNumLossesAboveTolAttr, 0, &theValueLen, sizeof(theValueLen)); (void)QTSS_SetValue(inStream, sNumLossesBelowTolAttr, 0, &theValueLen, sizeof(theValueLen)); (void)QTSS_SetValue(inStream, sNumWorsesAttr, 0, &theValueLen, sizeof(theValueLen)); } }
QTSS_Error DoPlay(QTSS_StandardRTSP_Params* inParams, ReflectorSession* inSession) { QTSS_Error theErr = QTSS_NoErr; UInt32 flags = 0; UInt32 theLen = 0; if (inSession == NULL) // it is a broadcast session so store the broadcast session. return QTSS_RequestFailed; else { UInt32 bitsPerSecond = inSession->GetBitRate(); (void)QTSS_SetValue(inParams->inClientSession, qtssCliSesMovieAverageBitRate, 0, &bitsPerSecond, sizeof(bitsPerSecond)); QTSS_Error theErr = QTSS_Play(inParams->inClientSession, inParams->inRTSPRequest, qtssPlayFlagsAppendServerInfo); if (theErr != QTSS_NoErr) return theErr; } OSRef* theRelaySessionRef = sClientSessionMap->Resolve(inSession->GetRef()->GetString()); if(theRelaySessionRef != NULL) { RTSPRelaySession* relaySes = (RTSPRelaySession*)theRelaySessionRef->GetObject(); QTSS_Error err = relaySes->Start(); sClientSessionMap->Release(theRelaySessionRef); } else { return QTSSModuleUtils::SendErrorResponse(inParams->inRTSPRequest, qtssServerInternal, 0); } (void)QTSS_SendStandardRTSPResponse(inParams->inRTSPRequest, inParams->inClientSession, flags); return QTSS_NoErr; }
Bool16 IsAuthentic(QTSS_Filter_Params* inParams,StringParser *fullRequestPtr) { Bool16 isAuthentic = false; if (!sAuthenticationEnabled) // no authentication { isAuthentic = true; } else // must authenticate { StrPtrLen theClientIPAddressStr; (void) QTSS_GetValuePtr(inParams->inRTSPSession, qtssRTSPSesRemoteAddrStr, 0, (void**)&theClientIPAddressStr.Ptr, &theClientIPAddressStr.Len); Bool16 isLocal = IPComponentStr(&theClientIPAddressStr).IsLocal(); StrPtrLen authenticateName; StrPtrLen authenticatePassword; StrPtrLen authType; Bool16 hasAuthentication = HasAuthentication(fullRequestPtr,&authenticateName,&authenticatePassword, &authType); if (hasAuthentication) { if (authType.Equal(sAuthRef)) { if (isLocal) isAuthentic = OSXAuthenticate(&authenticatePassword); } else isAuthentic = Authenticate(inParams->inRTSPRequest, &authenticateName,&authenticatePassword); } } // if (isAuthentic) // isAuthentic = AuthorizeAdminRequest(inParams->inRTSPRequest); (void) QTSS_SetValue(inParams->inRTSPRequest, sAuthenticatedID, 0, (void*)&isAuthentic, sizeof(isAuthentic)); return isAuthentic; }
/** * For the given RTSP session, will return true if the client is already flagged * as authenticated, false if they arent. if the value is not initialized, this * method will intitialize it. This is used to ensure a session is only authenticated * once. */ static Bool16 IsRTSPSessionAuthenticated(QTSS_RTSPSessionObject* theRTSPSession) { printf("QTSSIcecastAuthModule::IsRTSPSessionAuthenticated method start\n"); Bool16* alreadyAuthenticated = false; UInt32 theLen = 0; QTSS_Error getAlreadyAuthError = QTSS_GetValuePtr(*theRTSPSession, attrRtspSessionAuthenticated, 0, (void**)&alreadyAuthenticated, &theLen); //printf("QTSSIcecastAuthModule::IsRTSPSessionAuthenticated read value of already aythenticated: &i\n", alreadyAuthenticated); if (getAlreadyAuthError == QTSS_ValueNotFound) { // the value hasn't been set yet. initialize it to false, and return false. // TODO - check how to set a default variable (if possible), so we don't have to rely on this. Bool16 authenticated = false; (void)QTSS_SetValue(*theRTSPSession, attrRtspSessionAuthenticated, 0, &authenticated, sizeof(authenticated)); // we had to initialize, so def. not logged in return false; } else if (*alreadyAuthenticated) { // we are already logged in printf("QTSSIcecastAuthModule::IsRTSPSessionAuthenticated session already authenticated\n"); return true; } else if (!*alreadyAuthenticated && getAlreadyAuthError == QTSS_NoErr) { // we are not authed and there was no error, to return return false; } else { //printf("QTSSIcecastAuthModule::RTSPFilter ERROR while looking up not logged in\n"); PrintQTSSError("QTSSIcecastAuthModule::IsRTSPSessionAuthenticated", "while looking up not logged in", getAlreadyAuthError); return false; } }
kern_return_t StopServer(int inMinutes) { //if time is -1, we're supposed to wait until all clients have disconnected if (inMinutes == -1) { QTSS_ServerState theState = qtssRefusingConnectionsState; (void)QTSS_SetValue(sServer, qtssSvrState, 0, &theState, sizeof(theState)); sGracefulShutdownInProgress = true; } else { //just set the server state to shutting down QTSS_ServerState theShutDownState = qtssShuttingDownState; (void)QTSS_SetValue(sServer, qtssSvrState, 0, &theShutDownState, sizeof(theShutDownState)); } return SCNoError; }
void QTSSModuleUtils::SetupSupportedMethods(QTSS_Object inServer, QTSS_RTSPMethod* inMethodArray, UInt32 inNumMethods) { // Report to the server that this module handles DESCRIBE, SETUP, PLAY, PAUSE, and TEARDOWN UInt32 theNumMethods = 0; (void)QTSS_GetNumValues(inServer, qtssSvrHandledMethods, &theNumMethods); for (UInt32 x = 0; x < inNumMethods; x++) (void)QTSS_SetValue(inServer, qtssSvrHandledMethods, theNumMethods++, (void*)&inMethodArray[x], sizeof(inMethodArray[x])); }
QTSS_Error Initialize(QTSS_Initialize_Params* inParams) { // Setup module utils QTSSModuleUtils::Initialize(inParams->inMessages, inParams->inServer, inParams->inErrorLogStream); // Get the server object sServer = inParams->inServer; // Get our prefs object sModule = inParams->inModule; sModulePrefs = QTSSModuleUtils::GetModulePrefsObject(sModule); // Set our version and description (void)QTSS_SetValue(sModule, qtssModDesc, 0, sDescription, ::strlen(sDescription)); (void)QTSS_SetValue(sModule, qtssModVersion, 0, &sVersion, sizeof(sVersion)); RereadPrefs(); return QTSS_NoErr; }
QTSS_Error Authorize(QTSS_StandardRTSP_Params* inParams) { static Bool16 sTrue = true; Bool16* isFirstRequest = NULL; UInt32* theIPAddr = NULL; UInt32 theLen = 0; // Only do anything if this is the first request (void)QTSS_GetValuePtr(inParams->inRTSPSession, sIsFirstRequestAttr, 0, (void**)&isFirstRequest, &theLen); if (isFirstRequest != NULL) return QTSS_NoErr; // Get the IP address of this client. (void)QTSS_GetValuePtr(inParams->inRTSPSession, qtssRTSPSesRemoteAddr, 0, (void**)&theIPAddr, &theLen); if ((theIPAddr == NULL) || (theLen != sizeof(UInt32))) { Assert(0); return QTSS_NoErr; } IPAddrTableKey theKey(*theIPAddr); // This must be atomic OSMutexLocker locker(sMutex); // Check to see if this client currently has a connection open. IPAddrTableElem* theElem = sHashTable->Map(&theKey); if (theElem == NULL) { // Client doesn't have a connetion open currently. Create a map element, // and add it into the map. theElem = NEW IPAddrTableElem(*theIPAddr); sHashTable->Add(theElem); } // Check to see if this client has too many connections open. If it does, // return an error, otherwise, allow the connection and increment the // refcount. if (theElem->GetRefCount() >= sNumConnsPerIP) return QTSSModuleUtils::SendErrorResponse(inParams->inRTSPRequest, qtssClientForbidden, sTooManyConnectionsErr); else theElem->IncrementRefCount(); // Mark the request so we'll know subsequent ones aren't the first. // Note that we only do this if we've successfully added this client to our map. // That way, we only remove it in SessionClosing if we've added it. (void)QTSS_SetValue(inParams->inRTSPSession, sIsFirstRequestAttr, 0, &sTrue, sizeof(sTrue)); return QTSS_NoErr; }
void RTPSessionOutput::InitializeStreams() { UInt32 theLen = 0; QTSS_RTPStreamObject* theStreamPtr = NULL; UInt32 packetCountInitValue = 0; for (SInt16 z = 0; QTSS_GetValuePtr(fClientSession, qtssCliSesStreamObjects, z, (void**)&theStreamPtr, &theLen) == QTSS_NoErr; z++) { (void) QTSS_SetValue(*theStreamPtr, sStreamPacketCountAttr, 0, &packetCountInitValue, sizeof(UInt32)); } }
QTSS_Error PostProcess(QTSS_StandardRTSP_Params* inParams) { static UInt32 sZero = 0; UInt32* theStatus = NULL; UInt32 theLen = 0; QTSS_Error theErr = QTSS_GetValuePtr(inParams->inRTSPRequest, qtssRTSPReqRealStatusCode, 0, (void**)&theStatus, &theLen); if (theErr != QTSS_NoErr) return theErr; QTSS_CliSesClosingReason theReason = qtssCliSesCloseClientTeardown; if ((*theStatus == 401) || (*theStatus == 403)) { LogRequest(inParams->inClientSession, NULL, &theReason); (void)QTSS_SetValue(inParams->inClientSession, sLoggedAuthorizationAttrID, 0, theStatus, sizeof(*theStatus)); } else (void)QTSS_SetValue(inParams->inClientSession, sLoggedAuthorizationAttrID, 0, &sZero, sizeof(sZero)); return theErr; }
inline Bool16 GetRequestAuthenticatedState(QTSS_Filter_Params* inParams) { Bool16 result = false; UInt32 paramLen = sizeof(result); QTSS_Error err = QTSS_GetValue(inParams->inRTSPRequest, sAuthenticatedID, 0, (void*)&result, ¶mLen); if(err != QTSS_NoErr) { paramLen = sizeof(result); result = false; err =QTSS_SetValue(inParams->inRTSPRequest, sAuthenticatedID, 0, (void*)&result, paramLen); } return result; }
inline Bool16 GetRequestFlushState(QTSS_Filter_Params* inParams) { Bool16 result = false; UInt32 paramLen = sizeof(result); QTSS_Error err = QTSS_GetValue(inParams->inRTSPRequest, sFlushingID, 0, (void*)&result, ¶mLen); if (err != QTSS_NoErr) { paramLen = sizeof(result); result = false; //qtss_printf("no flush val so set to false session=%"_U32BITARG_" err =%"_S32BITARG_"\n",sSessID, err); err =QTSS_SetValue(inParams->inRTSPRequest, sFlushingID, 0, (void*)&result, paramLen); //qtss_printf("QTSS_SetValue flush session=%"_U32BITARG_" err =%"_S32BITARG_"\n",sSessID, err); } return result; }
QTSS_Error HTTPSessionInterface::RegDevSession(const char* serial, UInt32 serailLen) { if((::strlen(serial) == 0) || (serailLen == 0)) return QTSS_ValueNotFound; fSessionType = qtssDeviceSession; QTSS_SetValue(this, qtssEasySesSerial, 0, serial, serailLen); fDevSerialPtr.Set( fSerial, serailLen); fDevRef.Set( fDevSerialPtr, this); OS_Error theErr = QTSServerInterface::GetServer()->GetRecordSessionMap()->Register(GetRef()); //printf("[line:%d]HTTPSessionInterface::RegDevSession theErr = %d\n",__LINE__, theErr); if(theErr == OS_NoErr) fAuthenticated = true; return theErr; }
void RunServer() { Bool16 restartServer = false; UInt32 loopCount = 0; UInt32 debugLevel = 0; Bool16 printHeader = false; Bool16 printStatus = false; //just wait until someone stops the server or a fatal error occurs. QTSS_ServerState theServerState = sServer->GetServerState(); while ((theServerState != qtssShuttingDownState) && (theServerState != qtssFatalErrorState)) { #ifdef __sgi__ OSThread::Sleep(999); #else OSThread::Sleep(1000); #endif if ((sServer->SigIntSet()) || (sServer->SigTermSet())) { // // start the shutdown process theServerState = qtssShuttingDownState; (void)QTSS_SetValue(QTSServerInterface::GetServer(), qtssSvrState, 0, &theServerState, sizeof(theServerState)); if (sServer->SigIntSet()) restartServer = true; } } //Now, make sure that the server can't do any work TaskThreadPool::RemoveThreads(); //now that the server is definitely stopped, it is safe to initate //the shutdown process delete sServer; CleanPid(false); //ok, we're ready to exit. If we're quitting because of some fatal error //while running the server, make sure to let the parent process know by //exiting with a nonzero status. Otherwise, exit with a 0 status if (theServerState == qtssFatalErrorState || restartServer) ::exit (-2);//-2 signals parent process to restart server }
kern_return_t SetRefuseConnections(QTSRefuseConnectionsRec* inRefuseConnections) { //make sure not to allow people to stop the server from refusing connections when it //is in the process of a graceful shutdown. The only way to stop this is to call //CancelStopServer if (sGracefulShutdownInProgress) return SCServerShuttingDown; QTSS_ServerState theState = qtssRunningState; UInt32 theSize = sizeof(theState); if (inRefuseConnections->refuseConnections != 0) theState = qtssRefusingConnectionsState; (void)QTSS_SetValue(sServer, qtssSvrState, 0, &theState, theSize); return SCNoError; }
QTSS_Error DestroySession(QTSS_ClientSessionClosing_Params* inParams) { ProxyClientInfo* theClient = NULL; UInt32 theLen = sizeof(theClient); QTSS_Error theErr = QTSS_GetValue(inParams->inClientSession, sProxyClientInfoAttr, 0, &theClient, &theLen); if (theErr != QTSS_NoErr) return theErr; delete theClient; // // NULL out the attribute so in case there is a race condition no one will // get this dangling pointer (void)QTSS_SetValue(inParams->inClientSession, sProxyClientInfoAttr, 0, NULL, 0); return QTSS_NoErr; }
QTSS_Error RelaySession::SetupRelaySession(SourceInfo* inInfo) { QTSS_Error theErr = QTSS_NoErr; theErr = this->SetupReflectorSession(inInfo, NULL); if (theErr != QTSS_NoErr) return theErr; // create the reflector session object for this session UInt32 outIndex = 0; fRelaySessionObject = NULL; theErr = QTSS_LockObject(relayModuleAttributesObject); Assert(theErr == QTSS_NoErr); theErr = QTSS_CreateObjectValue (relayModuleAttributesObject , sRelaySessionObjectID, qtssRelaySessionObjectType, &outIndex, &fRelaySessionObject); Assert(theErr == QTSS_NoErr); if (fRelaySessionObject == NULL) return theErr; // set the values for all the static attributes in this session char* relayName = inInfo->Name(); // name of the relay if (relayName != NULL) theErr = QTSS_SetValue (fRelaySessionObject, sRelayName, 0, (void*)relayName, ::strlen(relayName)); else theErr = QTSS_SetValue (fRelaySessionObject, sRelayName, 0, (void*)sEmptyStr.Ptr, sEmptyStr.Len); Assert(theErr == QTSS_NoErr); StrPtrLen sourceStr; // type of source if (inInfo->IsRTSPSourceInfo()) { if (((RTSPSourceInfo*)inInfo)->IsAnnounce()) sourceStr.Set(sAnnouncedSourceStr.Ptr, sAnnouncedSourceStr.Len); else sourceStr.Set(sRTSPSourceStr.Ptr, sRTSPSourceStr.Len); } else sourceStr.Set(sUDPSourceStr.Ptr, sUDPSourceStr.Len); theErr = QTSS_SetValue (fRelaySessionObject, sSourceType, 0, (void*)sourceStr.Ptr, sourceStr.Len); Assert(theErr == QTSS_NoErr); char theIPAddrBuf[20]; StrPtrLen theIPAddr(theIPAddrBuf, 20); struct in_addr theSrcAddr; // source ip address theSrcAddr.s_addr = htonl(inInfo->GetStreamInfo(0)->fSrcIPAddr); SocketUtils::ConvertAddrToString(theSrcAddr, &theIPAddr); theErr = QTSS_SetValue (fRelaySessionObject, sSourceIPAddr, 0, (void*)theIPAddr.Ptr, theIPAddr.Len); Assert(theErr == QTSS_NoErr); struct in_addr theDestAddr; // dest (of source) ip address theDestAddr.s_addr = htonl(inInfo->GetStreamInfo(0)->fDestIPAddr); SocketUtils::ConvertAddrToString(theDestAddr, &theIPAddr); theErr = QTSS_SetValue (fRelaySessionObject, sSourceInIPAddr, 0, (void*)theIPAddr.Ptr, theIPAddr.Len); Assert(theErr == QTSS_NoErr); for (UInt32 index = 0; index < (inInfo->GetNumStreams()); index++) // source udp ports { UInt16 udpPort = inInfo->GetStreamInfo(index)->fPort; theErr = QTSS_SetValue (fRelaySessionObject, sSourceUDPPorts, index, &udpPort, sizeof(udpPort)); Assert(theErr == QTSS_NoErr); } if (inInfo->IsRTSPSourceInfo()) { RTSPSourceInfo* rtspInfo = (RTSPSourceInfo*)inInfo; if (!rtspInfo->IsAnnounce()) { UInt16 rtspPort = (UInt16) rtspInfo->GetHostPort(); char* username = rtspInfo->GetUsername(); char* password = rtspInfo->GetPassword(); theErr = QTSS_SetValue (fRelaySessionObject, sSourceRTSPPort, 0, &rtspPort, sizeof(rtspPort)); // source rtsp port Assert(theErr == QTSS_NoErr); theErr = QTSS_SetValue (fRelaySessionObject, sSourceUsername, 0, username, sizeof(username)); // source username Assert(theErr == QTSS_NoErr); theErr = QTSS_SetValue (fRelaySessionObject, sSourcePassword, 0, password, sizeof(password)); // source password Assert(theErr == QTSS_NoErr); } char* url = rtspInfo->GetSourceURL(); theErr = QTSS_SetValue (fRelaySessionObject, sSourceURL, 0, url, ::strlen(url)); Assert(theErr == QTSS_NoErr); // source url } UInt16 ttl = inInfo->GetStreamInfo(0)->fTimeToLive; theErr = QTSS_SetValue (fRelaySessionObject, sSourceTTL, 0, &ttl, sizeof(ttl)); // source ttl Assert(theErr == QTSS_NoErr); theErr = QTSS_UnlockObject(relayModuleAttributesObject); Assert(theErr == QTSS_NoErr); return QTSS_NoErr; }
void RTPSessionOutput::TearDown() { QTSS_CliSesTeardownReason reason = qtssCliSesTearDownBroadcastEnded; (void)QTSS_SetValue(fClientSession, qtssCliTeardownReason, 0, &reason, sizeof(reason)); (void)QTSS_Teardown(fClientSession); }
// this routine is not used Bool16 RTPSessionOutput::PacketShouldBeThinned(QTSS_RTPStreamObject inStream, StrPtrLen* inPacket) { return false; // function is disabled. static UInt16 sZero = 0; //This function determines whether the packet should be dropped. //It also adjusts the sequence number if necessary if (inPacket->Len < 4) return false; UInt16 curSeqNum = this->GetPacketSeqNumber(inPacket); UInt32* curQualityLevel = NULL; UInt16* nextSeqNum = NULL; UInt16* theSeqNumOffset = NULL; SInt64* lastChangeTime = NULL; UInt32 theLen = 0; (void)QTSS_GetValuePtr(inStream, qtssRTPStrQualityLevel, 0, (void**)&curQualityLevel, &theLen); if ((curQualityLevel == NULL) || (theLen != sizeof(UInt32))) return false; (void)QTSS_GetValuePtr(inStream, sNextSeqNumAttr, 0, (void**)&nextSeqNum, &theLen); if ((nextSeqNum == NULL) || (theLen != sizeof(UInt16))) { nextSeqNum = &sZero; (void)QTSS_SetValue(inStream, sNextSeqNumAttr, 0, nextSeqNum, sizeof(UInt16)); } (void)QTSS_GetValuePtr(inStream, sSeqNumOffsetAttr, 0, (void**)&theSeqNumOffset, &theLen); if ((theSeqNumOffset == NULL) || (theLen != sizeof(UInt16))) { theSeqNumOffset = &sZero; (void)QTSS_SetValue(inStream, sSeqNumOffsetAttr, 0, theSeqNumOffset, sizeof(UInt16)); } UInt16 newSeqNumOffset = *theSeqNumOffset; (void)QTSS_GetValuePtr(inStream, sLastQualityChangeAttr, 0, (void**)&lastChangeTime, &theLen); if ((lastChangeTime == NULL) || (theLen != sizeof(SInt64))) { static SInt64 startTime = 0; lastChangeTime = &startTime; (void)QTSS_SetValue(inStream, sLastQualityChangeAttr, 0, lastChangeTime, sizeof(SInt64)); } SInt64 timeNow = OS::Milliseconds(); if (*lastChangeTime == 0 || *curQualityLevel == 0) *lastChangeTime =timeNow; if (*curQualityLevel > 0 && ((*lastChangeTime + 30000) < timeNow) ) // 30 seconds between reductions { *curQualityLevel -= 1; // reduce quality value. If we quality doesn't change then we may have hit some steady state which we can't get out of without thinning or increasing the quality *lastChangeTime =timeNow; //qtss_printf("RTPSessionOutput set quality to %"_U32BITARG_"\n",*curQualityLevel); } //Check to see if we need to drop to audio only if ((*curQualityLevel >= ReflectorSession::kAudioOnlyQuality) && (*nextSeqNum == 0)) { #if REFLECTOR_THINNING_DEBUGGING || RTP_SESSION_DEBUGGING qtss_printf(" *** Reflector Dropping to audio only *** \n"); #endif //All we need to do in this case is mark the sequence number of the first dropped packet (void)QTSS_SetValue(inStream, sNextSeqNumAttr, 0, &curSeqNum, sizeof(UInt16)); *lastChangeTime =timeNow; } //Check to see if we can reinstate video if ((*curQualityLevel == ReflectorSession::kNormalQuality) && (*nextSeqNum != 0)) { //Compute the offset amount for each subsequent sequence number. This offset will //alter the sequence numbers so that they increment normally (providing the illusion to the //client that there are no missing packets) newSeqNumOffset = (*theSeqNumOffset) + (curSeqNum - (*nextSeqNum)); (void)QTSS_SetValue(inStream, sSeqNumOffsetAttr, 0, &newSeqNumOffset, sizeof(UInt16)); (void)QTSS_SetValue(inStream, sNextSeqNumAttr, 0, &sZero, sizeof(UInt16)); } //tell the caller whether to drop this packet or not. if (*curQualityLevel >= ReflectorSession::kAudioOnlyQuality) return true; else { //Adjust the sequence number of the current packet based on the offset, if any curSeqNum -= newSeqNumOffset; this->SetPacketSeqNumber(inPacket, curSeqNum); return false; } }
QTSS_Error RTPSessionOutput::WritePacket(StrPtrLen* inPacket, void* inStreamCookie, UInt32 inFlags, SInt64 packetLatenessInMSec, SInt64* timeToSendThisPacketAgain, UInt64* packetIDPtr, SInt64* arrivalTimeMSecPtr, Bool16 firstPacket) { QTSS_RTPSessionState* theState = NULL; UInt32 theLen = 0; QTSS_Error writeErr = QTSS_NoErr; SInt64 currentTime = OS::Milliseconds(); if (inPacket == NULL || inPacket->Len == 0) return QTSS_NoErr; (void)QTSS_GetValuePtr(fClientSession, qtssCliSesState, 0, (void**)&theState, &theLen); if (theLen == 0 || theState == NULL || *theState != qtssPlayingState) { //qtss_printf("QTSS_WouldBlock *theState=%d qtssPlayingState=%d\n", *theState , qtssPlayingState); return QTSS_WouldBlock; } //make sure all RTP streams with this ID see this packet QTSS_RTPStreamObject *theStreamPtr = NULL; for (UInt32 z = 0; QTSS_GetValuePtr(fClientSession, qtssCliSesStreamObjects, z, (void**)&theStreamPtr, &theLen) == QTSS_NoErr; z++) { if (this->PacketMatchesStream(inStreamCookie, theStreamPtr)) { if ( (inFlags & qtssWriteFlagsIsRTP) && this->FilterPacket(theStreamPtr, inPacket) ) return QTSS_NoErr; // keep looking at packets if (this->PacketAlreadySent(theStreamPtr,inFlags, packetIDPtr)) return QTSS_NoErr; // keep looking at packets if (!this->PacketReadyToSend(theStreamPtr,¤tTime, inFlags, packetIDPtr, timeToSendThisPacketAgain)) { //qtss_printf("QTSS_WouldBlock\n"); return QTSS_WouldBlock; // stop not ready to send packets now } // TrackPackets below is for re-writing the rtcps we don't use it right now-- shouldn't need to // (void) this->TrackPackets(theStreamPtr, inPacket, ¤tTime,inFlags, &packetLatenessInMSec, timeToSendThisPacketAgain, packetIDPtr,arrivalTimeMSecPtr); QTSS_PacketStruct thePacket; thePacket.packetData = inPacket->Ptr; SInt64 delayMSecs = fBufferDelayMSecs - (currentTime - *arrivalTimeMSecPtr); thePacket.packetTransmitTime = (currentTime - packetLatenessInMSec); if (fBufferDelayMSecs > 0 ) thePacket.packetTransmitTime += delayMSecs; // add buffer time where oldest buffered packet as now == 0 and newest is entire buffer time in the future. writeErr = QTSS_Write(*theStreamPtr, &thePacket, inPacket->Len, NULL, inFlags | qtssWriteFlagsWriteBurstBegin); if (writeErr == QTSS_WouldBlock) { //qtss_printf("QTSS_Write == QTSS_WouldBlock\n"); // // We are flow controlled. See if we know when flow control will be lifted and report that *timeToSendThisPacketAgain = thePacket.suggestedWakeupTime; if (firstPacket) { fBufferDelayMSecs = (currentTime - *arrivalTimeMSecPtr); //qtss_printf("firstPacket fBufferDelayMSecs =%lu \n", fBufferDelayMSecs); } } else { fLastIntervalMilliSec = currentTime - fLastPacketTransmitTime; if (fLastIntervalMilliSec > 100) //reset interval maybe first packet or it has been blocked for awhile fLastIntervalMilliSec = 5; fLastPacketTransmitTime = currentTime; if (inFlags & qtssWriteFlagsIsRTP) { (void) QTSS_SetValue (*theStreamPtr, sLastRTPPacketIDAttr, 0, packetIDPtr, sizeof(UInt64)); } else if (inFlags & qtssWriteFlagsIsRTCP) { (void) QTSS_SetValue (*theStreamPtr, sLastRTCPPacketIDAttr, 0, packetIDPtr, sizeof(UInt64)); (void) QTSS_SetValue (*theStreamPtr, sLastRTCPTransmitAttr, 0, ¤tTime, sizeof(UInt64)); } { // increment packet counts UInt32* packetCountPtr = NULL; UInt32 theLen = 0; (void) QTSS_GetValuePtr(*theStreamPtr, sStreamPacketCountAttr, 0,(void**) &packetCountPtr,&theLen); if (theLen > 0) { *packetCountPtr += 1; //printf("SET sStreamPacketCountAttr =%lu\n", *packetCountPtr); } } } } if ( writeErr != QTSS_NoErr ) break; } return writeErr; }
QTSS_Error RTPSessionOutput::TrackRTPPackets(QTSS_RTPStreamObject *theStreamPtr, StrPtrLen* inPacketStrPtr, SInt64 *currentTimePtr, UInt32 inFlags, SInt64* packetLatenessInMSec, SInt64* timeToSendThisPacketAgain, UInt64* packetIDPtr, SInt64* arrivalTimeMSecPtr) { QTSS_Error writeErr = QTSS_NoErr; Assert(inFlags & qtssWriteFlagsIsRTP); if (!(inFlags & qtssWriteFlagsIsRTP)) return QTSS_NoErr; ReflectorPacket packetContainer; packetContainer.SetPacketData(inPacketStrPtr->Ptr, inPacketStrPtr->Len); packetContainer.fIsRTCP = false; SInt64 *theTimePtr = NULL; UInt32 theLen = 0; if (QTSS_NoErr != QTSS_GetValuePtr(*theStreamPtr, sFirstRTPArrivalTimeAttr, 0, (void**)&theTimePtr, &theLen)) { UInt32 theSSRC = packetContainer.GetSSRC(packetContainer.fIsRTCP); (void) QTSS_SetValue(*theStreamPtr, sStreamSSRCAttr, 0, &theSSRC, sizeof(theSSRC)); UInt32 rtpTime = packetContainer.GetPacketRTPTime(); writeErr = QTSS_SetValue(*theStreamPtr, sFirstRTPTimeStampAttr, 0, &rtpTime, sizeof(rtpTime)); Assert(writeErr == QTSS_NoErr); writeErr = QTSS_SetValue(*theStreamPtr, sFirstRTPArrivalTimeAttr, 0, arrivalTimeMSecPtr, sizeof(SInt64)); Assert(writeErr == QTSS_NoErr); writeErr = QTSS_SetValue(*theStreamPtr, sFirstRTPCurrentTimeAttr, 0, currentTimePtr, sizeof(SInt64)); Assert(writeErr == QTSS_NoErr); UInt32 initValue = 0; writeErr = QTSS_SetValue(*theStreamPtr, sStreamByteCountAttr, 0, &initValue, sizeof(UInt32)); Assert(writeErr == QTSS_NoErr); //printf("first rtp on stream stream=%"_U32BITARG_" ssrc=%"_U32BITARG_" rtpTime=%"_U32BITARG_" arrivalTimeMSecPtr=%qd currentTime=%qd\n",(UInt32) theStreamPtr, theSSRC, rtpTime, *arrivalTimeMSecPtr, *currentTimePtr); } else { UInt32* packetCountPtr = NULL; UInt32* byteCountPtr = NULL; UInt32 theLen = 0; writeErr = QTSS_GetValuePtr(*theStreamPtr, sStreamByteCountAttr, 0, (void**) &byteCountPtr,&theLen); if (writeErr == QTSS_NoErr && theLen > 0) *byteCountPtr += inPacketStrPtr->Len - 12;// 12 header bytes UInt32* theSSRCPtr = 0; (void) QTSS_GetValuePtr(*theStreamPtr, sStreamSSRCAttr, 0, (void**)&theSSRCPtr, &theLen); if (*theSSRCPtr != packetContainer.GetSSRC(packetContainer.fIsRTCP)) { (void) QTSS_RemoveValue(*theStreamPtr,sFirstRTPArrivalTimeAttr,0); (void) QTSS_RemoveValue(*theStreamPtr,sFirstRTPTimeStampAttr,0); (void) QTSS_RemoveValue(*theStreamPtr,sFirstRTPCurrentTimeAttr,0); (void) QTSS_RemoveValue(*theStreamPtr,sStreamPacketCountAttr,0); (void) QTSS_RemoveValue(*theStreamPtr,sStreamByteCountAttr,0); fMustSynch = true; //printf("found different ssrc =%"_U32BITARG_" packetssrc=%"_U32BITARG_"\n",*theSSRCPtr, packetContainer.GetSSRC(packetContainer.fIsRTCP)); } } return writeErr; }
QTSS_Error RTPSessionOutput::TrackRTCPBaseTime(QTSS_RTPStreamObject *theStreamPtr, StrPtrLen* inPacketStrPtr, SInt64 *currentTimePtr, UInt32 inFlags, SInt64* packetLatenessInMSec, SInt64* timeToSendThisPacketAgain, UInt64* packetIDPtr, SInt64* arrivalTimeMSecPtr) { Bool16 haveBaseTime = false; Bool16 haveAllFirstRTPs = true; UInt32 streamTimeScale = 0; UInt32 theLen = sizeof(streamTimeScale); QTSS_Error writeErr = QTSS_GetValue(*theStreamPtr, qtssRTPStrTimescale, 0, (void *) &streamTimeScale, &theLen); Assert(writeErr == QTSS_NoErr); UInt32 baseTimeStamp = 0; theLen = sizeof(baseTimeStamp); if (!fMustSynch || QTSS_NoErr == QTSS_GetValue(*theStreamPtr, sBaseRTPTimeStampAttr, 0, (void*)&baseTimeStamp, &theLen) ) // we need a starting stream time that is synched { haveBaseTime = true; } else { UInt64 earliestArrivalTime = ~(UInt64) 0; //max value UInt32 firstStreamTime = 0; SInt64 firstStreamArrivalTime = 0; QTSS_RTPStreamObject *findStream = NULL; if (fMustSynch || QTSS_NoErr != QTSS_GetValuePtr(*theStreamPtr, sBaseArrivalTimeStampAttr, 0, (void**)&fBaseArrivalTime, &theLen) ) { // we don't have a base arrival time for the session see if we can set one now. for (SInt32 z = 0; QTSS_GetValuePtr(fClientSession, qtssCliSesStreamObjects, z, (void**)&findStream, &theLen) == QTSS_NoErr; z++) { SInt64* firstArrivalTimePtr = NULL; if (QTSS_NoErr != QTSS_GetValuePtr(*findStream, sFirstRTPArrivalTimeAttr, 0, (void**)&firstArrivalTimePtr, &theLen)) {// no packet on this stream yet haveAllFirstRTPs = false; // not enough info to calc a base time break; } else { // we have an arrival time see if it is the first for all streams if ( (UInt64) *firstArrivalTimePtr < earliestArrivalTime ) { earliestArrivalTime = *firstArrivalTimePtr; } } } if (haveAllFirstRTPs) // we can now create a base arrival time and base stream time from that { writeErr = QTSS_SetValue(*theStreamPtr, sBaseArrivalTimeStampAttr, 0, &earliestArrivalTime, sizeof(SInt64)); Assert(writeErr == QTSS_NoErr); fBaseArrivalTime = (SInt64) earliestArrivalTime; } } if (haveAllFirstRTPs)//sBaseRTPTimeStamp { // we don't have a base stream time but we have a base session time so calculate the base stream time. theLen = sizeof(firstStreamTime); if (QTSS_NoErr != QTSS_GetValue(*theStreamPtr, sFirstRTPTimeStampAttr, 0, (void*)&firstStreamTime, &theLen)) return QTSS_NoErr; theLen = sizeof(firstStreamArrivalTime); if (QTSS_NoErr != QTSS_GetValue(*theStreamPtr, sFirstRTPArrivalTimeAttr, 0, (void*)&firstStreamArrivalTime, &theLen)) return QTSS_NoErr; SInt64 arrivalTimeDiffMSecs = (firstStreamArrivalTime - fBaseArrivalTime);// + fBufferDelayMSecs;//add the buffer delay !! not sure about faster than real time arrival times.... UInt32 timeDiffStreamTime = (UInt32)( ( (Float64) arrivalTimeDiffMSecs/(Float64) 1000.0) * (Float64) streamTimeScale ); baseTimeStamp = firstStreamTime - timeDiffStreamTime; if (QTSS_NoErr == QTSS_SetValue(*theStreamPtr, sBaseRTPTimeStampAttr, 0, (void*)&baseTimeStamp, sizeof(baseTimeStamp))) haveBaseTime = true; (void) QTSS_SetValue(*theStreamPtr, qtssRTPStrFirstTimestamp, 0, &baseTimeStamp, sizeof(baseTimeStamp)); fMustSynch = false; //printf("fBaseArrivalTime =%qd baseTimeStamp %"_U32BITARG_" streamStartTime=%qd diff =%qd\n", fBaseArrivalTime, baseTimeStamp, firstStreamArrivalTime, arrivalTimeDiffMSecs); } } return writeErr; }
QTSS_Error ProcessRTSPRequest(QTSS_StandardRTSP_Params* inParams) { ProxyClientInfo* theClient = NULL; UInt32 theLen = sizeof(theClient); QTSS_Error theErr = QTSS_GetValue(inParams->inClientSession, sProxyClientInfoAttr, 0, &theClient, &theLen); // // If there is no client yet, this is the first request made on this session. // Create an RTSPClient if (theErr != QTSS_NoErr) { theClient = NEW ProxyClientInfo(); // // Parse out the DNS name of the origin server and the port StrPtrLen theDNSNameAndPort; theErr = QTSS_GetValuePtr(inParams->inRTSPHeaders, qtssHostHeader, 0, (void**)&theDNSNameAndPort.Ptr, &theDNSNameAndPort.Len); Assert(theErr == QTSS_NoErr); StringParser extractPortNumber(&theDNSNameAndPort); StrPtrLen theDNSNamePtr; extractPortNumber.GetThru(&theDNSNamePtr, ':'); UInt32 thePort = extractPortNumber.ConsumeInteger(NULL); // // For now, if there was no port specified, use 554 if (thePort == 0) thePort = 554; // // Make sure the port is in the range of a 2-byte integer if (thePort > 65536) return QTSSModuleUtils::SendErrorResponse(inParams->inRTSPRequest, qtssClientBadRequest, sPortNumberTooBigErr); // // gethostbyname takes a NULL terminated C-string OSCharArrayDeleter theDNSName(theDNSNamePtr.GetAsCString()); // // Do a DNS lookup on the host to find its IP address struct hostent* theHostent = ::gethostbyname(theDNSName); UInt32 theIPAddr = 0; if (theHostent != NULL) theIPAddr = ntohl(*(UInt32*)(theHostent->h_addr_list[0])); else theIPAddr = SocketUtils::ConvertStringToAddr(theDNSName); // // Give this information to the ClientSocket object theClient->GetRTSPClient()->GetSocket()->Set(theIPAddr, (UInt16)thePort); theErr = QTSS_SetValue(inParams->inClientSession, sProxyClientInfoAttr, 0, &theClient, sizeof(theClient)); Assert(theErr == QTSS_NoErr); // // Start the process of connecting to the origin server, first // just by telling the ClientSocket to send an empty message theErr = theClient->GetRTSPClient()->GetSocket()->Send(NULL, 0); if (theErr != QTSS_NoErr) // // we are connecting. This function will be called when connection is set up return HandleRTSPClientErr(inParams->inRTSPRequest, theClient, theErr); } // // If we aren't in the middle of sending a request, we have to set it up if (!theClient->GetRTSPClient()->IsTransactionInProgress()) theErr = DoRequestPreProcessing(theClient, inParams->inRTSPRequest, inParams->inClientSession); else // // Continue our attempt to send this request theErr = theClient->GetRTSPClient()->DoTransaction(); if (theErr != QTSS_NoErr) HandleRTSPClientErr(inParams->inRTSPRequest, theClient, theErr); else // // The response has come back from the origin server. Do whatever // processing we need on it, and send the response to the proxy client. theErr = DoRequestPostProcessing(theClient, inParams->inRTSPRequest, inParams->inClientSession); return theErr; }
void RelayOutput::SetupRelayOutputObject(RTSPOutputInfo* inRTSPInfo) { fRelaySessionObject = fRelaySession->GetRelaySessionObject(); UInt32 outIndex = 0; QTSS_Error theErr = QTSS_LockObject(fRelaySessionObject); Assert(theErr == QTSS_NoErr); theErr = QTSS_CreateObjectValue(fRelaySessionObject, RelaySession::sRelayOutputObject, qtssRelayOutputObjectType, &outIndex, &fRelayOutputObject); Assert(theErr == QTSS_NoErr); if ((inRTSPInfo == NULL) || !inRTSPInfo->fIsAnnounced) // output type { theErr = QTSS_SetValue(fRelayOutputObject, sOutputType, 0, (void*)sUDPDestStr.Ptr, sUDPDestStr.Len); Assert(theErr == QTSS_NoErr); } else { theErr = QTSS_SetValue(fRelayOutputObject, sOutputType, 0, (void*)sAnnouncedDestStr.Ptr, sAnnouncedDestStr.Len); // output type Assert(theErr == QTSS_NoErr); theErr = QTSS_SetValue(fRelayOutputObject, sOutputRTSPPort, 0, &inRTSPInfo->fAnnouncePort, sizeof(inRTSPInfo->fAnnouncePort)); // rtsp port Assert(theErr == QTSS_NoErr); theErr = QTSS_SetValue(fRelayOutputObject, sOutputURL, 0, (fClient->GetURL())->Ptr, (fClient->GetURL())->Len); // output url Assert(theErr == QTSS_NoErr); } char theIPAddrBuf[20]; StrPtrLen theIPAddr(theIPAddrBuf, 20); struct in_addr theDestAddr; // output destination address theDestAddr.s_addr = htonl(fOutputInfo.fDestAddr); SocketUtils::ConvertAddrToString(theDestAddr, &theIPAddr); theErr = QTSS_SetValue(fRelayOutputObject, sOutputDestAddr, 0, (void*)theIPAddr.Ptr, theIPAddr.Len); Assert(theErr == QTSS_NoErr); struct in_addr theLocalAddr; // output local address theLocalAddr.s_addr = htonl(fOutputInfo.fLocalAddr); SocketUtils::ConvertAddrToString(theLocalAddr, &theIPAddr); theErr = QTSS_SetValue(fRelayOutputObject, sOutputLocalAddr, 0, (void*)theIPAddr.Ptr, theIPAddr.Len); Assert(theErr == QTSS_NoErr); for (UInt32 index = 0; index < fNumStreams; index++) // output udp ports { UInt16 udpPort = fOutputInfo.fPortArray[index]; theErr = QTSS_SetValue(fRelayOutputObject, sOutputUDPPorts, index, &udpPort, sizeof(udpPort)); Assert(theErr == QTSS_NoErr); } theErr = QTSS_SetValue(fRelayOutputObject, sOutputTTL, 0, &(fOutputInfo.fTimeToLive), sizeof(fOutputInfo.fTimeToLive)); Assert(theErr == QTSS_NoErr); theErr = QTSS_SetValuePtr(fRelayOutputObject, sOutputCurPacketsPerSec, &fPacketsPerSecond, sizeof(fPacketsPerSecond)); Assert(theErr == QTSS_NoErr); theErr = QTSS_SetValuePtr(fRelayOutputObject, sOutputCurBitsPerSec, &fBitsPerSecond, sizeof(fBitsPerSecond)); Assert(theErr == QTSS_NoErr); theErr = QTSS_SetValuePtr(fRelayOutputObject, sOutputTotalPacketsSent, &fTotalPacketsSent, sizeof(fTotalPacketsSent)); Assert(theErr == QTSS_NoErr); theErr = QTSS_SetValuePtr(fRelayOutputObject, sOutputTotalBytesSent, &fTotalBytesSent, sizeof(fTotalBytesSent)); Assert(theErr == QTSS_NoErr); theErr = QTSS_UnlockObject(fRelaySessionObject); Assert(theErr == QTSS_NoErr); }