/* * * @APPLE_LICENSE_HEADER_START@ * * Copyright (c) 1999-2008 Apple Inc. All Rights Reserved. * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ * */ /* File: QTSSWebStatsModule.cpp Contains: Implements web stats module */ #include #include /* for qtss_printf */ #include /* for getloadavg & other useful stuff */ #include "QTSSWebStatsModule.h" #include "OSArrayObjectDeleter.h" #include "StringParser.h" #include "StrPtrLen.h" #include "QTSSModuleUtils.h" // STATIC DATA static char* sResponseHeader = "HTTP/1.0 200 OK\r\nServer: QTSS/3.0\r\nConnection: Close\r\nContent-Type: text/html\r\n\r\n"; static QTSS_ServerObject sServer = NULL; static QTSS_ModulePrefsObject sAccessLogPrefs = NULL; static QTSS_ModulePrefsObject sReflectorPrefs = NULL; static QTSS_ModulePrefsObject sSvrControlPrefs = NULL; static QTSS_ModulePrefsObject sPrefs = NULL; static QTSS_PrefsObject sServerPrefs = NULL; static Bool16 sFalse = false; static time_t sStartupTime = 0; static char* sDefaultURL = ""; static StrPtrLen sDefaultURLStr; static char* sDefaultURLPrefName = "web_stats_url"; static QTSS_Error QTSSWebStatsModuleDispatch(QTSS_Role inRole, QTSS_RoleParamPtr inParams); static QTSS_Error Register(QTSS_Register_Params* inParams); static QTSS_Error Initialize(QTSS_Initialize_Params* inParams); static QTSS_Error FilterRequest(QTSS_Filter_Params* inParams); static void SendStats(QTSS_StreamRef inStream, UInt32 refreshInterval, Bool16 displayHelp, StrPtrLen* fieldList); static char* GetPrefAsString(QTSS_ModulePrefsObject inPrefsObject, char* inPrefName); // FUNCTION IMPLEMENTATIONS QTSS_Error QTSSWebStatsModule_Main(void* inPrivateArgs) { return _stublibrary_main(inPrivateArgs, QTSSWebStatsModuleDispatch); } QTSS_Error QTSSWebStatsModuleDispatch(QTSS_Role inRole, QTSS_RoleParamPtr inParams) { switch (inRole) { case QTSS_Register_Role: return Register(&inParams->regParams); case QTSS_Initialize_Role: return Initialize(&inParams->initParams); case QTSS_RTSPFilter_Role: return FilterRequest(&inParams->rtspFilterParams); } return QTSS_NoErr; } QTSS_Error Register(QTSS_Register_Params* inParams) { // Do role & attribute setup (void)QTSS_AddRole(QTSS_Initialize_Role); (void)QTSS_AddRole(QTSS_RTSPFilter_Role); // Tell the server our name! static char* sModuleName = "QTSSWebStatsModule"; ::strcpy(inParams->outModuleName, sModuleName); return QTSS_NoErr; } QTSS_Error Initialize(QTSS_Initialize_Params* inParams) { // Setup module utils QTSSModuleUtils::Initialize(inParams->inMessages, inParams->inServer, inParams->inErrorLogStream); sAccessLogPrefs = QTSSModuleUtils::GetModulePrefsObject(QTSSModuleUtils::GetModuleObjectByName("QTSSAccessLogModule")); sReflectorPrefs = QTSSModuleUtils::GetModulePrefsObject(QTSSModuleUtils::GetModuleObjectByName("QTSSReflectorModule")); sPrefs = QTSSModuleUtils::GetModulePrefsObject(inParams->inModule); // This module may not be present, so be careful... QTSS_ModuleObject theSvrControlModule = QTSSModuleUtils::GetModuleObjectByName("QTSSSvrControlModule"); if (theSvrControlModule != NULL) sSvrControlPrefs = QTSSModuleUtils::GetModulePrefsObject(theSvrControlModule); sServer = inParams->inServer; sServerPrefs = inParams->inPrefs; sStartupTime = ::time(NULL); sDefaultURLStr.Delete(); sDefaultURLStr.Set(QTSSModuleUtils::GetStringAttribute(sPrefs, sDefaultURLPrefName, sDefaultURL)); return QTSS_NoErr; } QTSS_Error FilterRequest(QTSS_Filter_Params* inParams) { UInt8 sParamStopMask[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0-9 //stop unless a '\t', ' ', or '&' 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10-19 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //20-29 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, //30-39 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //40-49 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //50-59 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //60-69 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //70-79 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //80-89 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //90-99 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //100-109 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //110-119 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //120-129 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //130-139 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //140-149 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //150-159 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //160-169 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //170-179 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //180-189 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //190-199 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //200-209 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //210-219 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //220-229 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //230-239 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //240-249 0, 0, 0, 0, 0, 1 //250-255 }; //check to see if we should handle this request. Invokation is triggered //by a "GET /" request QTSS_RTSPRequestObject theRequest = inParams->inRTSPRequest; StrPtrLen theFullRequest; (void)QTSS_GetValuePtr(theRequest, qtssRTSPReqFullRequest, 0, (void**)&theFullRequest.Ptr, &theFullRequest.Len); StringParser fullRequest(&theFullRequest); StrPtrLen strPtr; StrPtrLen paramName; StrPtrLen fieldsList; fullRequest.ConsumeWord(&strPtr); if ( strPtr.Equal(StrPtrLen("GET")) ) //it's a "Get" request { fullRequest.ConsumeWhitespace(); if ( fullRequest.Expect('/') ) { UInt32 refreshInterval = 0; Bool16 displayHelp = false; OSCharArrayDeleter theWebStatsURL(GetPrefAsString(sPrefs, sDefaultURLPrefName)); StrPtrLen theWebStatsURLPtr(theWebStatsURL.GetObject()); // If there isn't any web stats URL, we can just return at this point if (theWebStatsURLPtr.Len == 0) return QTSS_NoErr; fullRequest.ConsumeUntil(&strPtr, StringParser::sEOLWhitespaceQueryMask); if ( strPtr.Len != 0 && strPtr.Equal(theWebStatsURLPtr) ) //it's a "stats" request { if ( fullRequest.Expect('?') ) { do { fullRequest.ConsumeWord(¶mName); if( paramName.Len != 0) { if ( paramName.Equal(StrPtrLen("refresh",strlen("refresh"))) ) { if (fullRequest.Expect('=')) refreshInterval = fullRequest.ConsumeInteger(NULL); } else if ( paramName.Equal(StrPtrLen("help",strlen("help"))) ) { displayHelp = true; } else if ( paramName.Equal(StrPtrLen("fields",strlen("fields"))) ) { if (fullRequest.Expect('=')) fullRequest.ConsumeUntil(&fieldsList, (UInt8*)sParamStopMask); } } } while ( paramName.Len != 0 && fullRequest.Expect('&') ); } // Before sending a response, set keep alive to off for this connection (void)QTSS_SetValue(theRequest, qtssRTSPReqRespKeepAlive, 0, &sFalse, sizeof(sFalse)); SendStats(inParams->inRTSPRequest, refreshInterval, displayHelp, (fieldsList.Len != 0) ? &fieldsList : NULL); } } } return QTSS_NoErr; } void SendStats(QTSS_StreamRef inStream, UInt32 refreshInterval, Bool16 displayHelp, StrPtrLen* fieldList) { struct FieldIndex { char* fieldName; int fieldIndex; }; const FieldIndex kFieldIndexes[] = { {"title", 1}, {"dnsname", 2}, {"curtime", 3}, {"", 4}, {"serververs", 5}, {"serverbornon", 6}, {"serverstatus", 7}, {"", 8}, {"", 9}, {"", 10}, {"", 11}, {"", 12}, {"", 13}, {"currtp", 14}, {"currtsp", 15}, {"currtsphttp", 16}, {"curthru", 17}, {"curpkts", 18}, {"totbytes", 19}, {"totconns", 20}, {"", 21}, {"connlimit", 22}, {"thrulimit", 23}, {"moviedir", 24}, {"rtspip", 25}, {"rtspport", 26}, {"rtsptimeout", 27}, {"rtptimeout", 28}, {"secstobuffer", 29}, {"", 30}, {"accesslog", 31}, {"accesslogdir",32}, {"accesslogname", 33}, {"accessrollsize", 34}, {"accessrollinterval", 35}, {"", 36}, {"errorlog", 37}, {"errorlogdir", 38}, {"errorlogname", 39}, {"errorrollsize", 40}, {"errorrollinterval", 41}, {"errorloglevel", 42}, {"", 43}, {"assertbreak", 44}, {"autostart", 45}, {"totbytesupdateinterval", 46}, {"reflectordelay", 47}, {"reflectorbucketsize", 48}, {"historyinterval", 49}, {"outoffiledesc", 50}, {"numudpsockets", 51}, {"apiversion", 52}, {"numreliableudpbuffers", 53}, {"reliableudpwastedbytes", 54}, {"numtaskthreads", 55} }; const int kMaxFieldNum = 55; static char* kEmptyStr = "?"; char* thePrefStr = kEmptyStr; char buffer[1024]; (void)QTSS_Write(inStream, sResponseHeader, ::strlen(sResponseHeader), NULL, 0); if (refreshInterval > 0) { qtss_sprintf(buffer, "\n", refreshInterval); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } //qtss_sprintf(buffer, "\n"); //(void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); char *theHTML = "\n"; (void)QTSS_Write(inStream, theHTML, ::strlen(theHTML), NULL, 0); if (displayHelp) { #ifndef __MacOSX__ static StrPtrLen sHelpLine1("

Streaming Server Statistics Help

\n"); #else static StrPtrLen sHelpLine1("

QuickTime Streaming Server Statistics Help

\n"); #endif static StrPtrLen sHelpLine2("

Example:

\n"); static StrPtrLen sHelpLine3("

http://server/statsURL?help&refresh=15&fields=curtime,cpuload

\n"); static StrPtrLen sHelpLine4("\"?\" means that there are options being attached to the stats request.
\n"); static StrPtrLen sHelpLine5("\"&\" separates multiple stats options
\n
\n"); static StrPtrLen sHelpLine6("

The three possible parameters to stats are:

\n"); static StrPtrLen sHelpLine7("

\"help\" -- shows the help information you're reading right now.

\n"); static StrPtrLen sHelpLine8("

\"refresh=[n]\" -- tells the browser to automatically update the page every [n] seconds.

\n"); static StrPtrLen sHelpLine9("

\"fields=[fieldList]\" -- show only the fields specified in comma delimited [fieldList]

\n"); static StrPtrLen sHelpLine10("
The following fields are available for use with the \"fields\" option:

\n"); (void)QTSS_Write(inStream, sHelpLine1.Ptr, sHelpLine1.Len, NULL, 0); (void)QTSS_Write(inStream, sHelpLine2.Ptr, sHelpLine2.Len, NULL, 0); (void)QTSS_Write(inStream, sHelpLine3.Ptr, sHelpLine3.Len, NULL, 0); (void)QTSS_Write(inStream, sHelpLine4.Ptr, sHelpLine4.Len, NULL, 0); (void)QTSS_Write(inStream, sHelpLine5.Ptr, sHelpLine5.Len, NULL, 0); (void)QTSS_Write(inStream, sHelpLine6.Ptr, sHelpLine6.Len, NULL, 0); (void)QTSS_Write(inStream, sHelpLine7.Ptr, sHelpLine7.Len, NULL, 0); (void)QTSS_Write(inStream, sHelpLine8.Ptr, sHelpLine8.Len, NULL, 0); (void)QTSS_Write(inStream, sHelpLine9.Ptr, sHelpLine9.Len, NULL, 0); (void)QTSS_Write(inStream, sHelpLine10.Ptr, sHelpLine10.Len, NULL, 0); for (short i = 0; i < kMaxFieldNum; i++) { qtss_sprintf(buffer, "
%s
\n", kFieldIndexes[i].fieldName); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } static StrPtrLen sHelpLine11("


"); (void)QTSS_Write(inStream, sHelpLine11.Ptr, sHelpLine11.Len, NULL, 0); } StringParser fieldNamesParser(fieldList); StrPtrLen fieldName; int fieldNum = 0; do { if (fieldList != NULL) { fieldNum = 0; fieldNamesParser.ConsumeWord(&fieldName); for (short i = 0; i < kMaxFieldNum; i++) { if ( fieldName.Equal(StrPtrLen(kFieldIndexes[i].fieldName, ::strlen(kFieldIndexes[i].fieldName))) ) { fieldNum = kFieldIndexes[i].fieldIndex; break; } } } else { fieldNum++; if ( fieldNum > kMaxFieldNum ) fieldNum = 0; } UInt32 theLen = 0; switch (fieldNum) { case 1: { #if __MacOSX__ static StrPtrLen sStatsLine1("QuickTime Streaming Server Stats
\n"); (void)QTSS_Write(inStream, sStatsLine1.Ptr, sStatsLine1.Len, NULL, 0); #else static StrPtrLen sStatsLine1("Streaming Server Stats
\n"); (void)QTSS_Write(inStream, sStatsLine1.Ptr, sStatsLine1.Len, NULL, 0); #endif #if __MacOSX__ static StrPtrLen sStatsLine2("

QuickTime Streaming Server Statistics

\n"); (void)QTSS_Write(inStream, sStatsLine2.Ptr, sStatsLine2.Len, NULL, 0); #else static StrPtrLen sStatsLine2("

Streaming Server Statistics

\n"); (void)QTSS_Write(inStream, sStatsLine2.Ptr, sStatsLine2.Len, NULL, 0); #endif } break; case 2: { StrPtrLen theDNS; (void)QTSS_GetValuePtr(sServer, qtssSvrDefaultDNSName, 0, (void**)&theDNS.Ptr, &theDNS.Len); if ( theDNS.Ptr == NULL ) { // no DNS, try for the IP address only. (void)QTSS_GetValuePtr(sServer, qtssSvrDefaultIPAddr, 0, (void**)&theDNS.Ptr, &theDNS.Len); } if ( theDNS.Ptr != NULL ) { qtss_sprintf(buffer, "DNS Name (default): %s
\n", theDNS.Ptr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } } break; case 3: { char uptimebuffer[1024]; time_t curTime = ::time(NULL); qtss_sprintf(uptimebuffer, "Current Time: %s
\n", qtss_ctime(&curTime, buffer, sizeof(buffer))); (void)QTSS_Write(inStream, uptimebuffer, ::strlen(uptimebuffer), NULL, 0); time_t upTime = curTime - sStartupTime; #define kDaySeconds (24 * 60 * 60) #define kHourSeconds (60 * 60) #define kMinuteSeconds 60 UInt32 upTimeDays = upTime / kDaySeconds; UInt32 upTimeHours = (upTime % kDaySeconds) / kHourSeconds; UInt32 upTimeMinutes = (upTime % kHourSeconds) / kMinuteSeconds; UInt32 upTimeSeconds = (upTime % kMinuteSeconds); qtss_snprintf(uptimebuffer,sizeof(uptimebuffer), "Up Time Total Seconds: %"_U32BITARG_"
\n", upTime); uptimebuffer[sizeof(uptimebuffer) -1] = 0; (void)QTSS_Write(inStream, uptimebuffer, ::strlen(uptimebuffer), NULL, 0); qtss_snprintf(uptimebuffer,sizeof(uptimebuffer), "Up Time: %"_U32BITARG_" days %"_U32BITARG_" hours %"_U32BITARG_" minutes %"_U32BITARG_" seconds
\n", upTimeDays, upTimeHours,upTimeMinutes, upTimeSeconds); uptimebuffer[sizeof(uptimebuffer) -1] = 0; (void)QTSS_Write(inStream, uptimebuffer, ::strlen(uptimebuffer), NULL, 0); } break; case 4: { (void)QTSS_Write(inStream, "


", ::strlen("


"), NULL, 0); } break; case 5: { StrPtrLen theVersion; (void)QTSS_GetValuePtr(sServer, qtssSvrRTSPServerHeader, 0, (void**)&theVersion.Ptr, &theVersion.Len); Assert(theVersion.Ptr != NULL); if (theVersion.Len > 7) //Skip the "Server:" text theVersion.Ptr += 7; qtss_sprintf(buffer, "Server Version: %s
\n", theVersion.Ptr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 6: { StrPtrLen theBuildDate; (void)QTSS_GetValuePtr(sServer, qtssSvrServerBuildDate, 0, (void**)&theBuildDate.Ptr, &theBuildDate.Len); Assert(theBuildDate.Ptr != NULL); qtss_sprintf(buffer, "Server Build Date: %s
\n", theBuildDate.Ptr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 7: { char statusBuffer[1024]; const char* states[] = { "Starting Up", "Running", "Refusing Connections", "Fatal Error", "Shutting Down" }; QTSS_ServerState theState = qtssRunningState; theLen = sizeof(theState); (void)QTSS_GetValue(sServer, qtssSvrState, 0, &theState, &theLen); if (theState == qtssRunningState) { qtss_snprintf(statusBuffer, sizeof(statusBuffer), "Status: %s since %s
", states[theState], qtss_ctime(&sStartupTime,buffer,sizeof(buffer))); } else qtss_snprintf(statusBuffer,sizeof(statusBuffer), "Status: %s
", states[theState]); (void)QTSS_Write(inStream, statusBuffer, ::strlen(statusBuffer), NULL, 0); } break; case 8: { (void)QTSS_Write(inStream, "


", ::strlen("


"), NULL, 0); } break; case 9: { //NOOP } break; case 10: { //NOOP } break; case 11: { //NOOP } break; case 12: { /* struct vm_statistics vmStats = {}; if (vm_statistics (current_task (), &vmStats) != KERN_SUCCESS) memset (&stats, '\0', sizeof (vmStats)) ; */ (void)QTSS_Write(inStream, "


", ::strlen("


"), NULL, 0); } break; case 13: { (void)QTSS_Write(inStream, "


", ::strlen("


"), NULL, 0); } break; //********************************** case 14: { (void)QTSS_GetValueAsString(sServer, qtssRTPSvrCurConn, 0, &thePrefStr); qtss_sprintf(buffer, "Current RTP Connections: %s
\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 15: { (void)QTSS_GetValueAsString(sServer, qtssRTSPCurrentSessionCount, 0, &thePrefStr); qtss_sprintf(buffer, "Current RTSP Connections: %s
\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 16: { (void)QTSS_GetValueAsString(sServer, qtssRTSPHTTPCurrentSessionCount, 0, &thePrefStr); qtss_sprintf(buffer, "Current RTSP over HTTP Connections: %s
\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 17: { UInt32 curBandwidth = 0; theLen = sizeof(curBandwidth); (void)QTSS_GetValue(sServer, qtssRTPSvrCurBandwidth, 0, &curBandwidth, &theLen); qtss_sprintf(buffer, "Current Throughput: %"_U32BITARG_" kbits
\n", curBandwidth/1024); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 18: { (void)QTSS_GetValueAsString(sServer, qtssRTPSvrCurPackets, 0, &thePrefStr); qtss_sprintf(buffer, "Current Packets Per Second: %s
\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 19: { (void)QTSS_GetValueAsString(sServer, qtssRTPSvrTotalBytes, 0, &thePrefStr); qtss_sprintf(buffer, "Total Bytes Served: %s
\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 20: { (void)QTSS_GetValueAsString(sServer, qtssRTPSvrTotalConn, 0, &thePrefStr); qtss_sprintf(buffer, "Total Connections: %s
", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 21: { (void)QTSS_Write(inStream, "


", ::strlen("


"), NULL, 0); } break; //************************************** case 22: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsMaximumConnections, 0, &thePrefStr); qtss_sprintf(buffer, "Maximum Connections: %s
\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 23: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsMaximumBandwidth, 0, &thePrefStr); qtss_sprintf(buffer, "Maximum Throughput: %s Kbits
\n",thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 24: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsMovieFolder, 0, &thePrefStr); qtss_sprintf(buffer, "Movie Folder Path: %s
\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 25: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsRTSPIPAddr, 0, &thePrefStr); qtss_sprintf(buffer, "RTSP IP Address: %s
\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 26: { static StrPtrLen sRTSPPortsStart("RTSP Ports: "); (void)QTSS_Write(inStream, sRTSPPortsStart.Ptr, sRTSPPortsStart.Len, NULL, 0); StrPtrLen thePort; for (UInt32 theIndex = 0; true; theIndex++) { QTSS_Error theErr = QTSS_GetValuePtr(sServer, qtssSvrRTSPPorts, theIndex, (void**)&thePort.Ptr, &thePort.Len); if (theErr != QTSS_NoErr) break; Assert(thePort.Ptr != NULL); char temp[20]; qtss_sprintf(temp, "%u ", *(UInt16*)thePort.Ptr); (void)QTSS_Write(inStream, temp, ::strlen(temp), NULL, 0); } static StrPtrLen sRTSPPortsEnd("
\n"); (void)QTSS_Write(inStream, sRTSPPortsEnd.Ptr, sRTSPPortsEnd.Len, NULL, 0); } break; case 27: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsRTSPTimeout, 0, &thePrefStr); qtss_sprintf(buffer, "RTP Timeout: %s
\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 28: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsRTPTimeout, 0, &thePrefStr); qtss_sprintf(buffer, "RTP Timeout: %s
\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 29: { (void)QTSS_Write(inStream, "


", ::strlen("


"), NULL, 0); } break; case 30: { (void)QTSS_Write(inStream, "


", ::strlen("


"), NULL, 0); } break; case 31: { if ( sAccessLogPrefs != NULL ) { thePrefStr = GetPrefAsString(sAccessLogPrefs, "request_logging"); qtss_sprintf(buffer, "Access Logging: %s
\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } } break; case 32: { if ( sAccessLogPrefs != NULL ) { thePrefStr = GetPrefAsString(sAccessLogPrefs, "request_logfile_dir"); qtss_sprintf(buffer, "Access Log Directory: %s
\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } } break; case 33: { if ( sAccessLogPrefs != NULL ) { thePrefStr = GetPrefAsString(sAccessLogPrefs, "request_logfile_name"); qtss_sprintf(buffer, "Access Log Name: %s
\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } } break; case 34: { if ( sAccessLogPrefs != NULL ) { thePrefStr = GetPrefAsString(sAccessLogPrefs, "request_logfile_size"); qtss_sprintf(buffer, "Access Log Roll Size: %s
\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } } break; case 35: { if ( sAccessLogPrefs != NULL ) { thePrefStr = GetPrefAsString(sAccessLogPrefs, "request_logfile_interval"); qtss_sprintf(buffer, "Access Log Roll Interval (days): %s
", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } } break; case 36: { (void)QTSS_Write(inStream, "


", ::strlen("


"), NULL, 0); } break; case 37: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsErrorLogEnabled, 0, &thePrefStr); qtss_sprintf(buffer, "Error Logging: %s
\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 38: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsErrorLogDir, 0, &thePrefStr); qtss_sprintf(buffer, "Error Log Directory: %s
\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 39: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsErrorLogName, 0, &thePrefStr); qtss_sprintf(buffer, "Error Log Name: %s
\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 40: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsMaxErrorLogSize, 0, &thePrefStr); qtss_sprintf(buffer, "Error Log Roll Size: %s
\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 41: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsErrorRollInterval, 0, &thePrefStr); qtss_sprintf(buffer, "Error Log Roll Interval (days): %s
\n",thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 42: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsErrorLogVerbosity, 0, &thePrefStr); qtss_sprintf(buffer, "Error Log Verbosity: %s
", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 43: { (void)QTSS_Write(inStream, "


", ::strlen("


"), NULL, 0); } break; case 44: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsBreakOnAssert, 0, &thePrefStr); qtss_sprintf(buffer, "Break On Assert: %s
\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 45: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsAutoRestart, 0, &thePrefStr); qtss_sprintf(buffer, "AutoStart: %s
\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 46: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsTotalBytesUpdate, 0, &thePrefStr); qtss_sprintf(buffer, "Total Bytes Update Interval: %s
\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 47: { if (sReflectorPrefs != NULL) { thePrefStr = GetPrefAsString(sReflectorPrefs, "reflector_delay"); qtss_sprintf(buffer, "Reflector Delay Time: %s
\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } } break; case 48: { if (sReflectorPrefs != NULL) { thePrefStr = GetPrefAsString(sReflectorPrefs, "reflector_bucket_size"); qtss_sprintf(buffer, "Reflector Bucket Size: %s
\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } } break; case 49: { if ( sSvrControlPrefs != NULL) { thePrefStr = GetPrefAsString(sSvrControlPrefs, "history_update_interval"); qtss_sprintf(buffer, "History Update Interval: %s
\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } } break; case 50: { Bool16 isOutOfDescriptors = false; theLen = sizeof(isOutOfDescriptors); (void)QTSS_GetValue(sServer, qtssSvrIsOutOfDescriptors, 0, &isOutOfDescriptors, &theLen); qtss_sprintf(buffer, "Out of file descriptors: %d
\n", isOutOfDescriptors); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 51: { (void)QTSS_GetValueAsString(sServer, qtssRTPSvrNumUDPSockets, 0, &thePrefStr); qtss_sprintf(buffer, "Number of UDP sockets: %s
\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 52: { UInt32 apiVersion = 0; UInt32 size = sizeof(UInt32); (void)QTSS_GetValue(sServer, qtssServerAPIVersion, 0, &apiVersion, &size); qtss_sprintf(buffer, "API version: %d.%d
\n", (int)( (UInt32) (apiVersion & (UInt32) 0xFFFF0000L) >> 16), (int)(apiVersion &(UInt32) 0x0000FFFFL)); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 53: { UInt32 reliableUDPBuffers = 0; UInt32 blahSize = sizeof(reliableUDPBuffers); (void)QTSS_GetValue(sServer, qtssSvrNumReliableUDPBuffers, 0, &reliableUDPBuffers, &blahSize); qtss_sprintf(buffer, "Num Reliable UDP Retransmit Buffers: %"_U32BITARG_"
\n", reliableUDPBuffers); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 54: { UInt32 wastedBufSpace = 0; UInt32 blahSize2 = sizeof(wastedBufSpace); (void)QTSS_GetValue(sServer, qtssSvrReliableUDPWastageInBytes, 0, &wastedBufSpace, &blahSize2); qtss_sprintf(buffer, "Amount of buffer space being wasted in UDP Retrans buffers: %"_U32BITARG_"
\n", wastedBufSpace); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 55: { (void)QTSS_GetValueAsString(sServer, qtssSvrNumThreads, 0, &thePrefStr); qtss_sprintf(buffer, "Number of Task Threads: %s
\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; default: break; } //switch fieldNum if (fieldList != NULL && !fieldNamesParser.Expect(',')) fieldNum = 0; if (thePrefStr != kEmptyStr) delete [] thePrefStr; thePrefStr = kEmptyStr; } while (fieldNum != 0); theHTML = "\n"; (void)QTSS_Write(inStream, theHTML, ::strlen(theHTML), NULL, 0); } char* GetPrefAsString(QTSS_ModulePrefsObject inPrefsObject, char* inPrefName) { static StrPtrLen sEmpty(""); // // Get the attribute ID of this pref. QTSS_AttributeID theID = qtssIllegalAttrID; if(inPrefsObject != NULL) theID = QTSSModuleUtils::GetAttrID(inPrefsObject, inPrefName); char* theString = NULL; if(inPrefsObject != NULL) (void)QTSS_GetValueAsString(inPrefsObject, theID, 0, &theString); if (theString == NULL) theString = sEmpty.GetAsCString(); return theString; }