00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "RTSPOverHTTPServer.hh"
00024 #include "RTSPCommon.hh"
00025 #include <GroupsockHelper.hh>
00026
00027 #include <string.h>
00028 #if defined(__WIN32__) || defined(_WIN32) || defined(_QNX4)
00029 #define snprintf _snprintf
00030 #else
00031 #include <signal.h>
00032 #define USE_SIGNALS 1
00033 #endif
00034
00035
00036 #define DEBUG 1 //#####@@@@@
00038
00039 #define HTTP_PARAM_STRING_MAX 100
00040
00041 RTSPOverHTTPServer*
00042 RTSPOverHTTPServer::createNew(UsageEnvironment& env, Port ourHTTPPort,
00043 Port rtspServerPort, char const* rtspServerHostName) {
00044 int ourSocket = -1;
00045
00046 do {
00047 int ourSocket = setUpOurSocket(env, ourHTTPPort);
00048 if (ourSocket == -1) break;
00049
00050 return new RTSPOverHTTPServer(env, ourSocket, rtspServerPort, rtspServerHostName);
00051 } while (0);
00052
00053 if (ourSocket != -1) ::closeSocket(ourSocket);
00054 return NULL;
00055 }
00056
00057 #define LISTEN_BACKLOG_SIZE 20
00058
00059 int RTSPOverHTTPServer::setUpOurSocket(UsageEnvironment& env, Port& ourPort) {
00060 int ourSocket = -1;
00061
00062 do {
00063 NoReuse dummy;
00064
00065 ourSocket = setupStreamSocket(env, ourPort);
00066 if (ourSocket < 0) break;
00067
00068
00069 if (!increaseSendBufferTo(env, ourSocket, 50*1024)) break;
00070
00071
00072 if (listen(ourSocket, LISTEN_BACKLOG_SIZE) < 0) {
00073 env.setResultErrMsg("listen() failed: ");
00074 break;
00075 }
00076
00077 if (ourPort.num() == 0) {
00078
00079 if (!getSourcePort(env, ourSocket, ourPort)) break;
00080 }
00081
00082 return ourSocket;
00083 } while (0);
00084
00085 if (ourSocket != -1) ::closeSocket(ourSocket);
00086 return -1;
00087 }
00088
00089 RTSPOverHTTPServer
00090 ::RTSPOverHTTPServer(UsageEnvironment& env, int ourSocket,
00091 Port rtspServerPort, char const* rtspServerHostName)
00092 : Medium(env),
00093 fServerSocket(ourSocket),
00094 fRTSPServerPort(rtspServerPort), fRTSPServerHostName(strDup(rtspServerHostName)) {
00095 #ifdef USE_SIGNALS
00096
00097
00098 signal(SIGPIPE, SIG_IGN);
00099 #endif
00100
00101
00102 env.taskScheduler().turnOnBackgroundReadHandling(fServerSocket,
00103 (TaskScheduler::BackgroundHandlerProc*)&incomingConnectionHandler,
00104 this);
00105 }
00106
00107 RTSPOverHTTPServer::~RTSPOverHTTPServer() {
00108 delete[] fRTSPServerHostName;
00109 }
00110
00111 void RTSPOverHTTPServer::incomingConnectionHandler(void* instance, int ) {
00112 RTSPOverHTTPServer* server = (RTSPOverHTTPServer*)instance;
00113 server->incomingConnectionHandler1();
00114 }
00115
00116 void RTSPOverHTTPServer::incomingConnectionHandler1() {
00117 struct sockaddr_in clientAddr;
00118 SOCKLEN_T clientAddrLen = sizeof clientAddr;
00119 int clientSocket = accept(fServerSocket, (struct sockaddr*)&clientAddr,
00120 &clientAddrLen);
00121 if (clientSocket < 0) {
00122 int err = envir().getErrno();
00123 if (err != EWOULDBLOCK) {
00124 envir().setResultErrMsg("accept() failed: ");
00125 }
00126 return;
00127 }
00128 makeSocketNonBlocking(clientSocket);
00129 increaseSendBufferTo(envir(), clientSocket, 50*1024);
00130 #if defined(DEBUG) || defined(DEBUG_CONNECTIONS)
00131 fprintf(stderr, "accept()ed connection from %s\n", our_inet_ntoa(clientAddr.sin_addr));
00132 #endif
00133
00134
00135 new HTTPClientConnection(*this, clientSocket);
00136 }
00137
00138
00140
00141 RTSPOverHTTPServer::HTTPClientConnection
00142 ::HTTPClientConnection(RTSPOverHTTPServer& ourServer, int clientSocket)
00143 : fOurServer(ourServer), fClientSocket(clientSocket), fSessionIsActive(True) {
00144
00145 resetRequestBuffer();
00146 envir().taskScheduler().turnOnBackgroundReadHandling(fClientSocket,
00147 (TaskScheduler::BackgroundHandlerProc*)&incomingRequestHandler, this);
00148 }
00149
00150 RTSPOverHTTPServer::HTTPClientConnection
00151 ::~HTTPClientConnection() {
00152
00153 envir().taskScheduler().turnOffBackgroundReadHandling(fClientSocket);
00154
00155 ::closeSocket(fClientSocket);
00156 }
00157
00158 void RTSPOverHTTPServer::HTTPClientConnection
00159 ::incomingRequestHandler(void* instance, int ) {
00160 HTTPClientConnection* connection = (HTTPClientConnection*)instance;
00161 connection->incomingRequestHandler1();
00162 }
00163
00164 void RTSPOverHTTPServer::HTTPClientConnection::incomingRequestHandler1() {
00165 struct sockaddr_in dummy;
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
00173
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
00187 unsigned char *tmpPtr = ptr;
00188 if (fRequestBytesAlreadySeen > 0) --tmpPtr;
00189
00190 while (tmpPtr < &ptr[bytesRead-1]) {
00191 if (*tmpPtr == '\r' && *(tmpPtr+1) == '\n') {
00192 if (tmpPtr - fLastCRLF == 2) {
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;
00205
00206
00207
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();
00250 if (!fSessionIsActive) delete this;
00251 }
00252
00253 void RTSPOverHTTPServer::HTTPClientConnection::resetRequestBuffer() {
00254 fRequestBytesAlreadySeen = 0;
00255 fRequestBufferBytesLeft = sizeof fRequestBuffer;
00256 fLastCRLF = &fRequestBuffer[-3];
00257 }
00258
00259 Boolean RTSPOverHTTPServer::HTTPClientConnection::
00260 parseHTTPRequestString(char* resultCmdName,
00261 unsigned resultCmdNameMaxSize,
00262 char* sessionCookie,
00263 unsigned sessionCookieMaxSize,
00264 char* acceptStr,
00265 unsigned acceptStrMaxSize,
00266 char* contentTypeStr,
00267 unsigned contentTypeStrMaxSize) {
00268 return False;
00269 #if 0
00270
00271
00272
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
00288 unsigned j = i+1;
00289 while (j < reqStrSize && (reqStr[j] == ' ' || reqStr[j] == '\t')) ++j;
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
00299 ++j;
00300 while (j < reqStrSize && reqStr[j] != '/' && reqStr[j] != ' ') ++j;
00301 } else {
00302
00303 --j;
00304 }
00305 i = j;
00306 break;
00307 }
00308 }
00309
00310
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] == ' ') {}
00316 unsigned k1 = k;
00317 while (k1 > i && reqStr[k1] != '/' && reqStr[k1] != ' ') --k1;
00318
00319
00320
00321 if (k - k1 + 1 > resultURLSuffixMaxSize) return False;
00322 unsigned n = 0, k2 = k1+1;
00323 while (k2 <= k) resultURLSuffix[n++] = reqStr[k2++];
00324 resultURLSuffix[n] = '\0';
00325
00326
00327 unsigned k3 = --k1;
00328 while (k3 > i && reqStr[k3] != '/' && reqStr[k3] != ' ') --k3;
00329
00330
00331
00332 if (k1 - k3 + 1 > resultURLPreSuffixMaxSize) return False;
00333 n = 0; k2 = k3+1;
00334 while (k2 <= k1) resultURLPreSuffix[n++] = reqStr[k2++];
00335 resultURLPreSuffix[n] = '\0';
00336
00337 i = k + 7;
00338 parseSucceeded = True;
00339 break;
00340 }
00341 }
00342 if (!parseSucceeded) return False;
00343
00344
00345
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 }
00371
00372 static char const* allowedCommandNames = "GET, PUT";
00373
00374 void RTSPOverHTTPServer::HTTPClientConnection::handleCmd_bad() {
00375 snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
00376 "HTTP/1.1 400 Bad Request\r\nAllow: %s\r\n\r\n",
00377 allowedCommandNames);
00378 }