liveMedia/include/RTSPCommon.hh File Reference

#include "Boolean.hh"
#include <Media.hh>

Include dependency graph for RTSPCommon.hh:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define _strncasecmp   strncasecmp
#define RTSP_PARAM_STRING_MAX   200

Functions

Boolean parseRTSPRequestString (char const *reqStr, unsigned reqStrSize, char *resultCmdName, unsigned resultCmdNameMaxSize, char *resultURLPreSuffix, unsigned resultURLPreSuffixMaxSize, char *resultURLSuffix, unsigned resultURLSuffixMaxSize, char *resultCSeq, unsigned resultCSeqMaxSize, char *resultSessionId, unsigned resultSessionIdMaxSize, unsigned &contentLength)
Boolean parseRangeParam (char const *paramStr, double &rangeStart, double &rangeEnd, char *&absStartTime, char *&absEndTime, Boolean &startTimeIsNow)
Boolean parseRangeHeader (char const *buf, double &rangeStart, double &rangeEnd, char *&absStartTime, char *&absEndTime, Boolean &startTimeIsNow)
Boolean parseScaleHeader (char const *buf, float &scale)
Boolean RTSPOptionIsSupported (char const *commandName, char const *optionsResponseString)
char const * dateHeader ()
void ignoreSigPipeOnSocket (int socketNum)


Define Documentation

#define _strncasecmp   strncasecmp

Definition at line 36 of file RTSPCommon.hh.

Referenced by RTSPClient::checkForHeader(), RTSPClient::handleGET_PARAMETERResponse(), RTSPClient::handleResponseBytes(), parseAuthorizationHeader(), parsePlayNowHeader(), parseRangeHeader(), parseRTSPRequestString(), RTSPClient::parseRTSPURL(), parseScaleHeader(), SIPClient::parseSIPURL(), SIPClient::parseSIPURLUsernamePassword(), parseTransportHeader(), parseTransportHeaderForREGISTER(), and RTSPClient::parseTransportParams().

#define RTSP_PARAM_STRING_MAX   200

Definition at line 39 of file RTSPCommon.hh.

Referenced by RTSPServer::RTSPClientConnection::handleCmd_DESCRIBE(), RTSPClient::handleIncomingRequest(), and RTSPServer::RTSPClientConnection::handleRequestBytes().


Function Documentation

char const* dateHeader (  ) 

Definition at line 343 of file RTSPCommon.cpp.

References DWORD, and NULL.

Referenced by RTSPServer::RTSPClientConnection::authenticationOK(), RTSPServer::RTSPClientConnection::handleCmd_bad(), RTSPServer::RTSPClientConnection::handleCmd_DESCRIBE(), RTSPServer::RTSPClientConnection::handleCmd_notSupported(), RTSPServer::RTSPClientConnection::handleCmd_OPTIONS(), RTSPServer::RTSPClientSession::handleCmd_PLAY(), RTSPServer::RTSPClientSession::handleCmd_SETUP(), RTSPServer::RTSPClientConnection::handleHTTPCmd_notFound(), RTSPServer::RTSPClientConnection::handleHTTPCmd_notSupported(), RTSPServer::RTSPClientConnection::handleHTTPCmd_OPTIONS(), RTSPServerSupportingHTTPStreaming::RTSPClientConnectionSupportingHTTPStreaming::handleHTTPCmd_StreamingGET(), RTSPServer::RTSPClientConnection::handleHTTPCmd_TunnelingGET(), and RTSPServer::RTSPClientConnection::setRTSPResponse().

00343                          {
00344   static char buf[200];
00345 #if !defined(_WIN32_WCE)
00346   time_t tt = time(NULL);
00347   strftime(buf, sizeof buf, "Date: %a, %b %d %Y %H:%M:%S GMT\r\n", gmtime(&tt));
00348 #else
00349   // WinCE apparently doesn't have "time()", "strftime()", or "gmtime()",
00350   // so generate the "Date:" header a different, WinCE-specific way.
00351   // (Thanks to Pierre l'Hussiez for this code)
00352   // RSF: But where is the "Date: " string?  This code doesn't look quite right...
00353   SYSTEMTIME SystemTime;
00354   GetSystemTime(&SystemTime);
00355   WCHAR dateFormat[] = L"ddd, MMM dd yyyy";
00356   WCHAR timeFormat[] = L"HH:mm:ss GMT\r\n";
00357   WCHAR inBuf[200];
00358   DWORD locale = LOCALE_NEUTRAL;
00359 
00360   int ret = GetDateFormat(locale, 0, &SystemTime,
00361                           (LPTSTR)dateFormat, (LPTSTR)inBuf, sizeof inBuf);
00362   inBuf[ret - 1] = ' ';
00363   ret = GetTimeFormat(locale, 0, &SystemTime,
00364                       (LPTSTR)timeFormat,
00365                       (LPTSTR)inBuf + ret, (sizeof inBuf) - ret);
00366   wcstombs(buf, inBuf, wcslen(inBuf));
00367 #endif
00368   return buf;
00369 }

void ignoreSigPipeOnSocket ( int  socketNum  ) 

Definition at line 371 of file RTSPCommon.cpp.

Referenced by RTSPClient::openConnection(), RTSPClient::responseHandlerForHTTP_GET1(), RTSPServer::RTSPServer(), and TCPStreamSink::TCPStreamSink().

00371                                           {
00372 #ifdef USE_SIGNALS
00373 #ifdef SO_NOSIGPIPE
00374   int set_option = 1;
00375   setsockopt(socketNum, SOL_SOCKET, SO_NOSIGPIPE, &set_option, sizeof set_option);
00376 #else
00377   signal(SIGPIPE, SIG_IGN);
00378 #endif
00379 #endif
00380 }

Boolean parseRangeHeader ( char const *  buf,
double &  rangeStart,
double &  rangeEnd,
char *&  absStartTime,
char *&  absEndTime,
Boolean startTimeIsNow 
)

Definition at line 272 of file RTSPCommon.cpp.

References _strncasecmp, False, and parseRangeParam().

Referenced by RTSPServer::RTSPClientSession::handleCmd_PLAY(), and RTSPServer::RTSPClientSession::handleCmd_SETUP().

00275                                                   {
00276   // First, find "Range:"
00277   while (1) {
00278     if (*buf == '\0') return False; // not found
00279     if (_strncasecmp(buf, "Range: ", 7) == 0) break;
00280     ++buf;
00281   }
00282 
00283   char const* fields = buf + 7;
00284   while (*fields == ' ') ++fields;
00285   return parseRangeParam(fields, rangeStart, rangeEnd, absStartTime, absEndTime, startTimeIsNow);
00286 }

Boolean parseRangeParam ( char const *  paramStr,
double &  rangeStart,
double &  rangeEnd,
char *&  absStartTime,
char *&  absEndTime,
Boolean startTimeIsNow 
)

Definition at line 217 of file RTSPCommon.cpp.

References False, NULL, Numeric, and True.

Referenced by RTSPClient::handlePLAYResponse(), and parseRangeHeader().

00220                                                  {
00221   delete[] absStartTime; delete[] absEndTime;
00222   absStartTime = absEndTime = NULL; // by default, unless "paramStr" is a "clock=..." string
00223   startTimeIsNow = False; // by default
00224   double start, end;
00225   int numCharsMatched1 = 0, numCharsMatched2 = 0, numCharsMatched3 = 0, numCharsMatched4 = 0;
00226   Locale l("C", Numeric);
00227   if (sscanf(paramStr, "npt = %lf - %lf", &start, &end) == 2) {
00228     rangeStart = start;
00229     rangeEnd = end;
00230   } else if (sscanf(paramStr, "npt = %n%lf -", &numCharsMatched1, &start) == 1) {
00231     if (paramStr[numCharsMatched1] == '-') {
00232       // special case for "npt = -<endtime>", which matches here:
00233       rangeStart = 0.0; startTimeIsNow = True;
00234       rangeEnd = -start;
00235     } else {
00236       rangeStart = start;
00237       rangeEnd = 0.0;
00238     }
00239   } else if (sscanf(paramStr, "npt = now - %lf", &end) == 1) {
00240       rangeStart = 0.0; startTimeIsNow = True;
00241       rangeEnd = end;
00242   } else if (sscanf(paramStr, "npt = now -%n", &numCharsMatched2) == 0 && numCharsMatched2 > 0) {
00243     rangeStart = 0.0; startTimeIsNow = True;
00244     rangeEnd = 0.0;
00245   } else if (sscanf(paramStr, "clock = %n", &numCharsMatched3) == 0 && numCharsMatched3 > 0) {
00246     rangeStart = rangeEnd = 0.0;
00247 
00248     char const* utcTimes = &paramStr[numCharsMatched3];
00249     size_t len = strlen(utcTimes) + 1;
00250     char* as = new char[len];
00251     char* ae = new char[len];
00252     int sscanfResult = sscanf(utcTimes, "%[^-]-%s", as, ae);
00253     if (sscanfResult == 2) {
00254       absStartTime = as;
00255       absEndTime = ae;
00256     } else if (sscanfResult == 1) {
00257       absStartTime = as;
00258       delete[] ae;
00259     } else {
00260       delete[] as; delete[] ae;
00261       return False;
00262     }
00263   } else if (sscanf(paramStr, "smtpe = %n", &numCharsMatched4) == 0 && numCharsMatched4 > 0) {
00264     // We accept "smtpe=" parameters, but currently do not interpret them.
00265   } else {
00266     return False; // The header is malformed
00267   }
00268 
00269   return True;
00270 }

Boolean parseRTSPRequestString ( char const *  reqStr,
unsigned  reqStrSize,
char *  resultCmdName,
unsigned  resultCmdNameMaxSize,
char *  resultURLPreSuffix,
unsigned  resultURLPreSuffixMaxSize,
char *  resultURLSuffix,
unsigned  resultURLSuffixMaxSize,
char *  resultCSeq,
unsigned  resultCSeqMaxSize,
char *  resultSessionId,
unsigned  resultSessionIdMaxSize,
unsigned &  contentLength 
)

Definition at line 57 of file RTSPCommon.cpp.

References _strncasecmp, decodeURL(), False, and True.

Referenced by RTSPClient::handleIncomingRequest(), and RTSPServer::RTSPClientConnection::handleRequestBytes().

00069                                                         {
00070   // This parser is currently rather dumb; it should be made smarter #####
00071 
00072   // "Be liberal in what you accept": Skip over any whitespace at the start of the request:
00073   unsigned i;
00074   for (i = 0; i < reqStrSize; ++i) {
00075     char c = reqStr[i];
00076     if (!(c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\0')) break;
00077   }
00078   if (i == reqStrSize) return False; // The request consisted of nothing but whitespace!
00079 
00080   // Then read everything up to the next space (or tab) as the command name:
00081   Boolean parseSucceeded = False;
00082   unsigned i1 = 0;
00083   for (; i1 < resultCmdNameMaxSize-1 && i < reqStrSize; ++i,++i1) {
00084     char c = reqStr[i];
00085     if (c == ' ' || c == '\t') {
00086       parseSucceeded = True;
00087       break;
00088     }
00089 
00090     resultCmdName[i1] = c;
00091   }
00092   resultCmdName[i1] = '\0';
00093   if (!parseSucceeded) return False;
00094 
00095   // Skip over the prefix of any "rtsp://" or "rtsp:/" URL that follows:
00096   unsigned j = i+1;
00097   while (j < reqStrSize && (reqStr[j] == ' ' || reqStr[j] == '\t')) ++j; // skip over any additional white space
00098   for (; (int)j < (int)(reqStrSize-8); ++j) {
00099     if ((reqStr[j] == 'r' || reqStr[j] == 'R')
00100         && (reqStr[j+1] == 't' || reqStr[j+1] == 'T')
00101         && (reqStr[j+2] == 's' || reqStr[j+2] == 'S')
00102         && (reqStr[j+3] == 'p' || reqStr[j+3] == 'P')
00103         && reqStr[j+4] == ':' && reqStr[j+5] == '/') {
00104       j += 6;
00105       if (reqStr[j] == '/') {
00106         // This is a "rtsp://" URL; skip over the host:port part that follows:
00107         ++j;
00108         while (j < reqStrSize && reqStr[j] != '/' && reqStr[j] != ' ') ++j;
00109       } else {
00110         // This is a "rtsp:/" URL; back up to the "/":
00111         --j;
00112       }
00113       i = j;
00114       break;
00115     }
00116   }
00117 
00118   // Look for the URL suffix (before the following "RTSP/"):
00119   parseSucceeded = False;
00120   for (unsigned k = i+1; (int)k < (int)(reqStrSize-5); ++k) {
00121     if (reqStr[k] == 'R' && reqStr[k+1] == 'T' &&
00122         reqStr[k+2] == 'S' && reqStr[k+3] == 'P' && reqStr[k+4] == '/') {
00123       while (--k >= i && reqStr[k] == ' ') {} // go back over all spaces before "RTSP/"
00124       unsigned k1 = k;
00125       while (k1 > i && reqStr[k1] != '/') --k1;
00126 
00127       // ASSERT: At this point
00128       //   i: first space or slash after "host" or "host:port"
00129       //   k: last non-space before "RTSP/"
00130       //   k1: last slash in the range [i,k]
00131 
00132       // The URL suffix comes from [k1+1,k]
00133       // Copy "resultURLSuffix":
00134       unsigned n = 0, k2 = k1+1;
00135       if (k2 <= k) {
00136         if (k - k1 + 1 > resultURLSuffixMaxSize) return False; // there's no room
00137         while (k2 <= k) resultURLSuffix[n++] = reqStr[k2++];
00138       }
00139       resultURLSuffix[n] = '\0';
00140 
00141       // The URL 'pre-suffix' comes from [i+1,k1-1]
00142       // Copy "resultURLPreSuffix":
00143       n = 0; k2 = i+1;
00144       if (k2+1 <= k1) {
00145         if (k1 - i > resultURLPreSuffixMaxSize) return False; // there's no room
00146         while (k2 <= k1-1) resultURLPreSuffix[n++] = reqStr[k2++];
00147       }
00148       resultURLPreSuffix[n] = '\0';
00149       decodeURL(resultURLPreSuffix);
00150 
00151       i = k + 7; // to go past " RTSP/"
00152       parseSucceeded = True;
00153       break;
00154     }
00155   }
00156   if (!parseSucceeded) return False;
00157 
00158   // Look for "CSeq:" (mandatory, case insensitive), skip whitespace,
00159   // then read everything up to the next \r or \n as 'CSeq':
00160   parseSucceeded = False;
00161   for (j = i; (int)j < (int)(reqStrSize-5); ++j) {
00162     if (_strncasecmp("CSeq:", &reqStr[j], 5) == 0) {
00163       j += 5;
00164       while (j < reqStrSize && (reqStr[j] ==  ' ' || reqStr[j] == '\t')) ++j;
00165       unsigned n;
00166       for (n = 0; n < resultCSeqMaxSize-1 && j < reqStrSize; ++n,++j) {
00167         char c = reqStr[j];
00168         if (c == '\r' || c == '\n') {
00169           parseSucceeded = True;
00170           break;
00171         }
00172 
00173         resultCSeq[n] = c;
00174       }
00175       resultCSeq[n] = '\0';
00176       break;
00177     }
00178   }
00179   if (!parseSucceeded) return False;
00180 
00181   // Look for "Session:" (optional, case insensitive), skip whitespace,
00182   // then read everything up to the next \r or \n as 'Session':
00183   resultSessionIdStr[0] = '\0'; // default value (empty string)
00184   for (j = i; (int)j < (int)(reqStrSize-8); ++j) {
00185     if (_strncasecmp("Session:", &reqStr[j], 8) == 0) {
00186       j += 8;
00187       while (j < reqStrSize && (reqStr[j] ==  ' ' || reqStr[j] == '\t')) ++j;
00188       unsigned n;
00189       for (n = 0; n < resultSessionIdStrMaxSize-1 && j < reqStrSize; ++n,++j) {
00190         char c = reqStr[j];
00191         if (c == '\r' || c == '\n') {
00192           break;
00193         }
00194 
00195         resultSessionIdStr[n] = c;
00196       }
00197       resultSessionIdStr[n] = '\0';
00198       break;
00199     }
00200   }
00201 
00202   // Also: Look for "Content-Length:" (optional, case insensitive)
00203   contentLength = 0; // default value
00204   for (j = i; (int)j < (int)(reqStrSize-15); ++j) {
00205     if (_strncasecmp("Content-Length:", &(reqStr[j]), 15) == 0) {
00206       j += 15;
00207       while (j < reqStrSize && (reqStr[j] ==  ' ' || reqStr[j] == '\t')) ++j;
00208       unsigned num;
00209       if (sscanf(&reqStr[j], "%u", &num) == 1) {
00210         contentLength = num;
00211       }
00212     }
00213   }
00214   return True;
00215 }

Boolean parseScaleHeader ( char const *  buf,
float &  scale 
)

Definition at line 288 of file RTSPCommon.cpp.

References _strncasecmp, False, and True.

Referenced by RTSPServer::RTSPClientSession::handleCmd_PLAY().

00288                                                         {
00289   // Initialize the result parameter to a default value:
00290   scale = 1.0;
00291 
00292   // First, find "Scale:"
00293   while (1) {
00294     if (*buf == '\0') return False; // not found
00295     if (_strncasecmp(buf, "Scale:", 6) == 0) break;
00296     ++buf;
00297   }
00298 
00299   char const* fields = buf + 6;
00300   while (*fields == ' ') ++fields;
00301   float sc;
00302   if (sscanf(fields, "%f", &sc) == 1) {
00303     scale = sc;
00304   } else {
00305     return False; // The header is malformed
00306   }
00307 
00308   return True;
00309 }

Boolean RTSPOptionIsSupported ( char const *  commandName,
char const *  optionsResponseString 
)

Definition at line 314 of file RTSPCommon.cpp.

References False, isSeparator(), NULL, and True.

Referenced by continueAfterOPTIONS().

00314                                                                                           {
00315   do {
00316     if (commandName == NULL || optionsResponseString == NULL) break;
00317 
00318     unsigned const commandNameLen = strlen(commandName);
00319     if (commandNameLen == 0) break;
00320 
00321     // "optionsResponseString" is assumed to be a list of command names, separated by " " and/or ",", ";", or ":"
00322     // Scan through these, looking for "commandName".
00323     while (1) {
00324       // Skip over separators:
00325       while (*optionsResponseString != '\0' && isSeparator(*optionsResponseString)) ++optionsResponseString;
00326       if (*optionsResponseString == '\0') break;
00327 
00328       // At this point, "optionsResponseString" begins with a command name (with perhaps a separator afterwads).
00329       if (strncmp(commandName, optionsResponseString, commandNameLen) == 0) {
00330         // We have at least a partial match here.
00331         optionsResponseString += commandNameLen;
00332         if (*optionsResponseString == '\0' || isSeparator(*optionsResponseString)) return True;
00333       }
00334 
00335       // No match.  Skip over the rest of the command name:
00336       while (*optionsResponseString != '\0' && !isSeparator(*optionsResponseString)) ++optionsResponseString;
00337     }
00338   } while (0);
00339 
00340   return False;
00341 }


Generated on Tue Mar 25 14:37:44 2014 for live by  doxygen 1.5.2