inline Bool16 HasAuthentication(StringParser *theFullRequestPtr, StrPtrLen* namePtr, StrPtrLen* passwordPtr, StrPtrLen* outAuthTypePtr) { // Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== Bool16 hasAuthentication = false; StrPtrLen strPtr; StrPtrLen authType; StrPtrLen authString; while (theFullRequestPtr->GetDataRemaining() > 0) { theFullRequestPtr->ConsumeWhitespace(); theFullRequestPtr->ConsumeUntilWhitespace(&strPtr); if ( strPtr.Len == 0 || !strPtr.Equal(StrPtrLen("Authorization:")) ) continue; theFullRequestPtr->ConsumeWhitespace(); theFullRequestPtr->ConsumeUntilWhitespace(&authType); if ( authType.Len == 0 ) continue; theFullRequestPtr->ConsumeWhitespace(); theFullRequestPtr->ConsumeUntil(&authString, StringParser::sEOLMask); if ( authString.Len == 0 ) continue; if (outAuthTypePtr != NULL) outAuthTypePtr->Set(authType.Ptr, authType.Len); if (authType.Equal(StrPtrLen("Basic") ) ) { (void) ParseAuthNameAndPassword(&authString,namePtr, passwordPtr); if (namePtr->Len == 0) continue; hasAuthentication = true; break; } else if (authType.Equal(sAuthRef) ) { namePtr->Set(NULL,0); passwordPtr->Set(authString.Ptr, authString.Len); hasAuthentication = true; break; } }; return hasAuthentication; }
void HTTPRequest:: CreateResponseHeader(HTTPStatusCode statusCode, HTTPVersion version) { // If we are creating a second response for the same request, make sure and // deallocate memory for old response and allocate fresh memory if (fResponseFormatter != NULL) { if(fResponseHeader->Ptr != NULL) delete fResponseHeader->Ptr; delete fResponseHeader; delete fResponseFormatter; } // Allocate memory for the response when you first create it char* responseString = NEW char[kMinHeaderSizeInBytes]; fResponseHeader = NEW StrPtrLen(responseString, kMinHeaderSizeInBytes); fResponseFormatter = NEW ResizeableStringFormatter(fResponseHeader->Ptr, fResponseHeader->Len); //make a partial header for the given version and status code PutStatusLine(fResponseFormatter, statusCode, version); Assert(fSvrHeader.Ptr != NULL); //fResponseFormatter->Put(fSvrHeader); //fResponseFormatter->PutEOL(); //AppendResponseHeader(httpServerHeader,&fSvrHeader); fResponseHeader->Len = fResponseFormatter->GetCurrentOffset(); }
inline Bool16 IsAdminRequest(StringParser *theFullRequestPtr) { Bool16 handleRequest = false; if (theFullRequestPtr != NULL) do { StrPtrLen strPtr; theFullRequestPtr->ConsumeWord(&strPtr); if ( !strPtr.Equal(StrPtrLen("GET")) ) break; //it's a "Get" request theFullRequestPtr->ConsumeWhitespace(); if ( !theFullRequestPtr->Expect('/') ) break; theFullRequestPtr->ConsumeWord(&strPtr); if ( strPtr.Len == 0 || !strPtr.Equal(StrPtrLen("modules") ) ) break; if (!theFullRequestPtr->Expect('/') ) break; theFullRequestPtr->ConsumeWord(&strPtr); if ( strPtr.Len == 0 || !strPtr.Equal(StrPtrLen("admin") ) ) break; handleRequest = true; } while (false); return handleRequest; }
// Parse out the URL from the HTTP GET line. Bool16 ParseURL(StrPtrLen& theRequest, char* outURL, UInt16 maxlen) { StringParser reqParse(&theRequest); StrPtrLen strPtr; ::memset(outURL, 0, maxlen); reqParse.ConsumeWord(&strPtr); if ( !strPtr.Equal(StrPtrLen("GET")) ) { return false; } reqParse.ConsumeWhitespace(); reqParse.ConsumeUntilWhitespace(&strPtr); if (strPtr.Len == 0) return false; else if ((UInt16)strPtr.Len > maxlen-1) strPtr.Len = maxlen-1; ::memcpy(outURL, strPtr.Ptr, strPtr.Len); return true; }
Bool16 IsHomeDirURL(StrPtrLen& theUrl) { StrPtrLen token = theUrl; token.Len = 2; return token.EqualIgnoreCase(StrPtrLen("/~")); }
// This determines if a URL in an HTTP request is actually // a server admin request. Bool16 IsAdminURL(StrPtrLen& theUrl) { StrPtrLen token = theUrl; token.Len = 15; return token.EqualIgnoreCase(StrPtrLen("/modules/admin/")); }
// This determines if an incoming request is an HTTP GET // request. Bool16 IsHTTPGet(StrPtrLen& theRequest) { StrPtrLen token = theRequest; token.Len = 3; return token.EqualIgnoreCase(StrPtrLen("GET")); }
* 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@ * */ #include "HTTPProtocol.h" StrPtrLen HTTPProtocol::sMethods[] = { StrPtrLen("GET"), StrPtrLen("HEAD"), StrPtrLen("POST"), StrPtrLen("OPTIONS"), StrPtrLen("PUT"), StrPtrLen("DELETE"), StrPtrLen("TRACE"), StrPtrLen("CONNECT"), }; HTTPMethod HTTPProtocol::GetMethod(const StrPtrLen* inMethodStr) { HTTPMethod theMethod = httpIllegalMethod; if (inMethodStr->Len == 0) return httpIllegalMethod;
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, "<META HTTP-EQUIV=Refresh CONTENT=%"_U32BITARG_">\n", refreshInterval); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } //qtss_sprintf(buffer, "<body text=\"#000000\" bgcolor=\"#C0C0C0\" link=\"#0000FF\" vlink=\"#551A8B\" alink=\"#0000FF\">\n"); //(void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); char *theHTML = "<HTML><BODY>\n"; (void)QTSS_Write(inStream, theHTML, ::strlen(theHTML), NULL, 0); if (displayHelp) { #ifndef __MacOSX__ static StrPtrLen sHelpLine1("<P><b>Streaming Server Statistics Help</b></P>\n"); #else static StrPtrLen sHelpLine1("<P><b>QuickTime Streaming Server Statistics Help</b></P>\n"); #endif static StrPtrLen sHelpLine2("<P>Example:</P>\n"); static StrPtrLen sHelpLine3("<BLOCKQUOTE><P>http://server/statsURL?help&refresh=15&fields=curtime,cpuload </P>\n"); static StrPtrLen sHelpLine4("\"?\" means that there are options being attached to the stats request.<BR>\n"); static StrPtrLen sHelpLine5("\"&\" separates multiple stats options<BR>\n<BR>\n"); static StrPtrLen sHelpLine6("<P>The three possible parameters to stats are:</P>\n"); static StrPtrLen sHelpLine7("<P>\"help\" -- shows the help information you're reading right now.</P>\n"); static StrPtrLen sHelpLine8("<P>\"refresh=[n]\" -- tells the browser to automatically update the page every [n] seconds.</P>\n"); static StrPtrLen sHelpLine9("<P>\"fields=[fieldList]\" -- show only the fields specified in comma delimited [fieldList]</P>\n"); static StrPtrLen sHelpLine10("<BLOCKQUOTE>The following fields are available for use with the \"fields\" option:</P><BLOCKQUOTE><DL>\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, "<DT><I>%s</I></DT>\n", kFieldIndexes[i].fieldName); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } static StrPtrLen sHelpLine11("</DL></BLOCKQUOTE></BLOCKQUOTE></BLOCKQUOTE><BR><P><HR>"); (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("<TITLE>QuickTime Streaming Server Stats</TITLE><BR>\n"); (void)QTSS_Write(inStream, sStatsLine1.Ptr, sStatsLine1.Len, NULL, 0); #else static StrPtrLen sStatsLine1("<TITLE>Streaming Server Stats</TITLE><BR>\n"); (void)QTSS_Write(inStream, sStatsLine1.Ptr, sStatsLine1.Len, NULL, 0); #endif #if __MacOSX__ static StrPtrLen sStatsLine2("<center><h1>QuickTime Streaming Server Statistics</h1></center>\n"); (void)QTSS_Write(inStream, sStatsLine2.Ptr, sStatsLine2.Len, NULL, 0); #else static StrPtrLen sStatsLine2("<center><h1>Streaming Server Statistics</h1></center>\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, "<b>DNS Name (default): </b> %s<BR>\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, "<b>Current Time: </b> %s<BR>\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), "<b>Up Time Total Seconds: </b> %"_U32BITARG_"<BR>\n", upTime); uptimebuffer[sizeof(uptimebuffer) -1] = 0; (void)QTSS_Write(inStream, uptimebuffer, ::strlen(uptimebuffer), NULL, 0); qtss_snprintf(uptimebuffer,sizeof(uptimebuffer), "<b>Up Time: </b> %"_U32BITARG_" days %"_U32BITARG_" hours %"_U32BITARG_" minutes %"_U32BITARG_" seconds <BR>\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, "<P><HR>", ::strlen("<P><HR>"), 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, "<b>Server Version: </b>%s<BR>\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, "<b>Server Build Date: </b> %s<BR>\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), "<b>Status: </b> %s since %s<BR>", states[theState], qtss_ctime(&sStartupTime,buffer,sizeof(buffer))); } else qtss_snprintf(statusBuffer,sizeof(statusBuffer), "<b>Status: </b> %s<BR>", states[theState]); (void)QTSS_Write(inStream, statusBuffer, ::strlen(statusBuffer), NULL, 0); } break; case 8: { (void)QTSS_Write(inStream, "<P><HR>", ::strlen("<P><HR>"), 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, "<P><HR>", ::strlen("<P><HR>"), NULL, 0); } break; case 13: { (void)QTSS_Write(inStream, "<P><HR>", ::strlen("<P><HR>"), NULL, 0); } break; //********************************** case 14: { (void)QTSS_GetValueAsString(sServer, qtssRTPSvrCurConn, 0, &thePrefStr); qtss_sprintf(buffer, "<b>Current RTP Connections: </b> %s<BR>\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 15: { (void)QTSS_GetValueAsString(sServer, qtssRTSPCurrentSessionCount, 0, &thePrefStr); qtss_sprintf(buffer, "<b>Current RTSP Connections: </b> %s<BR>\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 16: { (void)QTSS_GetValueAsString(sServer, qtssRTSPHTTPCurrentSessionCount, 0, &thePrefStr); qtss_sprintf(buffer, "<b>Current RTSP over HTTP Connections: </b> %s<BR>\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, "<b>Current Throughput: </b> %"_U32BITARG_" kbits<BR>\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, "<b>Current Packets Per Second: </b> %s <BR>\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 19: { (void)QTSS_GetValueAsString(sServer, qtssRTPSvrTotalBytes, 0, &thePrefStr); qtss_sprintf(buffer, "<b>Total Bytes Served: </b> %s<BR>\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 20: { (void)QTSS_GetValueAsString(sServer, qtssRTPSvrTotalConn, 0, &thePrefStr); qtss_sprintf(buffer, "<b>Total Connections: </b> %s<BR>", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 21: { (void)QTSS_Write(inStream, "<P><HR>", ::strlen("<P><HR>"), NULL, 0); } break; //************************************** case 22: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsMaximumConnections, 0, &thePrefStr); qtss_sprintf(buffer, "<b>Maximum Connections: </b> %s<BR>\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 23: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsMaximumBandwidth, 0, &thePrefStr); qtss_sprintf(buffer, "<b>Maximum Throughput: </b> %s Kbits<BR>\n",thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 24: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsMovieFolder, 0, &thePrefStr); qtss_sprintf(buffer, "<b>Movie Folder Path: </b> %s<BR>\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 25: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsRTSPIPAddr, 0, &thePrefStr); qtss_sprintf(buffer, "<b>RTSP IP Address: </b> %s<BR>\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 26: { static StrPtrLen sRTSPPortsStart("<b>RTSP Ports: </b> "); (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("<BR>\n"); (void)QTSS_Write(inStream, sRTSPPortsEnd.Ptr, sRTSPPortsEnd.Len, NULL, 0); } break; case 27: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsRTSPTimeout, 0, &thePrefStr); qtss_sprintf(buffer, "<b>RTP Timeout: </b> %s<BR>\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 28: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsRTPTimeout, 0, &thePrefStr); qtss_sprintf(buffer, "<b>RTP Timeout: </b> %s<BR>\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 29: { (void)QTSS_Write(inStream, "<P><HR>", ::strlen("<P><HR>"), NULL, 0); } break; case 30: { (void)QTSS_Write(inStream, "<P><HR>", ::strlen("<P><HR>"), NULL, 0); } break; case 31: { if ( sAccessLogPrefs != NULL ) { thePrefStr = GetPrefAsString(sAccessLogPrefs, "request_logging"); qtss_sprintf(buffer, "<b>Access Logging: </b> %s<BR>\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, "<b>Access Log Directory: </b> %s<BR>\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, "<b>Access Log Name: </b> %s<BR>\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, "<b>Access Log Roll Size: </b> %s<BR>\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, "<b>Access Log Roll Interval (days): </b> %s<BR>", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } } break; case 36: { (void)QTSS_Write(inStream, "<P><HR>", ::strlen("<P><HR>"), NULL, 0); } break; case 37: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsErrorLogEnabled, 0, &thePrefStr); qtss_sprintf(buffer, "<b>Error Logging: </b> %s<BR>\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 38: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsErrorLogDir, 0, &thePrefStr); qtss_sprintf(buffer, "<b>Error Log Directory: </b> %s<BR>\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 39: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsErrorLogName, 0, &thePrefStr); qtss_sprintf(buffer, "<b>Error Log Name: </b> %s<BR>\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 40: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsMaxErrorLogSize, 0, &thePrefStr); qtss_sprintf(buffer, "<b>Error Log Roll Size: </b> %s<BR>\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 41: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsErrorRollInterval, 0, &thePrefStr); qtss_sprintf(buffer, "<b>Error Log Roll Interval (days): </b> %s<BR>\n",thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 42: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsErrorLogVerbosity, 0, &thePrefStr); qtss_sprintf(buffer, "<b>Error Log Verbosity: </b> %s<BR>", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 43: { (void)QTSS_Write(inStream, "<P><HR>", ::strlen("<P><HR>"), NULL, 0); } break; case 44: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsBreakOnAssert, 0, &thePrefStr); qtss_sprintf(buffer, "<b>Break On Assert: </b> %s<BR>\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 45: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsAutoRestart, 0, &thePrefStr); qtss_sprintf(buffer, "<b>AutoStart: </b> %s<BR>\n", thePrefStr); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 46: { (void)QTSS_GetValueAsString(sServerPrefs, qtssPrefsTotalBytesUpdate, 0, &thePrefStr); qtss_sprintf(buffer, "<b>Total Bytes Update Interval: </b> %s<BR>\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, "<b>Reflector Delay Time: </b> %s<BR>\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, "<b>Reflector Bucket Size: </b> %s<BR>\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, "<b>History Update Interval: </b> %s<BR>\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, "<b>Out of file descriptors: </b> %d<BR>\n", isOutOfDescriptors); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 51: { (void)QTSS_GetValueAsString(sServer, qtssRTPSvrNumUDPSockets, 0, &thePrefStr); qtss_sprintf(buffer, "<b>Number of UDP sockets: </b> %s<BR>\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, "<b>API version: </b> %d.%d<BR>\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, "<b>Num Reliable UDP Retransmit Buffers: </b> %"_U32BITARG_"<BR>\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, "<b>Amount of buffer space being wasted in UDP Retrans buffers: </b> %"_U32BITARG_"<BR>\n", wastedBufSpace); (void)QTSS_Write(inStream, buffer, ::strlen(buffer), NULL, 0); } break; case 55: { (void)QTSS_GetValueAsString(sServer, qtssSvrNumThreads, 0, &thePrefStr); qtss_sprintf(buffer, "<b>Number of Task Threads: </b> %s<BR>\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 = "</BODY></HTML>\n"; (void)QTSS_Write(inStream, theHTML, ::strlen(theHTML), NULL, 0); }
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; }
QTSS_Error FilterRequest(QTSS_Filter_Params* inParams) { #if HTTP_FILE_DEBUGGING qtss_printf("FilterRequest\n"); #endif static Bool16 sFalse = false; QTSS_RTSPRequestObject theRequest = inParams->inRTSPRequest; // Initial state. StrPtrLen theFullRequest; StrPtrLen reqMethod; StrPtrLen reqStr; StrPtrLen httpVersion; (void)QTSS_GetValuePtr(theRequest, qtssRTSPReqFullRequest, 0, (void**)&theFullRequest.Ptr, &theFullRequest.Len); StringParser fullRequest(&theFullRequest); // Parsing the HTTP request fullRequest.ConsumeWord(&reqMethod); if ( !(reqMethod.Equal(StrPtrLen("GET")) || reqMethod.Equal(StrPtrLen("HEAD"))) ) // It's not a "Get" or a "Head" request return QTSS_NoErr; fullRequest.ConsumeWhitespace(); if ( !fullRequest.Expect('/') ) // Improperly formed request return QTSS_NoErr; fullRequest.ConsumeUntil(&reqStr, StringParser::sEOLWhitespaceMask); if( reqStr.Len == 0 ) //if a file or directory name is not given, return return QTSS_NoErr; if ( !reqStr.Equal(StrPtrLen("Popular.smil")) ) return QTSS_NoErr; // If it's a "Head" request send the Head response header back and just return if ( reqMethod.Equal(StrPtrLen("HEAD")) ) { QTSS_Write(theRequest, sResponseHeader, ::strlen(sResponseHeader), NULL, 0); return QTSS_NoErr; } // Create a buffer to store data. char theFileBuffer[8192]; char contentLength[256]; // Before sending any response, set keep alive to off for this connection // Regardless of what the client sends, the server always closes the connection after sending the file (void)QTSS_SetValue(theRequest, qtssRTSPReqRespKeepAlive, 0, &sFalse, sizeof(sFalse)); #if HTTP_FILE_DEBUGGING qtss_printf("Creating a smil file\n"); #endif // Create a ref movie buffer for the single file. It is of the form: // rtsptext\r // rtsp://servername/filepath char smilFileBuf[8192] = {0}; GenerateHotHitSMIL(smilFileBuf); qtss_sprintf(contentLength, "%lu", strlen(smilFileBuf)); // Allocate memory for theFileBuffer // Write the HTTP header prefix into the buffer ::strcpy(theFileBuffer, sRespHeaderPrefix.Ptr); ::strcat(theFileBuffer, sContentLengthHeaderTag.Ptr); // Write the remaining part of the HTTP header into the file buffer ::strcat(theFileBuffer, contentLength); ::strcat(theFileBuffer, sContentTypeHeaderTag.Ptr); ::strcat(theFileBuffer, sSmilMimeType.Ptr); ::strcat(theFileBuffer, "\r\n\r\n"); // Write the smil file created above to the file buffer ::strcat(theFileBuffer, smilFileBuf); // Write the contents of the file buffer to the request stream and return QTSS_Write(theRequest, theFileBuffer, strlen(theFileBuffer), NULL, 0); #if HTTP_FILE_DEBUGGING qtss_printf("Wrote the smil file to the request stream. Successful!\n"); #endif return QTSS_NoErr; }
*/ /* File: RTSPProtocol.cpp Contains: Implementation of class defined in RTSPProtocol.h */ #include <ctype.h> #include "RTSPProtocol.h" StrPtrLen RTSPProtocol::sRetrProtName("our-retransmit"); StrPtrLen RTSPProtocol::sMethods[] = { StrPtrLen("DESCRIBE"), StrPtrLen("SETUP"), StrPtrLen("TEARDOWN"), StrPtrLen("PLAY"), StrPtrLen("PAUSE"), StrPtrLen("OPTIONS"), StrPtrLen("ANNOUNCE"), StrPtrLen("GET_PARAMETER"), StrPtrLen("SET_PARAMETER"), StrPtrLen("REDIRECT"), StrPtrLen("RECORD") }; QTSS_RTSPMethod RTSPProtocol::GetMethod(const StrPtrLen &inMethodStr) {
int RtspRequest::ParseRtspPackage(char Buf[], int Size) //bool bReq { int ret = 0; StringArray_t saLine; StringPair_t spHeader; string Delim=CRLF; string sRequest(Buf, Size); U32 theHeader = 0; StringUtil::Trim(sRequest); StringUtil::Split(sRequest, Delim, saLine); //Request Line if(strncmp(saLine[0].c_str(), RTSPProtocol::GetVersionString(RTSPProtocol::k10Version).Ptr, RTSPProtocol::GetVersionString(RTSPProtocol::k10Version).Len) != 0) //bReq { m_bIsRequest = true; ret = ParseRequestLine(saLine[0]); if(ret < 0) { return -1; } } else { m_bIsRequest = false; ret = ParseStatusLine(saLine[0]); if(ret < 0) { return -1; } } //Parse Header for(int i=1; i<saLine.size(); i++) { StringUtil::Split(saLine[i], ':', spHeader); theHeader = RTSPProtocol::GetRequestHeader(StrPtrLen((char*)spHeader.first.c_str())); if(qtssIllegalHeader != theHeader) { StringUtil::Trim(spHeader.second); m_HeaderDict[theHeader] = spHeader.second; } //some headers require some special processing. If this code begins //to get out of control, we made need to come up with a function pointer table switch (theHeader) { case qtssSessionHeader: ParseSessionHeader(); break; case qtssCSeqHeader: ParseCSeqHeader(); break; case qtssTransportHeader: ParseTransportHeader(); break; case qtssRangeHeader: ParseRangeHeader(); break; case qtssContentLengthHeader: ParseContentLengthHeader();break; case qtssSpeedHeader: ParseSpeedHeader(); break; case qtssScaleHeader: ParseScaleHeader(); break; case qtssRequireHeader: ParseRequireHeader(); break; case ngodNoticeHeader: ParseNoticeHeader(); break; case ngodOnDemandSessionIdHeader: ParseOnDemandSessionIdHeader(); break; case ngodReasonHeader: ParseReasonHeader(); break; case ngodSessionGroupHeader: ParseSessionGroupHeader(); break; default: break; } } return 0; }
//Request-Line = Method SP Request-URI SP RTSP-Version CRLF int RtspRequest::ParseRequestLine(string& sReqLine) { int ret = 0; //StringArray_t saReqLineParam; m_Method = qtssIllegalMethod; #if 0 StringUtil::Split(sReqLine, ' ', saReqLineParam); if(saReqLineParam.size() == 3) { m_Method = RTSPProtocol::GetMethod(StrPtrLen(saReqLineParam[0].c_str())); if(qtssIllegalMethod != m_Method) { return -1;//qtssClientBadRequest; } ret = ParseRtspURI(saReqLineParam[1].c_str()); if(ret < 0) { return -1; } StrPtrLen RtspVer = RTSPProtocol::GetVersionString(RTSPProtocol::k10Version); if(strcmp(RtspVer.Ptr, saReqLineParam[2].c_str()) != 0) { return -1; } } #endif //first get the method StrPtrLen ReqLine((char*)sReqLine.c_str()); StringParser parser(&ReqLine); StrPtrLen theParsedData; parser.ConsumeWord(&theParsedData); //this->SetVal(qtssRTSPReqMethodStr, theParsedData.Ptr, theParsedData.Len); //THIS WORKS UNDER THE ASSUMPTION THAT: //valid HTTP/1.1 headers are: GET, HEAD, POST, PUT, OPTIONS, DELETE, TRACE m_Method = RTSPProtocol::GetMethod(theParsedData); if (m_Method == qtssIllegalMethod) return -1;//QTSSModuleUtils::SendErrorResponse(this, qtssClientBadRequest, qtssMsgBadRTSPMethod, &theParsedData); //no longer assume this is a space... instead, just consume whitespace parser.ConsumeWhitespace(); //now parse the uri ret = ParseRtspURI(parser); if (ret < 0) return -1; //no longer assume this is a space... instead, just consume whitespace parser.ConsumeWhitespace(); //if there is a version, consume the version string StrPtrLen versionStr; parser.ConsumeUntil(&versionStr, StringParser::sEOLMask); //check the version if (versionStr.Len < 0 || RTSPProtocol::k10Version != RTSPProtocol::GetVersion(versionStr)) return -1; //go past the end of line //if (!parser.ExpectEOL()) // return QTSSModuleUtils::SendErrorResponse(this, qtssClientBadRequest, qtssMsgNoRTSPVersion,&theParsedData); return 0;//QTSS_NoErr; }