/* 用当前RTSPSession构造一个OSRef实例, 在RTPSession Map(Hash表)中注册并加入该引用OSRef元(其key值唯一),
同时更新qtssSvrClientSessions的属性,及QTSServerInterface中的总RTPSession数 */
QTSS_Error  RTPSession::Activate(const StrPtrLen& inSessionID)
{
    //Set the session ID for this session

	/* 用入参配置fRTSPSessionIDBuf的值(是C-String) */
    Assert(inSessionID.Len <= QTSS_MAX_SESSION_ID_LENGTH);
    ::memcpy(fRTSPSessionIDBuf, inSessionID.Ptr, inSessionID.Len);
    fRTSPSessionIDBuf[inSessionID.Len] = '\0';

	/* 用C-String的fRTSPSessionIDBuf设置qtssCliSesRTSPSessionID的属性值 */
    this->SetVal(qtssCliSesRTSPSessionID, &fRTSPSessionIDBuf[0], inSessionID.Len);
    
	/* 用qtssCliSesRTSPSessionID的属性值来得到一个RTPSession Map的引用OSRef元 */
    fRTPMapElem.Set(*this->GetValue(qtssCliSesRTSPSessionID), this);
    
	/* 获取服务器接口 */
    QTSServerInterface* theServer = QTSServerInterface::GetServer();
    
    //Activate puts the session into the RTPSession Map
	/* 在RTPSession Map(Hash表)中注册并加入一个引用OSRef,若字符串标识唯一,就能成功返回OS_NoErr;若有一个相同key值的元素,就返回错误EPERM  */
    QTSS_Error err = theServer->GetRTPSessionMap()->Register(&fRTPMapElem);
	//若有同名键值,立即返回
    if (err == EPERM)
        return err;

	/* 确保key值唯一 */
    Assert(err == QTSS_NoErr);
    
    //
    // Adding this session into the qtssSvrClientSessions attr and incrementing the number of sessions must be atomic
	/* 锁定服务器对象 */
    OSMutexLocker locker(theServer->GetMutex()); 

    //
    // Put this session into the qtssSvrClientSessions attribute of the server
#if DEBUG
    Assert(theServer->GetNumValues(qtssSvrClientSessions) == theServer->GetNumRTPSessions());//确保属性qtssSvrClientSessions中的RTPSession个数和服务器中实际的个数相同
#endif
	/* 设置qtssSvrClientSessions的第GetNumRTPSessions()个RTPSession的属性 */
    RTPSession* theSession = this;
    err = theServer->SetValue(qtssSvrClientSessions, theServer->GetNumRTPSessions(), &theSession, sizeof(theSession), QTSSDictionary::kDontObeyReadOnly);
    Assert(err == QTSS_NoErr);
    
#if DEBUG
    fActivateCalled = true;
#endif
	/* 及时更新QTSServerInterface中的总RTPSession数  */
    QTSServerInterface::GetServer()->IncrementTotalRTPSessions();
    return QTSS_NoErr;
}
QTSS_Error  RTPSession::Activate(const StrPtrLen& inSessionID)
{
    //Set the session ID for this session
    Assert(inSessionID.Len <= QTSS_MAX_SESSION_ID_LENGTH);
    ::memcpy(fRTSPSessionIDBuf, inSessionID.Ptr, inSessionID.Len);
    fRTSPSessionIDBuf[inSessionID.Len] = '\0';
    this->SetVal(qtssCliSesRTSPSessionID, &fRTSPSessionIDBuf[0], inSessionID.Len);
    
    fRTPMapElem.Set(*this->GetValue(qtssCliSesRTSPSessionID), this);
    
    QTSServerInterface* theServer = QTSServerInterface::GetServer();
    
    //Activate puts the session into the RTPSession Map
    QTSS_Error err = theServer->GetRTPSessionMap()->Register(&fRTPMapElem);
    if (err == EPERM)
        return err;
    Assert(err == QTSS_NoErr);
    
    //
    // Adding this session into the qtssSvrClientSessions attr and incrementing the number of sessions must be atomic
    OSMutexLocker locker(theServer->GetMutex()); 

    //
    // Put this session into the qtssSvrClientSessions attribute of the server
#if DEBUG
    Assert(theServer->GetNumValues(qtssSvrClientSessions) == theServer->GetNumRTPSessions());
#endif
    RTPSession* theSession = this;
    err = theServer->SetValue(qtssSvrClientSessions, theServer->GetNumRTPSessions(), &theSession, sizeof(theSession), QTSSDictionary::kDontObeyReadOnly);
    Assert(err == QTSS_NoErr);
    
#if DEBUG
    fActivateCalled = true;
#endif
    QTSServerInterface::GetServer()->IncrementTotalRTPSessions();
    return QTSS_NoErr;
}
Beispiel #3
0
void WINAPI ServiceControl(DWORD inControlCode)
{
	QTSS_ServerState theState;
	QTSServerInterface* theServer = QTSServerInterface::GetServer();
	DWORD theStatusReport = SERVICE_START_PENDING;

	if (theServer != NULL)
		theState = theServer->GetServerState();
	else
		theState = qtssStartingUpState;

	switch (inControlCode)
	{
		// Stop the service.
		//
	case SERVICE_CONTROL_STOP:
	case SERVICE_CONTROL_SHUTDOWN:
		{
			if (theState == qtssStartingUpState)
				break;

			//
			// Signal the server to shut down.
			theState = qtssShuttingDownState;
			if (theServer != NULL)
				theServer->SetValue(qtssSvrState, 0, &theState, sizeof(theState));
			break;
		}
	case SERVICE_CONTROL_PAUSE:
		{
			if (theState != qtssRunningState)
				break;

			//
			// Signal the server to refuse new connections.
			theState = qtssRefusingConnectionsState;
			if (theServer != NULL)
				theServer->SetValue(qtssSvrState, 0, &theState, sizeof(theState));
			break;
		}
	case SERVICE_CONTROL_CONTINUE:
		{
			if (theState != qtssRefusingConnectionsState)
				break;

			//
			// Signal the server to refuse new connections.
			theState = qtssRefusingConnectionsState;
			if (theServer != NULL)
				theServer->SetValue(qtssSvrState, 0, &theState, sizeof(theState));
			break;
		}
	case SERVICE_CONTROL_INTERROGATE:
		break; // Just update our status

	default:
		break;
	}

	if (theServer != NULL)
	{
		theState = theServer->GetServerState();

		//
		// Convert a QTSS state to a Win32 Service state
		switch (theState)
		{
		case qtssStartingUpState:           theStatusReport = SERVICE_START_PENDING;    break;
		case qtssRunningState:              theStatusReport = SERVICE_RUNNING;          break;
		case qtssRefusingConnectionsState:  theStatusReport = SERVICE_PAUSED;           break;
		case qtssFatalErrorState:           theStatusReport = SERVICE_STOP_PENDING;     break;
		case qtssShuttingDownState:         theStatusReport = SERVICE_STOP_PENDING;     break;
		default:                            theStatusReport = SERVICE_RUNNING;          break;
		}
	}
	else
		theStatusReport = SERVICE_START_PENDING;

	qtss_printf("Reporting status from ServiceControl function\n");
	::ReportStatus(theStatusReport, NO_ERROR);
}
SInt64 RTPStatsUpdaterTask::Run()
{

    QTSServerInterface* theServer = QTSServerInterface::sServer;
    
    // All of this must happen atomically wrt dictionary values we are manipulating
    OSMutexLocker locker(&theServer->fMutex);
    
    //First update total bytes. This must be done because total bytes is a 64 bit number,
    //so no atomic functions can apply.
    //
    // NOTE: The line below is not thread safe on non-PowerPC platforms. This is
    // because the fPeriodicRTPBytes variable is being manipulated from within an
    // atomic_add. On PowerPC, assignments are atomic, so the assignment below is ok.
    // On a non-PowerPC platform, the following would be thread safe:
    //unsigned int periodicBytes = atomic_add(&theServer->fPeriodicRTPBytes, 0);
    unsigned int periodicBytes = theServer->fPeriodicRTPBytes;
    (void)atomic_sub(&theServer->fPeriodicRTPBytes, periodicBytes);
    theServer->fTotalRTPBytes += periodicBytes;
    
    // Same deal for packet totals
    unsigned int periodicPackets = theServer->fPeriodicRTPPackets;
    (void)atomic_sub(&theServer->fPeriodicRTPPackets, periodicPackets);
    theServer->fTotalRTPPackets += periodicPackets;
    
    // ..and for lost packet totals
    unsigned int periodicPacketsLost = theServer->fPeriodicRTPPacketsLost;
    (void)atomic_sub(&theServer->fPeriodicRTPPacketsLost, periodicPacketsLost);
    theServer->fTotalRTPPacketsLost += periodicPacketsLost;
    
    SInt64 curTime = OS::Milliseconds();
    
    //for cpu percent
        Float32 cpuTimeInSec = GetCPUTimeInSeconds();
    
    //also update current bandwidth statistic
    if (fLastBandwidthTime != 0)
    {
        Assert(curTime > fLastBandwidthTime);
        UInt32 delta = (UInt32)(curTime - fLastBandwidthTime);
        if (delta < 1000)
            WarnV(delta >= 1000, "Timer is off");
        
        //do the bandwidth computation using floating point divides
        //for accuracy and speed.
        Float32 bits = (Float32)(periodicBytes * 8);
        Float32 theTime = (Float32)delta;
        theTime /= 1000;
        bits /= theTime;
        Assert(bits >= 0);
        theServer->fCurrentRTPBandwidthInBits = (UInt32)bits;
        
        // okay let's do it for MP3 bytes now
        bits = (Float32)(((SInt64)theServer->fTotalMP3Bytes - fLastTotalMP3Bytes) * 8);
        bits /= theTime;
        theServer->fCurrentMP3BandwidthInBits = (UInt32)bits;

        //do the same computation for packets per second
        Float32 packetsPerSecond = (Float32)periodicPackets;
        packetsPerSecond /= theTime;
        Assert(packetsPerSecond >= 0);
        theServer->fRTPPacketsPerSecond = (UInt32)packetsPerSecond;
        
        //do the computation for cpu percent
        Float32 diffTime = cpuTimeInSec - theServer->fCPUTimeUsedInSec;
        theServer->fCPUPercent = (diffTime/theTime) * 100;  
		
		UInt32 numProcessors = OS::GetNumProcessors();
		
		if (numProcessors > 1)
			theServer->fCPUPercent /= numProcessors;
    }
    
    fLastTotalMP3Bytes = (SInt64)theServer->fTotalMP3Bytes;
    fLastBandwidthTime = curTime;
    // We use a running average for avg. bandwidth calculations
    theServer->fAvgMP3BandwidthInBits = (theServer->fAvgMP3BandwidthInBits
            + theServer->fCurrentMP3BandwidthInBits)/2; 
    
    //for cpu percent
    theServer->fCPUTimeUsedInSec    = cpuTimeInSec; 
    
    //also compute average bandwidth, a much more smooth value. This is done with
    //the fLastBandwidthAvg, a timestamp of the last time we did an average, and
    //fLastBytesSent, the number of bytes sent when we last did an average.
    if ((fLastBandwidthAvg != 0) && (curTime > (fLastBandwidthAvg +
        (theServer->GetPrefs()->GetAvgBandwidthUpdateTimeInSecs() * 1000))))
    {
        UInt32 delta = (UInt32)(curTime - fLastBandwidthAvg);
        SInt64 bytesSent = theServer->fTotalRTPBytes - fLastBytesSent;
        Assert(bytesSent >= 0);
        
        //do the bandwidth computation using floating point divides
        //for accuracy and speed.
        Float32 bits = (Float32)(bytesSent * 8);
        Float32 theAvgTime = (Float32)delta;
        theAvgTime /= 1000;
        bits /= theAvgTime;
        Assert(bits >= 0);
        theServer->fAvgRTPBandwidthInBits = (UInt32)bits;

        fLastBandwidthAvg = curTime;
        fLastBytesSent = theServer->fTotalRTPBytes;
        
        //if the bandwidth is above the bandwidth setting, disconnect 1 user by sending them
        //a BYE RTCP packet.
        SInt32 maxKBits = theServer->GetPrefs()->GetMaxKBitsBandwidth();
        if ((maxKBits > -1) && (theServer->fAvgRTPBandwidthInBits > ((UInt32)maxKBits * 1024)))
        {
            //we need to make sure that all of this happens atomically wrt the session map
            OSMutexLocker locker(theServer->GetRTPSessionMap()->GetMutex());
            RTPSessionInterface* theSession = this->GetNewestSession(theServer->fRTPMap);
            if (theSession != NULL)
                if ((curTime - theSession->GetSessionCreateTime()) <
                        theServer->GetPrefs()->GetSafePlayDurationInSecs() * 1000)
                    theSession->Signal(Task::kKillEvent);
        }
    }
    else if (fLastBandwidthAvg == 0)
    {
        fLastBandwidthAvg = curTime;
        fLastBytesSent = theServer->fTotalRTPBytes;
    }
    
    (void)this->GetEvents();//we must clear the event mask!
    return theServer->GetPrefs()->GetTotalBytesUpdateTimeInSecs() * 1000;
}
Beispiel #5
0
QTSS_Error QTSServer::RereadPrefsService(QTSS_ServiceFunctionArgsPtr /*inArgs*/)
{
    //
    // This function can only be called safely when the server is completely running.
    // Ensuring this is a bit complicated because of preemption. Here's how it's done...
    
    QTSServerInterface* theServer = QTSServerInterface::GetServer();
    
    // This is to make sure this function isn't being called before the server is
    // completely started up.
    if ((theServer == NULL) || (theServer->GetServerState() != qtssRunningState))
        return QTSS_OutOfState;

    // Because the server must have started up, and because this object always stays
    // around (until the process dies), we can now safely get this object.
    QTSServerPrefs* thePrefs = theServer->GetPrefs();
    
    // Grab the prefs mutex. We want to make sure that calls to RereadPrefsService
    // are serialized. This also prevents the server from shutting down while in
    // this function, because the QTSServer destructor grabs this mutex as well.
    OSMutexLocker locker(thePrefs->GetMutex());
    
    // Finally, check the server state again. The state may have changed
    // to qtssShuttingDownState or qtssFatalErrorState in this time, though
    // at this point we have the prefs mutex, so we are guarenteed that the
    // server can't actually shut down anymore
    if (theServer->GetServerState() != qtssRunningState)
        return QTSS_OutOfState;
    
    // Ok, we're ready to reread preferences now.
    
    //
    // Reread preferences
    sPrefsSource->Parse();
    thePrefs->RereadServerPreferences(true);
    
    // Delete all the streams
    QTSSModule** theModule = NULL;
    UInt32 theLen = 0;
    
    for (int y = 0; QTSServerInterface::GetServer()->GetValuePtr(qtssSvrModuleObjects, y, (void**)&theModule, &theLen) == QTSS_NoErr; y++)
    {
        Assert(theModule != NULL);
        Assert(theLen == sizeof(QTSSModule*));
        
        (*theModule)->GetPrefsDict()->RereadPreferences();

#if DEBUG
        theModule = NULL;
        theLen = 0;
#endif
    }
    
    //
    // Go through each module's prefs object and have those reread as well

    //
    // Now that we are done rereading the prefs, invoke all modules in the RereadPrefs
    // role so they can update their internal prefs caches.
    for (UInt32 x = 0; x < QTSServerInterface::GetNumModulesInRole(QTSSModule::kRereadPrefsRole); x++)
    {
        QTSSModule* theModule = QTSServerInterface::GetModule(QTSSModule::kRereadPrefsRole, x);
        (void)theModule->CallDispatch(QTSS_RereadPrefs_Role, NULL);
    }
    return QTSS_NoErr;
}
Beispiel #6
0
QTSS_Error RTSPRequest::SendDigestChallenge(UInt32 qop, StrPtrLen *nonce, StrPtrLen* opaque)
{
    QTSS_Error theErr = QTSS_NoErr;

    char challengeBuf[kAuthChallengeHeaderBufSize];
    ResizeableStringFormatter challengeFormatter(challengeBuf, kAuthChallengeHeaderBufSize);
    
    StrPtrLen realm;
    char *prefRealmPtr = NULL;
    StrPtrLen *realmPtr = this->GetValue(qtssRTSPReqURLRealm);              // Get auth realm set by the module
    if(realmPtr->Len > 0) {
        realm = *realmPtr;
    }
    else {                                                                  // If module hasn't set the realm
        QTSServerInterface* theServer = QTSServerInterface::GetServer();    // get the realm from prefs
        prefRealmPtr = theServer->GetPrefs()->GetAuthorizationRealm();      // allocates memory
        Assert(prefRealmPtr != NULL);
        if (prefRealmPtr != NULL){  
            realm.Set(prefRealmPtr, strlen(prefRealmPtr));
        }
        else {
            realm = sDefaultRealm;  
        }
    }
    
    // Creating the Challenge header
    challengeFormatter.Put(sAuthDigestStr);             // [Digest]
    challengeFormatter.PutSpace();                      // [Digest ] 
    challengeFormatter.Put(sRealmStr);                  // [Digest realm]
    challengeFormatter.Put(sEqualQuote);                // [Digest realm="]
    challengeFormatter.Put(realm);                      // [Digest realm="somerealm]
    challengeFormatter.Put(sQuoteCommaSpace);           // [Digest realm="somerealm", ]
    if(this->GetStale()) {
        challengeFormatter.Put(sStaleTrue);             // [Digest realm="somerealm", stale="true", ]
    }
    challengeFormatter.Put(sNonceStr);                  // [Digest realm="somerealm", nonce]
    challengeFormatter.Put(sEqualQuote);                // [Digest realm="somerealm", nonce="]
    challengeFormatter.Put(*nonce);                     // [Digest realm="somerealm", nonce="19723343a9fd75e019723343a9fd75e0]
    challengeFormatter.PutChar('"');                    // [Digest realm="somerealm", nonce="19723343a9fd75e019723343a9fd75e0"]
    challengeFormatter.PutTerminator();                 // [Digest realm="somerealm", nonce="19723343a9fd75e019723343a9fd75e0"\0]

    StrPtrLen challengePtr(challengeFormatter.GetBufPtr(), challengeFormatter.GetBytesWritten() - 1);
    
    this->SetValue(qtssRTSPReqDigestChallenge, 0, challengePtr.Ptr, challengePtr.Len, QTSSDictionary::kDontObeyReadOnly);
    RTSPSessionInterface* thisRTSPSession = this->GetSession();
    if (thisRTSPSession)
    {   (void)thisRTSPSession->SetValue(qtssRTSPSesLastDigestChallenge, 0, challengePtr.Ptr, challengePtr.Len,QTSSDictionary::kDontObeyReadOnly);
    }

    fStatus = qtssClientUnAuthorized;
    this->SetResponseKeepAlive(true);
    this->AppendHeader(qtssWWWAuthenticateHeader, &challengePtr);
    this->SendHeader();
    
    // deleting the memory that was allocated in GetPrefs call above
    if (prefRealmPtr != NULL)
    {   
        delete[] prefRealmPtr;  
    }
        
    return theErr;
}
Beispiel #7
0
QTSS_Error RTSPRequest::SendBasicChallenge(void)
{   
    QTSS_Error theErr = QTSS_NoErr;
    char *prefRealmPtr = NULL;
    
    do 
    {   
        char realmBuff[kRealmBuffSize] = "Basic realm=\"";
        StrPtrLen challenge(realmBuff);
        StrPtrLen whichRealm;
        
        // Get the module's realm
        StrPtrLen moduleRealm;
        theErr = this->GetValuePtr(qtssRTSPReqURLRealm, 0,  (void **) &moduleRealm.Ptr, &moduleRealm.Len);
        if ( (QTSS_NoErr == theErr) && (moduleRealm.Len > 0) )
        {
            whichRealm = moduleRealm;   
        }
        else
        {
            theErr = QTSS_NoErr;
            // Get the default realm from the config file or use the static default if config realm is not found
            QTSServerInterface* theServer = QTSServerInterface::GetServer();
            prefRealmPtr = theServer->GetPrefs()->GetAuthorizationRealm(); // allocates memory
            Assert(prefRealmPtr != NULL);
            if (prefRealmPtr != NULL)
            {   whichRealm.Set(prefRealmPtr, strlen(prefRealmPtr));
            }   
            else
            {
                whichRealm = sDefaultRealm;
            }
        }
        
        int realmLen = whichRealm.Len + challenge.Len + 2; // add 2 based on double quote char + end of string 0x00
        if (realmLen > kRealmBuffSize) // The realm is too big so use the default realm
        {   Assert(0);
            whichRealm = sDefaultRealm;
        }
        memcpy(&challenge.Ptr[challenge.Len],whichRealm.Ptr,whichRealm.Len);
        int newLen = challenge.Len + whichRealm.Len;
        
        challenge.Ptr[newLen] = '"'; // add the terminating "" this was accounted for with the size check above
        challenge.Ptr[newLen + 1] = 0;// add the 0 terminator this was accounted for with the size check above
        challenge.Len = newLen +1; // set the real size of the string excluding the 0.
        
        #if (0)
        {  // test code
            char test[256];
            
            memcpy(test,sDefaultRealm.Ptr,sDefaultRealm.Len);
            test[sDefaultRealm.Len] = 0;
            qtss_printf("the static realm =%s \n",test);
            
            OSCharArrayDeleter prefDeleter(QTSServerInterface::GetServer()->GetPrefs()->GetAuthorizationRealm());
            memcpy(test,prefDeleter.GetObject(),strlen(prefDeleter.GetObject()));
            test[strlen(prefDeleter.GetObject())] = 0;
            qtss_printf("the Pref realm =%s \n",test);

            memcpy(test,moduleRealm.Ptr,moduleRealm.Len);
            test[moduleRealm.Len] = 0;
            qtss_printf("the moduleRealm  =%s \n",test);
        
            memcpy(test,whichRealm.Ptr,whichRealm.Len);
            test[whichRealm.Len] = 0;
            qtss_printf("the challenge realm  =%s \n",test);
            
            memcpy(test,challenge.Ptr,challenge.Len);
            test[challenge.Len] = 0;
            qtss_printf("the challenge string  =%s len = %"_S32BITARG_"\n",test, challenge.Len);
        }
        #endif

        fStatus = qtssClientUnAuthorized;
        this->SetResponseKeepAlive(true);
        this->AppendHeader(qtssWWWAuthenticateHeader, &challenge);
        this->SendHeader();

    
    } while (false);
    
    if (prefRealmPtr != NULL)
    {   
        delete[] prefRealmPtr;  
    }
    
    return theErr;
}
RTPSession::~RTPSession()
{
    // Delete all the streams
    RTPStream** theStream = NULL;
    UInt32 theLen = 0;
    
	/* 假如预设值能打印RUDP信息 */
    if (QTSServerInterface::GetServer()->GetPrefs()->GetReliableUDPPrintfsEnabled())
    {
        SInt32 theNumLatePacketsDropped = 0;/* 丢弃延迟包个数 */
        SInt32 theNumResends = 0; /* 重传包个数 */
        
		/* 遍历该RTPSession的每个RTPStream,计算丢弃的过时包总数和重传包总数 */
        for (int x = 0; this->GetValuePtr(qtssCliSesStreamObjects, x, (void**)&theStream, &theLen) == QTSS_NoErr; x++)
        {
            Assert(theStream != NULL);
            Assert(theLen == sizeof(RTPStream*));
            if (*theStream != NULL)
            {
				/* 计算丢弃的过时包总数 */
                theNumLatePacketsDropped += (*theStream)->GetStalePacketsDropped();
				/* 得到重传包总数 */
                theNumResends += (*theStream)->GetResender()->GetNumResends();
            }
        }
        
		/* 得到客户端请求播放文件的Full URL */
        char* theURL = NULL;
        (void)this->GetValueAsString(qtssCliSesFullURL, 0, &theURL);
        Assert(theURL != NULL);
        /* 获得RTPBandwidthTracker类 */
        RTPBandwidthTracker* tracker = this->GetBandwidthTracker(); 
    
        qtss_printf("Client complete. URL: %s.\n",theURL);
        qtss_printf("Max congestion window: %ld. Min congestion window: %ld. Avg congestion window: %ld\n", tracker->GetMaxCongestionWindowSize(), tracker->GetMinCongestionWindowSize(), tracker->GetAvgCongestionWindowSize());
        qtss_printf("Max RTT: %ld. Min RTT: %ld. Avg RTT: %ld\n", tracker->GetMaxRTO(), tracker->GetMinRTO(), tracker->GetAvgRTO());
        qtss_printf("Num resends: %ld. Num skipped frames: %ld. Num late packets dropped: %ld\n", theNumResends, this->GetFramesSkipped(), theNumLatePacketsDropped);
        
        delete [] theURL;
    }
    
	/* 遍历该RTPSession的每个RTPStream,逐一删除它们 */
    for (int x = 0; this->GetValuePtr(qtssCliSesStreamObjects, x, (void**)&theStream, &theLen) == QTSS_NoErr; x++)
    {
        Assert(theStream != NULL);
        Assert(theLen == sizeof(RTPStream*));
        
        if (*theStream != NULL)
            delete *theStream;
    }
    
	/* 获取服务器接口类,逐一将该RTPSession从qtssSvrClientSessions属性中删去 */
    QTSServerInterface* theServer = QTSServerInterface::GetServer();
    {
        OSMutexLocker theLocker(theServer->GetMutex());
        
        RTPSession** theSession = NULL;
        
        // Remove this session from the qtssSvrClientSessions attribute
        UInt32 y = 0;
        for ( ; y < theServer->GetNumRTPSessions(); y++)
        {
            QTSS_Error theErr = theServer->GetValuePtr(qtssSvrClientSessions, y, (void**)&theSession, &theLen, true);
            Assert(theErr == QTSS_NoErr);
            
            if (*theSession == this)
            {
                theErr = theServer->RemoveValue(qtssSvrClientSessions, y, QTSSDictionary::kDontObeyReadOnly);
                break;
            }
        }

        Assert(y < theServer->GetNumRTPSessions());
        theServer->AlterCurrentRTPSessionCount(-1);
        if (!fIsFirstPlay) // The session was started playing (the counter ignores additional pause-play changes while session is active)
            theServer->AlterRTPPlayingSessions(-1);
        
    }


    //we better not be in the RTPSessionMap anymore!
#if DEBUG
    Assert(!fRTPMapElem.IsInTable());
	StrPtrLen theRTSPSessionID(fRTSPSessionIDBuf,sizeof(fRTSPSessionIDBuf));
	/* 从RTPSession Map中删去它们 */
    OSRef* theRef = QTSServerInterface::GetServer()->GetRTPSessionMap()->Resolve(&theRTSPSessionID);
    Assert(theRef == NULL);
#endif
}
Beispiel #9
0
SInt64 RTCPTask::Run()
{
    const UInt32 kMaxRTCPPacketSize = 2048;
    char thePacketBuffer[kMaxRTCPPacketSize];
    StrPtrLen thePacket(thePacketBuffer, 0);
    QTSServerInterface* theServer = QTSServerInterface::GetServer();
    
    //This task goes through all the UDPSockets in the RTPSocketPool, checking to see
    //if they have data. If they do, it demuxes the packets and sends the packet onto
    //the proper RTP session.
    EventFlags events = this->GetEvents(); // get and clear events
    
    if ( (events & Task::kReadEvent) || (events & Task::kIdleEvent) )
        {
                //Must be done atomically wrt the socket pool.
                
                OSMutexLocker locker(theServer->GetSocketPool()->GetMutex());
                for (OSQueueIter iter(theServer->GetSocketPool()->GetSocketQueue());
                                !iter.IsDone(); iter.Next())
                {
                        UInt32 theRemoteAddr = 0;
                        UInt16 theRemotePort = 0;
        
                        UDPSocketPair* thePair = (UDPSocketPair*)iter.GetCurrent()->GetEnclosingObject();
                        Assert(thePair != NULL);
                        
                        for (UInt32 x = 0; x < 2; x++)
                        {
                                UDPSocket* theSocket = NULL;
                                if (x == 0)
                                        theSocket = thePair->GetSocketA();
                                else
                                        theSocket = thePair->GetSocketB();
                                        
                                UDPDemuxer* theDemuxer = theSocket->GetDemuxer();
                        if (theDemuxer == NULL) 
                            continue;
                        else
                        {
                                        theDemuxer->GetMutex()->Lock();
                            while (true) //get all the outstanding packets for this socket
                                {
                                        thePacket.Len = 0;
                                        theSocket->RecvFrom(&theRemoteAddr, &theRemotePort, thePacket.Ptr,  
                                                                        kMaxRTCPPacketSize, &thePacket.Len);
                                        if (thePacket.Len == 0)
                                        {
                                                theSocket->RequestEvent(EV_RE);   
                                                break;//no more packets on this socket!
                                        }
                                        
                                        //if this socket has a demuxer, find the target RTPStream
                                        if (theDemuxer != NULL)
                                        {
                                                RTPStream* theStream = (RTPStream*)theDemuxer->GetTask(theRemoteAddr, theRemotePort);
                                                if (theStream != NULL)
                                                        theStream->ProcessIncomingRTCPPacket(&thePacket);
                                        }
                                }
                                        theDemuxer->GetMutex()->Unlock();
                        }
                }
        }
    }
     
    return 0; /* Fix for 4004432 */   
    /*
    SInt64 result = 0;
    if (theServer->GetNumRTPSessions() > 0)
        result =  theServer->GetPrefs()->GetRTCPPollIntervalInMsec();
    
   return result;
   */
}