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; }
SInt64 ProxyTask::Run() { const UInt32 kMaxRTCPPacketSize = 2048; char thePacketBuffer[kMaxRTCPPacketSize]; QTSS_PacketStruct thePacketStruct; thePacketStruct.packetTransmitTime = QTSS_Milliseconds(); thePacketStruct.packetData = thePacketBuffer; (void)this->GetEvents(); OSMutexLocker locker(sSocketPool->GetMutex()); for (OSQueueIter iter(sSocketPool->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++) { QTSS_WriteFlags theFlags = qtssWriteFlagsNoFlags; UDPSocket* theSocket = NULL; if (x == 0) { theFlags = qtssWriteFlagsIsRTP; theSocket = thePair->GetSocketA(); } else { theFlags = qtssWriteFlagsIsRTCP; theSocket = thePair->GetSocketB(); } Assert(theSocket->GetDemuxer() != NULL); OSMutexLocker locker(theSocket->GetDemuxer()->GetMutex()); //get all the outstanding packets for this socket while (true) { UInt32 thePacketLen = 0; theSocket->RecvFrom(&theRemoteAddr, &theRemotePort, thePacketStruct.packetData, kMaxRTCPPacketSize, &thePacketLen); if (thePacketLen == 0) break;//no more packets on this socket! ProxyDemuxerTask* theDemuxerTask = (ProxyDemuxerTask*)theSocket->GetDemuxer()->GetTask(theRemoteAddr, 0); if (theDemuxerTask != NULL) { QTSS_RTPStreamObject theStream = theDemuxerTask->GetStream(); (void)QTSS_Write(theStream, &thePacketStruct, thePacketLen, NULL, theFlags); } } } } return kProxyTaskPollIntervalMsec; }
inline Bool16 InWaitInterval(QTSS_Filter_Params* inParams) { QTSS_TimeVal nextExecuteTime = sLastRequestTime + sRequestTimeIntervalMilli; QTSS_TimeVal currentTime = QTSS_Milliseconds(); SInt32 waitTime = 0; if (currentTime < nextExecuteTime) { waitTime = (SInt32) (nextExecuteTime - currentTime) + 1; //qtss_printf("(currentTime < nextExecuteTime) sSessID = %"_U32BITARG_" waitTime =%"_S32BITARG_" currentTime = %qd nextExecute = %qd interval=%"_U32BITARG_"\n",sSessID, waitTime, currentTime, nextExecuteTime,sRequestTimeIntervalMilli); (void)QTSS_SetIdleTimer(waitTime); KeepSession(inParams->inRTSPRequest,true); //qtss_printf("-- call me again after %"_S32BITARG_" millisecs session=%"_U32BITARG_" \n",waitTime,sSessID); return true; } sLastRequestTime = QTSS_Milliseconds(); //qtss_printf("handle sessID=%"_U32BITARG_" time=%qd \n",sSessID,currentTime); return false; }
void QTSSvrControlThread::HistoryEntry() { //compute how often to run this thread. QTSSModuleUtils::GetAttribute(sPrefs, "history_update_interval", qtssAttrDataTypeUInt32, &sHistoryIntervalInSecs, &sDefaultHistoryIntervalInSecs, sizeof(sHistoryIntervalInSecs)); UInt32 theSampleInterval = (sHistoryIntervalInSecs * 1000) / kNumSamplesPerEntry; UInt32 theEntryInterval = sHistoryIntervalInSecs * 1000; //use local time to figure out when we need move onto a new entry. This //will eliminate the possibility that we drift off time. SInt64 theStartTime = QTSS_Milliseconds(); Assert(theStartTime > 0); while (!fDone) { //sleep for the kHistoryUpdateInterval //kHistoryUpdateInterval is in minutes. Convert to msec. thread_switch(THREAD_NULL, SWITCH_OPTION_WAIT, theSampleInterval); //if server is doing a graceful shutdown, this thread is used to periodically //poll, checking if all connections are complete CheckShutdown(); //every time we wake up, first thing we want to do is sample the //current state of the server for the history AddHistorySample(); SInt64 theCurrentTime = QTSS_Milliseconds(); Assert(theCurrentTime > 0); if ((theCurrentTime - theStartTime) > theEntryInterval) { UpdateHistoryArray(); theStartTime += theEntryInterval; } } }
QTSS_Error LogRequest(QTSS_ClientSessionObject inClientSession, QTSS_RTSPSessionObject inRTSPSession, QTSS_CliSesClosingReason *inCloseReasonPtr) { static StrPtrLen sUnknownStr(sVoidField); static StrPtrLen sTCPStr("TCP"); static StrPtrLen sUDPStr("UDP"); //Fetch the URL, user agent, movielength & movie bytes to log out of the RTP session enum { eTempLogItemSize = 256, // must be same or larger than others eURLSize = 256, eUserAgentSize = 256, ePlayerIDSize = 32, ePlayerVersionSize = 32, ePlayerLangSize = 32, ePlayerOSSize = 32, ePlayerOSVersSize = 32, ePlayerCPUSize = 32 }; char tempLogItemBuf[eTempLogItemSize] = { 0 }; StrPtrLen tempLogStr(tempLogItemBuf, eTempLogItemSize - 1); // // Check to see if this session is closing because authorization failed. If that's // the case, we've logged that already, let's not log it twice UInt32 theLen = 0; UInt32* authorizationFailed = NULL; (void)QTSS_GetValuePtr(inClientSession, sLoggedAuthorizationAttrID, 0, (void**)&authorizationFailed, &theLen); if ((authorizationFailed != NULL) && (*authorizationFailed > 0)) return QTSS_NoErr; ///inClientSession should never be NULL //inRTSPRequest may be NULL if this is a timeout OSMutexLocker locker(sLogMutex); CheckAccessLogState(false); if (sAccessLog == NULL) return QTSS_NoErr; //if logging is on, then log the request... first construct a timestamp char theDateBuffer[QTSSRollingLog::kMaxDateBufferSizeInBytes]; bool result = QTSSRollingLog::FormatDate(theDateBuffer, sLogTimeInGMT); //for now, just ignore the error. if (!result) theDateBuffer[0] = '\0'; theLen = sizeof(QTSS_RTSPSessionObject); QTSS_RTSPSessionObject theRTSPSession = inRTSPSession; if (theRTSPSession == NULL) (void)QTSS_GetValue(inClientSession, qtssCliSesLastRTSPSession, 0, (void*)&theRTSPSession, &theLen); // Get lots of neat info to log from the various dictionaries // Each attribute must be copied out to ensure that it is NULL terminated. // To ensure NULL termination, just memset the buffers to 0, and make sure that // the last byte of each array is untouched. Float32* packetLossPercent = NULL; Float64* movieDuration = NULL; UInt64* movieSizeInBytes = NULL; UInt32* movieAverageBitRatePtr = 0; UInt32 clientPacketsReceived = 0; UInt32 clientPacketsLost = 0; StrPtrLen* theTransportType = &sUnknownStr; SInt64* theCreateTime = NULL; SInt64* thePlayTime = NULL; UInt32 startPlayTimeInSecs = 0; char localIPAddrBuf[20] = { 0 }; StrPtrLen localIPAddr(localIPAddrBuf, 19); char localDNSBuf[70] = { 0 }; StrPtrLen localDNS(localDNSBuf, 69); char remoteDNSBuf[70] = { 0 }; StrPtrLen remoteDNS(remoteDNSBuf, 69); char remoteAddrBuf[20] = { 0 }; StrPtrLen remoteAddr(remoteAddrBuf, 19); char playerIDBuf[ePlayerIDSize] = { 0 }; StrPtrLen playerID(playerIDBuf, ePlayerIDSize - 1); // First, get networking info from the RTSP session (void)QTSS_GetValue(inClientSession, qtssCliRTSPSessLocalAddrStr, 0, localIPAddr.Ptr, &localIPAddr.Len); (void)QTSS_GetValue(inClientSession, qtssCliRTSPSessLocalDNS, 0, localDNS.Ptr, &localDNS.Len); (void)QTSS_GetValue(inClientSession, qtssCliSesHostName, 0, remoteDNS.Ptr, &remoteDNS.Len); (void)QTSS_GetValue(inClientSession, qtssCliRTSPSessRemoteAddrStr, 0, remoteAddr.Ptr, &remoteAddr.Len); (void)QTSS_GetValue(inClientSession, qtssCliRTSPSessRemoteAddrStr, 0, playerID.Ptr, &playerID.Len); UInt32* rtpBytesSent = NULL; UInt32* rtcpBytesRecv = NULL; UInt32* rtpPacketsSent = NULL; // Second, get networking info from the Client's session. // (Including the stats for incoming RTCP packets.) char urlBuf[eURLSize] = { 0 }; StrPtrLen url(urlBuf, eURLSize - 1); (void)QTSS_GetValue(inClientSession, qtssCliSesPresentationURL, 0, url.Ptr, &url.Len); (void)QTSS_GetValuePtr(inClientSession, qtssCliSesPacketLossPercent, 0, (void**)&packetLossPercent, &theLen); (void)QTSS_GetValuePtr(inClientSession, qtssCliSesMovieDurationInSecs, 0, (void**)&movieDuration, &theLen); (void)QTSS_GetValuePtr(inClientSession, qtssCliSesMovieSizeInBytes, 0, (void**)&movieSizeInBytes, &theLen); (void)QTSS_GetValuePtr(inClientSession, qtssCliSesMovieAverageBitRate, 0, (void**)&movieAverageBitRatePtr, &theLen); (void)QTSS_GetValuePtr(inClientSession, qtssCliSesCreateTimeInMsec, 0, (void**)&theCreateTime, &theLen); (void)QTSS_GetValuePtr(inClientSession, qtssCliSesFirstPlayTimeInMsec, 0, (void**)&thePlayTime, &theLen); (void)QTSS_GetValuePtr(inClientSession, qtssCliSesRTPBytesSent, 0, (void**)&rtpBytesSent, &theLen); (void)QTSS_GetValuePtr(inClientSession, qtssCliSesRTPPacketsSent, 0, (void**)&rtpPacketsSent, &theLen); (void)QTSS_GetValuePtr(inClientSession, qtssCliSesRTCPBytesRecv, 0, (void**)&rtcpBytesRecv, &theLen); if (theCreateTime != NULL && thePlayTime != NULL) startPlayTimeInSecs = (UInt32)(((*theCreateTime - *thePlayTime) / 1000) + 0.5); // We need a value of 'c-bytes' to report as a log entry. This is supposed to be the total number // of bytes the client has received during the session. Unfortunately, the QT client does not give // us this number. We will use the following heuristic formula to estimate the number of bytes the // client has received during the session: // // client-bytes-received = bytes-sent * (100.0 - percent-packet-lost) / 100.0 // // The 'percent-packet-lost' value has been calculated internally by QTSS based on the RTCP packets // sent to the server from the client. If those values are accurate then the above formula will not // be exactly correct but it will be nearly correct. UInt32 clientBytesRecv = (UInt32)((*rtpBytesSent * (100.0 - *packetLossPercent)) / 100.0); tempLogStr.Ptr[0] = 0; tempLogStr.Len = eUserAgentSize; (void)QTSS_GetValue(inClientSession, qtssCliSesFirstUserAgent, 0, tempLogStr.Ptr, &tempLogStr.Len); char userAgentBuf[eUserAgentSize] = { 0 }; StrPtrLen userAgent(userAgentBuf, eUserAgentSize - 1); ReplaceSpaces(&tempLogStr, &userAgent, "%20"); UserAgentParser userAgentParser(&userAgent); // StrPtrLen* playerID = userAgentParser.GetUserID() ; StrPtrLen* playerVersion = userAgentParser.GetUserVersion(); StrPtrLen* playerLang = userAgentParser.GetUserLanguage(); StrPtrLen* playerOS = userAgentParser.GetrUserOS(); StrPtrLen* playerOSVers = userAgentParser.GetUserOSVersion(); StrPtrLen* playerCPU = userAgentParser.GetUserCPU(); // char playerIDBuf[ePlayerIDSize] = {}; char playerVersionBuf[ePlayerVersionSize] = { 0 }; char playerLangBuf[ePlayerLangSize] = { 0 }; char playerOSBuf[ePlayerOSSize] = { 0 }; char playerOSVersBuf[ePlayerOSVersSize] = { 0 }; char playerCPUBuf[ePlayerCPUSize] = { 0 }; UInt32 size; // (ePlayerIDSize < playerID->Len ) ? size = ePlayerIDSize -1 : size = playerID->Len; // if (playerID->Ptr != NULL) memcpy (playerIDBuf, playerID->Ptr, size); (ePlayerVersionSize < playerVersion->Len) ? size = ePlayerVersionSize - 1 : size = playerVersion->Len; if (playerVersion->Ptr != NULL) memcpy(playerVersionBuf, playerVersion->Ptr, size); (ePlayerLangSize < playerLang->Len) ? size = ePlayerLangSize - 1 : size = playerLang->Len; if (playerLang->Ptr != NULL) memcpy(playerLangBuf, playerLang->Ptr, size); (ePlayerOSSize < playerOS->Len) ? size = ePlayerOSSize - 1 : size = playerOS->Len; if (playerOS->Ptr != NULL) memcpy(playerOSBuf, playerOS->Ptr, size); (ePlayerOSVersSize < playerOSVers->Len) ? size = ePlayerOSVersSize - 1 : size = playerOSVers->Len; if (playerOSVers->Ptr != NULL) memcpy(playerOSVersBuf, playerOSVers->Ptr, size); (ePlayerCPUSize < playerCPU->Len) ? size = ePlayerCPUSize - 1 : size = playerCPU->Len; if (playerCPU->Ptr != NULL) memcpy(playerCPUBuf, playerCPU->Ptr, size); // clientPacketsReceived, clientPacketsLost, videoPayloadName and audioPayloadName // are all stored on a per-stream basis, so let's iterate through all the streams, // finding this information char videoPayloadNameBuf[32] = { 0 }; StrPtrLen videoPayloadName(videoPayloadNameBuf, 31); char audioPayloadNameBuf[32] = { 0 }; StrPtrLen audioPayloadName(audioPayloadNameBuf, 31); UInt32 qualityLevel = 0; UInt32 clientBufferTime = 0; UInt32 theStreamIndex = 0; bool* isTCPPtr = NULL; QTSS_RTPStreamObject theRTPStreamObject = NULL; for (UInt32 theStreamObjectLen = sizeof(theRTPStreamObject); QTSS_GetValue(inClientSession, qtssCliSesStreamObjects, theStreamIndex, (void*)&theRTPStreamObject, &theStreamObjectLen) == QTSS_NoErr; theStreamIndex++, theStreamObjectLen = sizeof(theRTPStreamObject)) { UInt32* streamPacketsReceived = NULL; UInt32* streamPacketsLost = NULL; (void)QTSS_GetValuePtr(theRTPStreamObject, qtssRTPStrTotPacketsRecv, 0, (void**)&streamPacketsReceived, &theLen); (void)QTSS_GetValuePtr(theRTPStreamObject, qtssRTPStrTotalLostPackets, 0, (void**)&streamPacketsLost, &theLen); // Add up packets received and packets lost to come up with a session wide total if (streamPacketsReceived != NULL) clientPacketsReceived += *streamPacketsReceived; if (streamPacketsLost != NULL) clientPacketsLost += *streamPacketsLost; // Identify the video and audio codec types QTSS_RTPPayloadType* thePayloadType = NULL; (void)QTSS_GetValuePtr(theRTPStreamObject, qtssRTPStrPayloadType, 0, (void**)&thePayloadType, &theLen); if (thePayloadType != NULL) { if (*thePayloadType == qtssVideoPayloadType) (void)QTSS_GetValue(theRTPStreamObject, qtssRTPStrPayloadName, 0, videoPayloadName.Ptr, &videoPayloadName.Len); else if (*thePayloadType == qtssAudioPayloadType) (void)QTSS_GetValue(theRTPStreamObject, qtssRTPStrPayloadName, 0, audioPayloadName.Ptr, &audioPayloadName.Len); } // If any one of the streams is being delivered over UDP instead of TCP, // report in the log that the transport type for this session was UDP. if (isTCPPtr == NULL) { (void)QTSS_GetValuePtr(theRTPStreamObject, qtssRTPStrIsTCP, 0, (void**)&isTCPPtr, &theLen); if (isTCPPtr != NULL) { if (*isTCPPtr == false) theTransportType = &sUDPStr; else theTransportType = &sTCPStr; } } Float32* clientBufferTimePtr = NULL; (void)QTSS_GetValuePtr(theRTPStreamObject, qtssRTPStrBufferDelayInSecs, 0, (void**)&clientBufferTimePtr, &theLen); if ((clientBufferTimePtr != NULL) && (*clientBufferTimePtr != 0)) { if (*clientBufferTimePtr > clientBufferTime) clientBufferTime = (UInt32)(*clientBufferTimePtr + .5); // round up to full seconds } } // Add the client buffer time to our client start latency (in whole seconds). startPlayTimeInSecs += clientBufferTime; if (*rtpPacketsSent == 0) // no packets sent qualityLevel = 0; // no quality else { if ((clientPacketsReceived == 0) && (clientPacketsLost == 0)) // no info from client qualityLevel = 100; //so assume 100 else { float qualityPercent = (float)clientPacketsReceived / (float)(clientPacketsReceived + clientPacketsLost); qualityPercent += (float).005; // round up qualityLevel = (UInt32)((float) 100.0 * qualityPercent); // average of sum of packet counts for all streams } } //we may not have an RTSP request. Assume that the status code is 504 timeout, if there is an RTSP //request, though, we can find out what the real status code of the response is static UInt32 sTimeoutCode = 504; UInt32* theStatusCode = &sTimeoutCode; theLen = sizeof(UInt32); (void)QTSS_GetValuePtr(inClientSession, qtssCliRTSPReqRealStatusCode, 0, (void **)&theStatusCode, &theLen); // qtss_printf("qtssCliRTSPReqRealStatusCode = %" _U32BITARG_ " \n", *theStatusCode); if (inCloseReasonPtr) do { if (*theStatusCode < 300) // it was a succesful RTSP request but... { if (*inCloseReasonPtr == qtssCliSesCloseTimeout) // there was a timeout { *theStatusCode = sTimeoutCode; // qtss_printf(" log timeout "); break; } if (*inCloseReasonPtr == qtssCliSesCloseClientTeardown) // there was a teardown { static QTSS_CliSesClosingReason sReason = qtssCliSesCloseClientTeardown; QTSS_CliSesClosingReason* theReasonPtr = &sReason; theLen = sizeof(QTSS_CliSesTeardownReason); (void)QTSS_GetValuePtr(inClientSession, qtssCliTeardownReason, 0, (void **)&theReasonPtr, &theLen); // qtss_printf("qtssCliTeardownReason = %" _U32BITARG_ " \n", *theReasonPtr); if (*theReasonPtr == qtssCliSesTearDownClientRequest) // the client asked for a tear down { // qtss_printf(" client requests teardown "); break; } if (*theReasonPtr == qtssCliSesTearDownUnsupportedMedia) // An error occured while streaming the file. { *theStatusCode = 415; // qtss_printf(" log UnsupportedMedia "); break; } if (*theReasonPtr == qtssCliSesTearDownBroadcastEnded) // a broadcaster stopped broadcasting { *theStatusCode = 452; // qtss_printf(" log broadcast removed "); break; } *theStatusCode = 500; // some unknown reason for cancelling the connection } // qtss_printf("return status "); // just use the qtssCliRTSPReqRealStatusCode for the reason } } while (false); // qtss_printf(" = %" _U32BITARG_ " \n", *theStatusCode); // Find out what time it is SInt64 curTime = QTSS_Milliseconds(); UInt32 numCurClients = 0; theLen = sizeof(numCurClients); (void)QTSS_GetValue(sServer, qtssRTPSvrCurConn, 0, &numCurClients, &theLen); /* IMPORTANT!!!! Some values such as cpu, #conns, need to be grabbed as the session starts, not when the teardown happened (I think) */ #if TESTUNIXTIME char thetestDateBuffer[QTSSRollingLog::kMaxDateBufferSizeInBytes]; TestUnixTime(QTSS_MilliSecsTo1970Secs(*theCreateTime), thetestDateBuffer); qtss_printf("%s\n", thetestDateBuffer); #endif float zeroFloat = 0; UInt64 zeroUInt64 = 0; Float32 fcpuUtilized = 0; theLen = sizeof(fcpuUtilized); (void)QTSS_GetValue(sServer, qtssSvrCPULoadPercent, 0, &fcpuUtilized, &theLen); UInt32 cpuUtilized = (UInt32)fcpuUtilized; char lastUserName[eTempLogItemSize] = { 0 }; StrPtrLen lastUserNameStr(lastUserName, eTempLogItemSize); char lastURLRealm[eTempLogItemSize] = { 0 }; StrPtrLen lastURLRealmStr(lastURLRealm, eTempLogItemSize); //qtss_printf("logging of saved params are in dictionary \n"); tempLogStr.Ptr[0] = 0; tempLogStr.Len = eTempLogItemSize; (void)QTSS_GetValue(inClientSession, qtssCliRTSPSesUserName, 0, tempLogStr.Ptr, &tempLogStr.Len); ReplaceSpaces(&tempLogStr, &lastUserNameStr, "%20"); //qtss_printf("qtssRTSPSesLastUserName dictionary item = %s len = %" _S32BITARG_ "\n",lastUserNameStr.Ptr,lastUserNameStr.Len); tempLogStr.Ptr[0] = 0; tempLogStr.Len = eTempLogItemSize; (void)QTSS_GetValue(inClientSession, qtssCliRTSPSesURLRealm, 0, tempLogStr.Ptr, &tempLogStr.Len); ReplaceSpaces(&tempLogStr, &lastURLRealmStr, "%20"); //qtss_printf("qtssRTSPSesLastURLRealm dictionary item = %s len = %" _S32BITARG_ "\n",lastURLRealmStr.Ptr,lastURLRealmStr.Len); char respMsgBuffer[1024] = { 0 }; StrPtrLen theRespMsg; (void)QTSS_GetValuePtr(inClientSession, qtssCliRTSPReqRespMsg, 0, (void**)&theRespMsg.Ptr, &theRespMsg.Len); StrPtrLen respMsgEncoded(respMsgBuffer, 1024 - 1); SInt32 theErr = StringTranslator::EncodeURL(theRespMsg.Ptr, theRespMsg.Len, respMsgEncoded.Ptr, respMsgEncoded.Len); if (theErr <= 0) respMsgEncoded.Ptr[0] = '\0'; else { respMsgEncoded.Len = theErr; respMsgEncoded.Ptr[respMsgEncoded.Len] = '\0'; } //cs-uri-query char urlQryBuf[eURLSize] = { 0 }; StrPtrLen urlQry(urlQryBuf, eURLSize - 1); (void)QTSS_GetValue(inClientSession, qtssCliSesReqQueryString, 0, urlQry.Ptr, &urlQry.Len); char tempLogBuffer[1024]; char logBuffer[2048]; // compatible fields (no respMsgEncoded field) ::memset(logBuffer, 0, 2048); qtss_sprintf(tempLogBuffer, "%s ", (remoteAddr.Ptr[0] == '\0') ? sVoidField : remoteAddr.Ptr); //c-ip* ::strcpy(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%s ", (theDateBuffer[0] == '\0') ? sVoidField : theDateBuffer); //date* time* ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%s ", (remoteDNS.Ptr[0] == '\0') ? sVoidField : remoteDNS.Ptr); //c-dns ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%s ", (url.Ptr[0] == '\0') ? sVoidField : url.Ptr); //cs-uri-stem* ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%" _U32BITARG_ " ", startPlayTimeInSecs); //c-starttime ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%" _U32BITARG_ " ", theCreateTime == NULL ? (UInt32)0 : (UInt32)(QTSS_MilliSecsTo1970Secs(curTime) - QTSS_MilliSecsTo1970Secs(*theCreateTime))); //x-duration* ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%" _S32BITARG_ " ", (UInt32)1); //c-rate ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%" _S32BITARG_ " ", *theStatusCode); //c-status* ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%s ", (playerIDBuf[0] == '\0') ? sVoidField : playerIDBuf); //c-playerid* ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%s ", (playerVersionBuf[0] == '\0') ? sVoidField : playerVersionBuf); //c-playerversion ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%s ", (playerLangBuf[0] == '\0') ? sVoidField : playerLangBuf); //c-playerlanguage* ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%s ", (userAgent.Ptr[0] == '\0') ? sVoidField : userAgent.Ptr); //cs(User-Agent) ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%s ", (playerOSBuf[0] == '\0') ? sVoidField : playerOSBuf); //c-os* ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%s ", (playerOSVersBuf[0] == '\0') ? sVoidField : playerOSVersBuf); //c-osversion ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%s ", (playerCPUBuf[0] == '\0') ? sVoidField : playerCPUBuf); //c-cpu* ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%0.0f ", movieDuration == NULL ? zeroFloat : *movieDuration); //filelength in secs* ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%" _64BITARG_ "d ", movieSizeInBytes == NULL ? zeroUInt64 : *movieSizeInBytes); //filesize in bytes* ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%" _U32BITARG_ " ", movieAverageBitRatePtr == NULL ? (UInt32)0 : *movieAverageBitRatePtr); //avgbandwidth in bits per second ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%s ", "RTP"); //protocol ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%s ", (theTransportType->Ptr[0] == '\0') ? sVoidField : theTransportType->Ptr); //transport ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%s ", (audioPayloadName.Ptr[0] == '\0') ? sVoidField : audioPayloadName.Ptr); //audiocodec* ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%s ", (videoPayloadName.Ptr[0] == '\0') ? sVoidField : videoPayloadName.Ptr); //videocodec* ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%" _U32BITARG_ " ", rtpBytesSent == NULL ? (UInt32)0 : *rtpBytesSent); //sc-bytes* ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%" _U32BITARG_ " ", rtcpBytesRecv == NULL ? (UInt32)0 : *rtcpBytesRecv); //cs-bytes* ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%" _U32BITARG_ " ", clientBytesRecv); //c-bytes ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%" _U32BITARG_ " ", rtpPacketsSent == NULL ? (UInt32)0 : *rtpPacketsSent); //s-pkts-sent* ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%" _U32BITARG_ " ", clientPacketsReceived); //c-pkts-recieved ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%" _U32BITARG_ " ", clientPacketsLost); //c-pkts-lost-client* ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%" _U32BITARG_ " ", (UInt32)1); //c-buffercount ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%" _U32BITARG_ " ", clientBufferTime); //c-totalbuffertime* ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%" _U32BITARG_ " ", qualityLevel); //c-quality ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%s ", (localIPAddr.Ptr[0] == '\0') ? sVoidField : localIPAddr.Ptr); //s-ip ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%s ", (localDNS.Ptr[0] == '\0') ? sVoidField : localDNS.Ptr); //s-dns ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%" _U32BITARG_ " ", numCurClients); //s-totalclients ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%" _U32BITARG_ " ", cpuUtilized); //s-cpu-util ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%s ", (urlQry.Ptr[0] == '\0') ? sVoidField : urlQry.Ptr); //cs-uri-query ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%s ", (lastUserName[0] == '\0') ? sVoidField : lastUserName); //c-username ::strcat(logBuffer, tempLogBuffer); qtss_sprintf(tempLogBuffer, "%s ", (lastURLRealm[0] == '\0') ? sVoidField : lastURLRealm); //sc(Realm) ::strcat(logBuffer, tempLogBuffer); ::strcat(logBuffer, "\n"); Assert(::strlen(logBuffer) < 2048); //finally, write the log message sAccessLog->WriteToLog(logBuffer, kAllowLogToRoll); return QTSS_NoErr; }