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; }
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; }
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; }
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; }