RTSPOverHTTPServer::HTTPClientConnection Class Reference

Collaboration diagram for RTSPOverHTTPServer::HTTPClientConnection:

Collaboration graph
[legend]

Public Member Functions

 HTTPClientConnection (RTSPOverHTTPServer &ourServer, int clientSocket)
virtual ~HTTPClientConnection ()

Private Member Functions

void incomingRequestHandler1 ()
UsageEnvironmentenvir ()
void resetRequestBuffer ()
Boolean parseHTTPRequestString (char *resultCmdName, unsigned resultCmdNameMaxSize, char *sessionCookie, unsigned sessionCookieMaxSize, char *acceptStr, unsigned acceptStrMaxSize, char *contentTypeStr, unsigned contentTypeStrMaxSize)
void handleCmd_bad ()

Static Private Member Functions

static void incomingRequestHandler (void *, int)

Private Attributes

RTSPOverHTTPServerfOurServer
int fClientSocket
unsigned char fRequestBuffer [HTTP_BUFFER_SIZE]
unsigned fRequestBytesAlreadySeen
unsigned fRequestBufferBytesLeft
unsigned char * fLastCRLF
unsigned char fResponseBuffer [HTTP_BUFFER_SIZE]
Boolean fSessionIsActive

Detailed Description

Definition at line 50 of file RTSPOverHTTPServer.hh.


Constructor & Destructor Documentation

RTSPOverHTTPServer::HTTPClientConnection::HTTPClientConnection ( RTSPOverHTTPServer ourServer,
int  clientSocket 
)

Definition at line 142 of file RTSPOverHTTPServer.cpp.

References envir(), fClientSocket, incomingRequestHandler(), resetRequestBuffer(), UsageEnvironment::taskScheduler(), and TaskScheduler::turnOnBackgroundReadHandling().

00143   : fOurServer(ourServer), fClientSocket(clientSocket), fSessionIsActive(True) {
00144   // Arrange to handle incoming requests:
00145   resetRequestBuffer();
00146   envir().taskScheduler().turnOnBackgroundReadHandling(fClientSocket,
00147                (TaskScheduler::BackgroundHandlerProc*)&incomingRequestHandler, this);
00148 }

RTSPOverHTTPServer::HTTPClientConnection::~HTTPClientConnection (  )  [virtual]

Definition at line 151 of file RTSPOverHTTPServer.cpp.

References closeSocket, Medium::envir(), UsageEnvironment::taskScheduler(), and TaskScheduler::turnOffBackgroundReadHandling().

00151                         {
00152   // Turn off background read handling:
00153   envir().taskScheduler().turnOffBackgroundReadHandling(fClientSocket);
00154 
00155   ::closeSocket(fClientSocket);
00156 }


Member Function Documentation

void RTSPOverHTTPServer::HTTPClientConnection::incomingRequestHandler ( void *  ,
int   
) [static, private]

Definition at line 159 of file RTSPOverHTTPServer.cpp.

References incomingRequestHandler1().

Referenced by HTTPClientConnection().

00159                                                      {
00160   HTTPClientConnection* connection = (HTTPClientConnection*)instance;
00161   connection->incomingRequestHandler1();
00162 }

void RTSPOverHTTPServer::HTTPClientConnection::incomingRequestHandler1 (  )  [private]

Definition at line 164 of file RTSPOverHTTPServer.cpp.

References envir(), False, fClientSocket, fLastCRLF, fRequestBuffer, fRequestBufferBytesLeft, fRequestBytesAlreadySeen, fResponseBuffer, fSessionIsActive, handleCmd_bad(), HTTP_PARAM_STRING_MAX, parseHTTPRequestString(), readSocket(), and resetRequestBuffer().

Referenced by incomingRequestHandler().

00164                                                                      {
00165   struct sockaddr_in dummy; // 'from' address, meaningless in this case
00166   Boolean endOfMsg = False;
00167   unsigned char* ptr = &fRequestBuffer[fRequestBytesAlreadySeen];
00168 
00169   int bytesRead = readSocket(envir(), fClientSocket,
00170                              ptr, fRequestBufferBytesLeft, dummy);
00171   if (bytesRead <= 0 || (unsigned)bytesRead >= fRequestBufferBytesLeft) {
00172     // Either the client socket has died, or the request was too big for us.
00173     // Terminate this connection:
00174 #ifdef DEBUG
00175     fprintf(stderr, "HTTPClientConnection[%p]::incomingRequestHandler1() read %d bytes (of %d); terminating connection!\n", this, bytesRead, fRequestBufferBytesLeft);
00176 #endif
00177     delete this;
00178     return;
00179   }
00180 #ifdef DEBUG
00181   ptr[bytesRead] = '\0';
00182   fprintf(stderr, "HTTPClientConnection[%p]::incomingRequestHandler1() read %d bytes:%s\n",
00183           this, bytesRead, ptr);
00184 #endif
00185 
00186   // Look for the end of the message: <CR><LF><CR><LF>
00187   unsigned char *tmpPtr = ptr;
00188   if (fRequestBytesAlreadySeen > 0) --tmpPtr;
00189   // in case the last read ended with a <CR>
00190   while (tmpPtr < &ptr[bytesRead-1]) {
00191     if (*tmpPtr == '\r' && *(tmpPtr+1) == '\n') {
00192       if (tmpPtr - fLastCRLF == 2) { // This is it:
00193         endOfMsg = 1;
00194         break;
00195       }
00196       fLastCRLF = tmpPtr;
00197     }
00198     ++tmpPtr;
00199   }
00200 
00201   fRequestBufferBytesLeft -= bytesRead;
00202   fRequestBytesAlreadySeen += bytesRead;
00203 
00204   if (!endOfMsg) return; // subsequent reads will be needed to complete the request
00205 
00206   // Parse the request string to get the (few) parameters that we care about,
00207   // then handle the command:
00208   fRequestBuffer[fRequestBytesAlreadySeen] = '\0';
00209   char cmdName[HTTP_PARAM_STRING_MAX];
00210   char sessionCookie[HTTP_PARAM_STRING_MAX];
00211   char acceptStr[HTTP_PARAM_STRING_MAX];
00212   char contentTypeStr[HTTP_PARAM_STRING_MAX];
00213   if (!parseHTTPRequestString(cmdName, sizeof cmdName,
00214                           sessionCookie, sizeof sessionCookie,
00215                           acceptStr, sizeof acceptStr,
00216                           contentTypeStr, sizeof contentTypeStr)) {
00217 #ifdef DEBUG
00218     fprintf(stderr, "parseHTTPRTSPRequestString() failed!\n");
00219 #endif
00220     handleCmd_bad();
00221   } else {
00222 #ifdef DEBUG
00223     fprintf(stderr, "parseHTTPRTSPRequestString() returned cmdName \"%s\", sessionCookie \"%s\", acceptStr \"%s\", contentTypeStr \"%s\"\n", cmdName, sessionCookie, acceptStr, contentTypeStr);
00224 #endif
00225 #if 0
00226     if (strcmp(cmdName, "OPTIONS") == 0) {
00227       handleCmd_OPTIONS(cseq);
00228     } else if (strcmp(cmdName, "DESCRIBE") == 0) {
00229       handleCmd_DESCRIBE(cseq, urlSuffix, (char const*)fRequestBuffer);
00230     } else if (strcmp(cmdName, "SETUP") == 0) {
00231       handleCmd_SETUP(cseq, urlPreSuffix, urlSuffix, (char const*)fRequestBuffer);
00232     } else if (strcmp(cmdName, "TEARDOWN") == 0
00233                || strcmp(cmdName, "PLAY") == 0
00234                || strcmp(cmdName, "PAUSE") == 0
00235                || strcmp(cmdName, "GET_PARAMETER") == 0) {
00236       handleCmd_withinSession(cmdName, urlPreSuffix, urlSuffix, cseq,
00237                               (char const*)fRequestBuffer);
00238     } else {
00239       handleCmd_notSupported(cseq);
00240     }
00241 #endif
00242   }
00243 
00244 #ifdef DEBUG
00245   fprintf(stderr, "sending response: %s", fResponseBuffer);
00246 #endif
00247   send(fClientSocket, (char const*)fResponseBuffer, strlen((char*)fResponseBuffer), 0);
00248 
00249   resetRequestBuffer(); // to prepare for any subsequent request
00250   if (!fSessionIsActive) delete this;
00251 }

UsageEnvironment& RTSPOverHTTPServer::HTTPClientConnection::envir (  )  [inline, private]

Definition at line 57 of file RTSPOverHTTPServer.hh.

References Medium::envir(), and fOurServer.

Referenced by HTTPClientConnection(), and incomingRequestHandler1().

00057 { return fOurServer.envir(); }

void RTSPOverHTTPServer::HTTPClientConnection::resetRequestBuffer (  )  [private]

Definition at line 253 of file RTSPOverHTTPServer.cpp.

References fLastCRLF, fRequestBuffer, fRequestBufferBytesLeft, and fRequestBytesAlreadySeen.

Referenced by HTTPClientConnection(), and incomingRequestHandler1().

00253                                                                 {
00254   fRequestBytesAlreadySeen = 0;
00255   fRequestBufferBytesLeft = sizeof fRequestBuffer;
00256   fLastCRLF = &fRequestBuffer[-3]; // hack
00257 }

Boolean RTSPOverHTTPServer::HTTPClientConnection::parseHTTPRequestString ( char *  resultCmdName,
unsigned  resultCmdNameMaxSize,
char *  sessionCookie,
unsigned  sessionCookieMaxSize,
char *  acceptStr,
unsigned  acceptStrMaxSize,
char *  contentTypeStr,
unsigned  contentTypeStrMaxSize 
) [private]

Definition at line 260 of file RTSPOverHTTPServer.cpp.

References False, and True.

Referenced by incomingRequestHandler1().

00267                                                    {
00268   return False; //#####@@@@@
00269 #if 0
00270   // This parser is currently rather dumb; it should be made smarter #####
00271 
00272   // Read everything up to the first space as the command name:
00273   Boolean parseSucceeded = False;
00274   unsigned i;
00275   for (i = 0; i < resultCmdNameMaxSize-1 && i < reqStrSize; ++i) {
00276     char c = reqStr[i];
00277     if (c == ' ' || c == '\t') {
00278       parseSucceeded = True;
00279       break;
00280     }
00281 
00282     resultCmdName[i] = c;
00283   }
00284   resultCmdName[i] = '\0';
00285   if (!parseSucceeded) return False;
00286 
00287   // Skip over the prefix of any "rtsp://" or "rtsp:/" URL that follows:
00288   unsigned j = i+1;
00289   while (j < reqStrSize && (reqStr[j] == ' ' || reqStr[j] == '\t')) ++j; // skip over any additional white space
00290    for (j = i+1; j < reqStrSize-8; ++j) {
00291      if ((reqStr[j] == 'r' || reqStr[j] == 'R')
00292          && (reqStr[j+1] == 't' || reqStr[j+1] == 'T')
00293          && (reqStr[j+2] == 's' || reqStr[j+2] == 'S')
00294          && (reqStr[j+3] == 'p' || reqStr[j+3] == 'P')
00295          && reqStr[j+4] == ':' && reqStr[j+5] == '/') {
00296        j += 6;
00297        if (reqStr[j] == '/') {
00298          // This is a "rtsp://" URL; skip over the host:port part that follows:
00299          ++j;
00300          while (j < reqStrSize && reqStr[j] != '/' && reqStr[j] != ' ') ++j;
00301        } else {
00302          // This is a "rtsp:/" URL; back up to the "/":
00303          --j;
00304        }
00305        i = j;
00306        break;
00307      }
00308    }
00309 
00310  // Look for the URL suffix (before the following "RTSP/"):
00311  parseSucceeded = False;
00312  for (unsigned k = i+1; k < reqStrSize-5; ++k) {
00313    if (reqStr[k] == 'R' && reqStr[k+1] == 'T' &&
00314        reqStr[k+2] == 'S' && reqStr[k+3] == 'P' && reqStr[k+4] == '/') {
00315      while (--k >= i && reqStr[k] == ' ') {} // go back over all spaces before "RTSP/"
00316       unsigned k1 = k;
00317       while (k1 > i && reqStr[k1] != '/' && reqStr[k1] != ' ') --k1;
00318       // the URL suffix comes from [k1+1,k]
00319 
00320       // Copy "resultURLSuffix":
00321       if (k - k1 + 1 > resultURLSuffixMaxSize) return False; // there's no room
00322       unsigned n = 0, k2 = k1+1;
00323       while (k2 <= k) resultURLSuffix[n++] = reqStr[k2++];
00324       resultURLSuffix[n] = '\0';
00325 
00326       // Also look for the URL 'pre-suffix' before this:
00327       unsigned k3 = --k1;
00328       while (k3 > i && reqStr[k3] != '/' && reqStr[k3] != ' ') --k3;
00329       // the URL pre-suffix comes from [k3+1,k1]
00330 
00331       // Copy "resultURLPreSuffix":
00332       if (k1 - k3 + 1 > resultURLPreSuffixMaxSize) return False; // there's no room
00333       n = 0; k2 = k3+1;
00334       while (k2 <= k1) resultURLPreSuffix[n++] = reqStr[k2++];
00335       resultURLPreSuffix[n] = '\0';
00336 
00337       i = k + 7; // to go past " RTSP/"
00338       parseSucceeded = True;
00339       break;
00340     }
00341   }
00342   if (!parseSucceeded) return False;
00343 
00344   // Look for "CSeq:", skip whitespace,
00345   // then read everything up to the next \r or \n as 'CSeq':
00346   parseSucceeded = False;
00347   for (j = i; j < reqStrSize-5; ++j) {
00348     if (reqStr[j] == 'C' && reqStr[j+1] == 'S' && reqStr[j+2] == 'e' &&
00349         reqStr[j+3] == 'q' && reqStr[j+4] == ':') {
00350       j += 5;
00351       unsigned n;
00352       while (j < reqStrSize && (reqStr[j] ==  ' ' || reqStr[j] == '\t')) ++j;
00353       for (n = 0; n < resultCSeqMaxSize-1 && j < reqStrSize; ++n,++j) {
00354         char c = reqStr[j];
00355         if (c == '\r' || c == '\n') {
00356           parseSucceeded = True;
00357           break;
00358         }
00359 
00360         resultCSeq[n] = c;
00361       }
00362       resultCSeq[n] = '\0';
00363       break;
00364     }
00365   }
00366   if (!parseSucceeded) return False;
00367 
00368   return True;
00369 #endif
00370 }

void RTSPOverHTTPServer::HTTPClientConnection::handleCmd_bad (  )  [private]

Definition at line 374 of file RTSPOverHTTPServer.cpp.

References fResponseBuffer.

Referenced by incomingRequestHandler1().

00374                                                            {
00375   snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
00376            "HTTP/1.1 400 Bad Request\r\nAllow: %s\r\n\r\n",
00377            allowedCommandNames);
00378 }


Field Documentation

RTSPOverHTTPServer& RTSPOverHTTPServer::HTTPClientConnection::fOurServer [private]

Definition at line 98 of file RTSPOverHTTPServer.hh.

Referenced by envir().

int RTSPOverHTTPServer::HTTPClientConnection::fClientSocket [private]

Definition at line 103 of file RTSPOverHTTPServer.hh.

Referenced by HTTPClientConnection(), and incomingRequestHandler1().

unsigned char RTSPOverHTTPServer::HTTPClientConnection::fRequestBuffer[HTTP_BUFFER_SIZE] [private]

Definition at line 108 of file RTSPOverHTTPServer.hh.

Referenced by incomingRequestHandler1(), and resetRequestBuffer().

unsigned RTSPOverHTTPServer::HTTPClientConnection::fRequestBytesAlreadySeen [private]

Definition at line 109 of file RTSPOverHTTPServer.hh.

Referenced by incomingRequestHandler1(), and resetRequestBuffer().

unsigned RTSPOverHTTPServer::HTTPClientConnection::fRequestBufferBytesLeft [private]

Definition at line 109 of file RTSPOverHTTPServer.hh.

Referenced by incomingRequestHandler1(), and resetRequestBuffer().

unsigned char* RTSPOverHTTPServer::HTTPClientConnection::fLastCRLF [private]

Definition at line 110 of file RTSPOverHTTPServer.hh.

Referenced by incomingRequestHandler1(), and resetRequestBuffer().

unsigned char RTSPOverHTTPServer::HTTPClientConnection::fResponseBuffer[HTTP_BUFFER_SIZE] [private]

Definition at line 111 of file RTSPOverHTTPServer.hh.

Referenced by handleCmd_bad(), and incomingRequestHandler1().

Boolean RTSPOverHTTPServer::HTTPClientConnection::fSessionIsActive [private]

Definition at line 112 of file RTSPOverHTTPServer.hh.

Referenced by incomingRequestHandler1().


The documentation for this class was generated from the following files:
Generated on Tue Oct 7 15:40:09 2008 for live by  doxygen 1.5.2