00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "RTSPServer.hh"
00022 #include "RTSPCommon.hh"
00023 #include <GroupsockHelper.hh>
00024
00025 #if defined(__WIN32__) || defined(_WIN32) || defined(_QNX4)
00026 #else
00027 #include <signal.h>
00028 #define USE_SIGNALS 1
00029 #endif
00030 #include <time.h>
00031
00032 #define RTPINFO_INCLUDE_RTPTIME 1
00033
00035
00036 RTSPServer*
00037 RTSPServer::createNew(UsageEnvironment& env, Port ourPort,
00038 UserAuthenticationDatabase* authDatabase,
00039 unsigned reclamationTestSeconds) {
00040 int ourSocket = -1;
00041
00042 do {
00043 int ourSocket = setUpOurSocket(env, ourPort);
00044 if (ourSocket == -1) break;
00045
00046 return new RTSPServer(env, ourSocket, ourPort, authDatabase,
00047 reclamationTestSeconds);
00048 } while (0);
00049
00050 if (ourSocket != -1) ::closeSocket(ourSocket);
00051 return NULL;
00052 }
00053
00054 Boolean RTSPServer::lookupByName(UsageEnvironment& env,
00055 char const* name,
00056 RTSPServer*& resultServer) {
00057 resultServer = NULL;
00058
00059 Medium* medium;
00060 if (!Medium::lookupByName(env, name, medium)) return False;
00061
00062 if (!medium->isRTSPServer()) {
00063 env.setResultMsg(name, " is not a RTSP server");
00064 return False;
00065 }
00066
00067 resultServer = (RTSPServer*)medium;
00068 return True;
00069 }
00070
00071 void RTSPServer::addServerMediaSession(ServerMediaSession* serverMediaSession) {
00072 if (serverMediaSession == NULL) return;
00073
00074 char const* sessionName = serverMediaSession->streamName();
00075 if (sessionName == NULL) sessionName = "";
00076 ServerMediaSession* existingSession
00077 = (ServerMediaSession*)
00078 (fServerMediaSessions->Add(sessionName,
00079 (void*)serverMediaSession));
00080 removeServerMediaSession(existingSession);
00081 }
00082
00083 ServerMediaSession* RTSPServer::lookupServerMediaSession(char const* streamName) {
00084 return (ServerMediaSession*)(fServerMediaSessions->Lookup(streamName));
00085 }
00086
00087 void RTSPServer::removeServerMediaSession(ServerMediaSession* serverMediaSession) {
00088 if (serverMediaSession == NULL) return;
00089
00090 fServerMediaSessions->Remove(serverMediaSession->streamName());
00091 if (serverMediaSession->referenceCount() == 0) {
00092 Medium::close(serverMediaSession);
00093 } else {
00094 serverMediaSession->deleteWhenUnreferenced() = True;
00095 }
00096 }
00097
00098 void RTSPServer::removeServerMediaSession(char const* streamName) {
00099 removeServerMediaSession(lookupServerMediaSession(streamName));
00100 }
00101
00102 char* RTSPServer::rtspURLPrefix(int clientSocket) const {
00103 struct sockaddr_in ourAddress;
00104 if (clientSocket < 0) {
00105
00106 ourAddress.sin_addr.s_addr = ReceivingInterfaceAddr != 0
00107 ? ReceivingInterfaceAddr
00108 : ourIPAddress(envir());
00109 } else {
00110 SOCKLEN_T namelen = sizeof ourAddress;
00111 getsockname(clientSocket, (struct sockaddr*)&ourAddress, &namelen);
00112 }
00113
00114 char urlBuffer[100];
00115
00116 portNumBits portNumHostOrder = ntohs(fServerPort.num());
00117 if (portNumHostOrder == 554 ) {
00118 sprintf(urlBuffer, "rtsp://%s/", our_inet_ntoa(ourAddress.sin_addr));
00119 } else {
00120 sprintf(urlBuffer, "rtsp://%s:%hu/",
00121 our_inet_ntoa(ourAddress.sin_addr), portNumHostOrder);
00122 }
00123
00124 return strDup(urlBuffer);
00125 }
00126
00127 char* RTSPServer
00128 ::rtspURL(ServerMediaSession const* serverMediaSession, int clientSocket) const {
00129 char* urlPrefix = rtspURLPrefix(clientSocket);
00130 char const* sessionName = serverMediaSession->streamName();
00131
00132 char* resultURL = new char[strlen(urlPrefix) + strlen(sessionName) + 1];
00133 sprintf(resultURL, "%s%s", urlPrefix, sessionName);
00134
00135 delete[] urlPrefix;
00136 return resultURL;
00137 }
00138
00139 #define LISTEN_BACKLOG_SIZE 20
00140
00141 int RTSPServer::setUpOurSocket(UsageEnvironment& env, Port& ourPort) {
00142 int ourSocket = -1;
00143
00144 do {
00145 ourSocket = setupStreamSocket(env, ourPort);
00146 if (ourSocket < 0) break;
00147
00148
00149 if (!increaseSendBufferTo(env, ourSocket, 50*1024)) break;
00150
00151
00152 if (listen(ourSocket, LISTEN_BACKLOG_SIZE) < 0) {
00153 env.setResultErrMsg("listen() failed: ");
00154 break;
00155 }
00156
00157 if (ourPort.num() == 0) {
00158
00159 if (!getSourcePort(env, ourSocket, ourPort)) break;
00160 }
00161
00162 return ourSocket;
00163 } while (0);
00164
00165 if (ourSocket != -1) ::closeSocket(ourSocket);
00166 return -1;
00167 }
00168
00169 Boolean RTSPServer
00170 ::specialClientAccessCheck(int , struct sockaddr_in& , char const* ) {
00171
00172 return True;
00173 }
00174
00175 RTSPServer::RTSPServer(UsageEnvironment& env,
00176 int ourSocket, Port ourPort,
00177 UserAuthenticationDatabase* authDatabase,
00178 unsigned reclamationTestSeconds)
00179 : Medium(env),
00180 fServerSocket(ourSocket), fServerPort(ourPort),
00181 fAuthDB(authDatabase), fReclamationTestSeconds(reclamationTestSeconds),
00182 fServerMediaSessions(HashTable::create(STRING_HASH_KEYS)),
00183 fSessionIdCounter(0) {
00184 #ifdef USE_SIGNALS
00185
00186
00187 signal(SIGPIPE, SIG_IGN);
00188 #endif
00189
00190
00191 env.taskScheduler().turnOnBackgroundReadHandling(fServerSocket,
00192 (TaskScheduler::BackgroundHandlerProc*)&incomingConnectionHandler,
00193 this);
00194 }
00195
00196 RTSPServer::~RTSPServer() {
00197
00198 envir().taskScheduler().turnOffBackgroundReadHandling(fServerSocket);
00199
00200 ::closeSocket(fServerSocket);
00201
00202
00203 while (1) {
00204 ServerMediaSession* serverMediaSession
00205 = (ServerMediaSession*)fServerMediaSessions->RemoveNext();
00206 if (serverMediaSession == NULL) break;
00207 removeServerMediaSession(serverMediaSession);
00208 }
00209
00210
00211 delete fServerMediaSessions;
00212 }
00213
00214 Boolean RTSPServer::isRTSPServer() const {
00215 return True;
00216 }
00217
00218 void RTSPServer::incomingConnectionHandler(void* instance, int ) {
00219 RTSPServer* server = (RTSPServer*)instance;
00220 server->incomingConnectionHandler1();
00221 }
00222
00223 void RTSPServer::incomingConnectionHandler1() {
00224 struct sockaddr_in clientAddr;
00225 SOCKLEN_T clientAddrLen = sizeof clientAddr;
00226 int clientSocket = accept(fServerSocket, (struct sockaddr*)&clientAddr,
00227 &clientAddrLen);
00228 if (clientSocket < 0) {
00229 int err = envir().getErrno();
00230 if (err != EWOULDBLOCK) {
00231 envir().setResultErrMsg("accept() failed: ");
00232 }
00233 return;
00234 }
00235 makeSocketNonBlocking(clientSocket);
00236 increaseSendBufferTo(envir(), clientSocket, 50*1024);
00237
00238 #if defined(DEBUG) || defined(DEBUG_CONNECTIONS)
00239 fprintf(stderr, "accept()ed connection from %s\n", our_inet_ntoa(clientAddr.sin_addr));
00240 #endif
00241
00242
00243 new RTSPClientSession(*this, ++fSessionIdCounter,
00244 clientSocket, clientAddr);
00245 }
00246
00247
00249
00250 RTSPServer::RTSPClientSession
00251 ::RTSPClientSession(RTSPServer& ourServer, unsigned sessionId,
00252 int clientSocket, struct sockaddr_in clientAddr)
00253 : fOurServer(ourServer), fOurSessionId(sessionId),
00254 fOurServerMediaSession(NULL),
00255 fClientSocket(clientSocket), fClientAddr(clientAddr),
00256 fLivenessCheckTask(NULL),
00257 fIsMulticast(False), fSessionIsActive(True), fStreamAfterSETUP(False),
00258 fTCPStreamIdCount(0), fNumStreamStates(0), fStreamStates(NULL) {
00259
00260 resetRequestBuffer();
00261 envir().taskScheduler().turnOnBackgroundReadHandling(fClientSocket,
00262 (TaskScheduler::BackgroundHandlerProc*)&incomingRequestHandler, this);
00263 noteLiveness();
00264 }
00265
00266 RTSPServer::RTSPClientSession::~RTSPClientSession() {
00267
00268 envir().taskScheduler().unscheduleDelayedTask(fLivenessCheckTask);
00269
00270
00271 envir().taskScheduler().turnOffBackgroundReadHandling(fClientSocket);
00272
00273 ::closeSocket(fClientSocket);
00274
00275 reclaimStreamStates();
00276
00277 if (fOurServerMediaSession != NULL) {
00278 fOurServerMediaSession->decrementReferenceCount();
00279 if (fOurServerMediaSession->referenceCount() == 0
00280 && fOurServerMediaSession->deleteWhenUnreferenced()) {
00281 fOurServer.removeServerMediaSession(fOurServerMediaSession);
00282 }
00283 }
00284 }
00285
00286 void RTSPServer::RTSPClientSession::reclaimStreamStates() {
00287 for (unsigned i = 0; i < fNumStreamStates; ++i) {
00288 if (fStreamStates[i].subsession != NULL) {
00289 fStreamStates[i].subsession->deleteStream(fOurSessionId,
00290 fStreamStates[i].streamToken);
00291 }
00292 }
00293 delete[] fStreamStates; fStreamStates = NULL;
00294 fNumStreamStates = 0;
00295 }
00296
00297 void RTSPServer::RTSPClientSession::resetRequestBuffer() {
00298 fRequestBytesAlreadySeen = 0;
00299 fRequestBufferBytesLeft = sizeof fRequestBuffer;
00300 fLastCRLF = &fRequestBuffer[-3];
00301 }
00302
00303 void RTSPServer::RTSPClientSession
00304 ::incomingRequestHandler(void* instance, int ) {
00305 RTSPClientSession* session = (RTSPClientSession*)instance;
00306 session->incomingRequestHandler1();
00307 }
00308
00309 void RTSPServer::RTSPClientSession::incomingRequestHandler1() {
00310 noteLiveness();
00311
00312 struct sockaddr_in dummy;
00313 Boolean endOfMsg = False;
00314 unsigned char* ptr = &fRequestBuffer[fRequestBytesAlreadySeen];
00315
00316 int bytesRead = readSocket(envir(), fClientSocket,
00317 ptr, fRequestBufferBytesLeft, dummy);
00318 if (bytesRead <= 0 || (unsigned)bytesRead >= fRequestBufferBytesLeft) {
00319
00320
00321 #ifdef DEBUG
00322 fprintf(stderr, "RTSPClientSession[%p]::incomingRequestHandler1() read %d bytes (of %d); terminating connection!\n", this, bytesRead, fRequestBufferBytesLeft);
00323 #endif
00324 delete this;
00325 return;
00326 }
00327 #ifdef DEBUG
00328 ptr[bytesRead] = '\0';
00329 fprintf(stderr, "RTSPClientSession[%p]::incomingRequestHandler1() read %d bytes:%s\n", this, bytesRead, ptr);
00330 #endif
00331
00332
00333 unsigned char *tmpPtr = ptr;
00334 if (fRequestBytesAlreadySeen > 0) --tmpPtr;
00335
00336 while (tmpPtr < &ptr[bytesRead-1]) {
00337 if (*tmpPtr == '\r' && *(tmpPtr+1) == '\n') {
00338 if (tmpPtr - fLastCRLF == 2) {
00339 endOfMsg = 1;
00340 break;
00341 }
00342 fLastCRLF = tmpPtr;
00343 }
00344 ++tmpPtr;
00345 }
00346
00347 fRequestBufferBytesLeft -= bytesRead;
00348 fRequestBytesAlreadySeen += bytesRead;
00349
00350 if (!endOfMsg) return;
00351
00352
00353
00354 fRequestBuffer[fRequestBytesAlreadySeen] = '\0';
00355 char cmdName[RTSP_PARAM_STRING_MAX];
00356 char urlPreSuffix[RTSP_PARAM_STRING_MAX];
00357 char urlSuffix[RTSP_PARAM_STRING_MAX];
00358 char cseq[RTSP_PARAM_STRING_MAX];
00359 if (!parseRTSPRequestString((char*)fRequestBuffer, fRequestBytesAlreadySeen,
00360 cmdName, sizeof cmdName,
00361 urlPreSuffix, sizeof urlPreSuffix,
00362 urlSuffix, sizeof urlSuffix,
00363 cseq, sizeof cseq)) {
00364 #ifdef DEBUG
00365 fprintf(stderr, "parseRTSPRequestString() failed!\n");
00366 #endif
00367 handleCmd_bad(cseq);
00368 } else {
00369 #ifdef DEBUG
00370 fprintf(stderr, "parseRTSPRequestString() returned cmdName \"%s\", urlPreSuffix \"%s\", urlSuffix \"%s\"\n", cmdName, urlPreSuffix, urlSuffix);
00371 #endif
00372 if (strcmp(cmdName, "OPTIONS") == 0) {
00373 handleCmd_OPTIONS(cseq);
00374 } else if (strcmp(cmdName, "DESCRIBE") == 0) {
00375 handleCmd_DESCRIBE(cseq, urlSuffix, (char const*)fRequestBuffer);
00376 } else if (strcmp(cmdName, "SETUP") == 0) {
00377 handleCmd_SETUP(cseq, urlPreSuffix, urlSuffix, (char const*)fRequestBuffer);
00378 } else if (strcmp(cmdName, "TEARDOWN") == 0
00379 || strcmp(cmdName, "PLAY") == 0
00380 || strcmp(cmdName, "PAUSE") == 0
00381 || strcmp(cmdName, "GET_PARAMETER") == 0) {
00382 handleCmd_withinSession(cmdName, urlPreSuffix, urlSuffix, cseq,
00383 (char const*)fRequestBuffer);
00384 } else {
00385 handleCmd_notSupported(cseq);
00386 }
00387 }
00388
00389 #ifdef DEBUG
00390 fprintf(stderr, "sending response: %s", fResponseBuffer);
00391 #endif
00392 send(fClientSocket, (char const*)fResponseBuffer, strlen((char*)fResponseBuffer), 0);
00393
00394 if (strcmp(cmdName, "SETUP") == 0 && fStreamAfterSETUP) {
00395
00396
00397 handleCmd_withinSession("PLAY", urlPreSuffix, urlSuffix, cseq,
00398 (char const*)fRequestBuffer);
00399 }
00400
00401 resetRequestBuffer();
00402 if (!fSessionIsActive) delete this;
00403 }
00404
00405
00406
00407
00408 static char const* dateHeader() {
00409 static char buf[200];
00410 #if !defined(_WIN32_WCE)
00411 time_t tt = time(NULL);
00412 strftime(buf, sizeof buf, "Date: %a, %b %d %Y %H:%M:%S GMT\r\n", gmtime(&tt));
00413 #else
00414
00415
00416
00417 SYSTEMTIME SystemTime;
00418 GetSystemTime(&SystemTime);
00419 WCHAR dateFormat[] = L"ddd, MMM dd yyyy";
00420 WCHAR timeFormat[] = L"HH:mm:ss GMT\r\n";
00421 WCHAR inBuf[200];
00422 DWORD locale = LOCALE_NEUTRAL;
00423
00424 int ret = GetDateFormat(locale, 0, &SystemTime,
00425 (LPTSTR)dateFormat, (LPTSTR)inBuf, sizeof inBuf);
00426 inBuf[ret - 1] = ' ';
00427 ret = GetTimeFormat(locale, 0, &SystemTime,
00428 (LPTSTR)timeFormat,
00429 (LPTSTR)inBuf + ret, (sizeof inBuf) - ret);
00430 wcstombs(buf, inBuf, wcslen(inBuf));
00431 #endif
00432 return buf;
00433 }
00434
00435 static char const* allowedCommandNames
00436 = "OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE";
00437
00438 void RTSPServer::RTSPClientSession::handleCmd_bad(char const* ) {
00439
00440 snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
00441 "RTSP/1.0 400 Bad Request\r\n%sAllow: %s\r\n\r\n",
00442 dateHeader(), allowedCommandNames);
00443 }
00444
00445 void RTSPServer::RTSPClientSession::handleCmd_notSupported(char const* cseq) {
00446 snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
00447 "RTSP/1.0 405 Method Not Allowed\r\nCSeq: %s\r\n%sAllow: %s\r\n\r\n",
00448 cseq, dateHeader(), allowedCommandNames);
00449 }
00450
00451 void RTSPServer::RTSPClientSession::handleCmd_notFound(char const* cseq) {
00452 snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
00453 "RTSP/1.0 404 Stream Not Found\r\nCSeq: %s\r\n%s\r\n",
00454 cseq, dateHeader());
00455 fSessionIsActive = False;
00456 }
00457
00458 void RTSPServer::RTSPClientSession::handleCmd_unsupportedTransport(char const* cseq) {
00459 snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
00460 "RTSP/1.0 461 Unsupported Transport\r\nCSeq: %s\r\n%s\r\n",
00461 cseq, dateHeader());
00462 fSessionIsActive = False;
00463 }
00464
00465 void RTSPServer::RTSPClientSession::handleCmd_OPTIONS(char const* cseq) {
00466 snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
00467 "RTSP/1.0 200 OK\r\nCSeq: %s\r\n%sPublic: %s\r\n\r\n",
00468 cseq, dateHeader(), allowedCommandNames);
00469 }
00470
00471 void RTSPServer::RTSPClientSession
00472 ::handleCmd_DESCRIBE(char const* cseq, char const* urlSuffix,
00473 char const* fullRequestStr) {
00474 char* sdpDescription = NULL;
00475 char* rtspURL = NULL;
00476 do {
00477 if (!authenticationOK("DESCRIBE", cseq, urlSuffix, fullRequestStr))
00478 break;
00479
00480
00481
00482
00483
00484
00485 ServerMediaSession* session = fOurServer.lookupServerMediaSession(urlSuffix);
00486 if (session == NULL) {
00487 handleCmd_notFound(cseq);
00488 break;
00489 }
00490
00491
00492 sdpDescription = session->generateSDPDescription();
00493 if (sdpDescription == NULL) {
00494
00495
00496 snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
00497 "RTSP/1.0 404 File Not Found, Or In Incorrect Format\r\n"
00498 "CSeq: %s\r\n"
00499 "%s\r\n",
00500 cseq,
00501 dateHeader());
00502 break;
00503 }
00504 unsigned sdpDescriptionSize = strlen(sdpDescription);
00505
00506
00507
00508
00509 rtspURL = fOurServer.rtspURL(session, fClientSocket);
00510
00511 snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
00512 "RTSP/1.0 200 OK\r\nCSeq: %s\r\n"
00513 "%s"
00514 "Content-Base: %s/\r\n"
00515 "Content-Type: application/sdp\r\n"
00516 "Content-Length: %d\r\n\r\n"
00517 "%s",
00518 cseq,
00519 dateHeader(),
00520 rtspURL,
00521 sdpDescriptionSize,
00522 sdpDescription);
00523 } while (0);
00524
00525 delete[] sdpDescription;
00526 delete[] rtspURL;
00527 }
00528
00529 typedef enum StreamingMode {
00530 RTP_UDP,
00531 RTP_TCP,
00532 RAW_UDP
00533 } StreamingMode;
00534
00535 static void parseTransportHeader(char const* buf,
00536 StreamingMode& streamingMode,
00537 char*& streamingModeString,
00538 char*& destinationAddressStr,
00539 u_int8_t& destinationTTL,
00540 portNumBits& clientRTPPortNum,
00541 portNumBits& clientRTCPPortNum,
00542 unsigned char& rtpChannelId,
00543 unsigned char& rtcpChannelId
00544 ) {
00545
00546 streamingMode = RTP_UDP;
00547 streamingModeString = NULL;
00548 destinationAddressStr = NULL;
00549 destinationTTL = 255;
00550 clientRTPPortNum = 0;
00551 clientRTCPPortNum = 1;
00552 rtpChannelId = rtcpChannelId = 0xFF;
00553
00554 portNumBits p1, p2;
00555 unsigned ttl, rtpCid, rtcpCid;
00556
00557
00558 while (1) {
00559 if (*buf == '\0') return;
00560 if (_strncasecmp(buf, "Transport: ", 11) == 0) break;
00561 ++buf;
00562 }
00563
00564
00565 char const* fields = buf + 11;
00566 char* field = strDupSize(fields);
00567 while (sscanf(fields, "%[^;]", field) == 1) {
00568 if (strcmp(field, "RTP/AVP/TCP") == 0) {
00569 streamingMode = RTP_TCP;
00570 } else if (strcmp(field, "RAW/RAW/UDP") == 0 ||
00571 strcmp(field, "MP2T/H2221/UDP") == 0) {
00572 streamingMode = RAW_UDP;
00573 streamingModeString = strDup(field);
00574 } else if (_strncasecmp(field, "destination=", 12) == 0) {
00575 delete[] destinationAddressStr;
00576 destinationAddressStr = strDup(field+12);
00577 } else if (sscanf(field, "ttl%u", &ttl) == 1) {
00578 destinationTTL = (u_int8_t)ttl;
00579 } else if (sscanf(field, "client_port=%hu-%hu", &p1, &p2) == 2) {
00580 clientRTPPortNum = p1;
00581 clientRTCPPortNum = p2;
00582 } else if (sscanf(field, "client_port=%hu", &p1) == 1) {
00583 clientRTPPortNum = p1;
00584 clientRTCPPortNum = streamingMode == RAW_UDP ? 0 : p1 + 1;
00585 } else if (sscanf(field, "interleaved=%u-%u", &rtpCid, &rtcpCid) == 2) {
00586 rtpChannelId = (unsigned char)rtpCid;
00587 rtcpChannelId = (unsigned char)rtcpCid;
00588 }
00589
00590 fields += strlen(field);
00591 while (*fields == ';') ++fields;
00592 if (*fields == '\0' || *fields == '\r' || *fields == '\n') break;
00593 }
00594 delete[] field;
00595 }
00596
00597 static Boolean parsePlayNowHeader(char const* buf) {
00598
00599 while (1) {
00600 if (*buf == '\0') return False;
00601 if (_strncasecmp(buf, "x-playNow:", 10) == 0) break;
00602 ++buf;
00603 }
00604
00605 return True;
00606 }
00607
00608 void RTSPServer::RTSPClientSession
00609 ::handleCmd_SETUP(char const* cseq,
00610 char const* urlPreSuffix, char const* urlSuffix,
00611 char const* fullRequestStr) {
00612
00613
00614 char const* streamName = urlPreSuffix;
00615 char const* trackId = urlSuffix;
00616
00617
00618
00619
00620 if (fOurServerMediaSession != NULL
00621 && strcmp(streamName, fOurServerMediaSession->streamName()) != 0) {
00622 fOurServerMediaSession = NULL;
00623 }
00624 if (fOurServerMediaSession == NULL) {
00625
00626
00627
00628 if (streamName[0] != '\0' ||
00629 fOurServer.lookupServerMediaSession("") != NULL) {
00630 } else {
00631 streamName = urlSuffix;
00632 trackId = NULL;
00633 }
00634 fOurServerMediaSession = fOurServer.lookupServerMediaSession(streamName);
00635 if (fOurServerMediaSession == NULL) {
00636 handleCmd_notFound(cseq);
00637 return;
00638 }
00639
00640 fOurServerMediaSession->incrementReferenceCount();
00641
00642
00643 reclaimStreamStates();
00644 ServerMediaSubsessionIterator iter(*fOurServerMediaSession);
00645 for (fNumStreamStates = 0; iter.next() != NULL; ++fNumStreamStates) {}
00646 fStreamStates = new struct streamState[fNumStreamStates];
00647 iter.reset();
00648 ServerMediaSubsession* subsession;
00649 for (unsigned i = 0; i < fNumStreamStates; ++i) {
00650 subsession = iter.next();
00651 fStreamStates[i].subsession = subsession;
00652 fStreamStates[i].streamToken = NULL;
00653 }
00654 }
00655
00656
00657 ServerMediaSubsession* subsession = NULL;
00658 unsigned streamNum;
00659 if (trackId != NULL && trackId[0] != '\0') {
00660 for (streamNum = 0; streamNum < fNumStreamStates; ++streamNum) {
00661 subsession = fStreamStates[streamNum].subsession;
00662 if (subsession != NULL && strcmp(trackId, subsession->trackId()) == 0) break;
00663 }
00664 if (streamNum >= fNumStreamStates) {
00665
00666 handleCmd_notFound(cseq);
00667 return;
00668 }
00669 } else {
00670
00671
00672 if (fNumStreamStates != 1) {
00673 handleCmd_bad(cseq);
00674 return;
00675 }
00676 streamNum = 0;
00677 subsession = fStreamStates[streamNum].subsession;
00678 }
00679
00680
00681
00682
00683 StreamingMode streamingMode;
00684 char* streamingModeString = NULL;
00685 char* clientsDestinationAddressStr;
00686 u_int8_t clientsDestinationTTL;
00687 portNumBits clientRTPPortNum, clientRTCPPortNum;
00688 unsigned char rtpChannelId, rtcpChannelId;
00689 parseTransportHeader(fullRequestStr, streamingMode, streamingModeString,
00690 clientsDestinationAddressStr, clientsDestinationTTL,
00691 clientRTPPortNum, clientRTCPPortNum,
00692 rtpChannelId, rtcpChannelId);
00693 if (streamingMode == RTP_TCP && rtpChannelId == 0xFF) {
00694
00695
00696
00697 rtpChannelId = fTCPStreamIdCount; rtcpChannelId = fTCPStreamIdCount+1;
00698 }
00699 fTCPStreamIdCount += 2;
00700
00701 Port clientRTPPort(clientRTPPortNum);
00702 Port clientRTCPPort(clientRTCPPortNum);
00703
00704
00705
00706 float rangeStart = 0.0, rangeEnd = 0.0;
00707 fStreamAfterSETUP = parseRangeHeader(fullRequestStr, rangeStart, rangeEnd) ||
00708 parsePlayNowHeader(fullRequestStr);
00709
00710
00711 int tcpSocketNum = streamingMode == RTP_TCP ? fClientSocket : -1;
00712 netAddressBits destinationAddress = 0;
00713 u_int8_t destinationTTL = 255;
00714 #ifdef RTSP_ALLOW_CLIENT_DESTINATION_SETTING
00715 if (clientsDestinationAddressStr != NULL) {
00716
00717
00718
00719
00720 destinationAddress = our_inet_addr(clientsDestinationAddressStr);
00721 }
00722
00723 destinationTTL = clientsDestinationTTL;
00724 #endif
00725 delete[] clientsDestinationAddressStr;
00726 Port serverRTPPort(0);
00727 Port serverRTCPPort(0);
00728 subsession->getStreamParameters(fOurSessionId, fClientAddr.sin_addr.s_addr,
00729 clientRTPPort, clientRTCPPort,
00730 tcpSocketNum, rtpChannelId, rtcpChannelId,
00731 destinationAddress, destinationTTL, fIsMulticast,
00732 serverRTPPort, serverRTCPPort,
00733 fStreamStates[streamNum].streamToken);
00734 struct in_addr destinationAddr; destinationAddr.s_addr = destinationAddress;
00735 char* destAddrStr = strDup(our_inet_ntoa(destinationAddr));
00736 struct sockaddr_in sourceAddr; SOCKLEN_T namelen = sizeof sourceAddr;
00737 getsockname(fClientSocket, (struct sockaddr*)&sourceAddr, &namelen);
00738 char* sourceAddrStr = strDup(our_inet_ntoa(sourceAddr.sin_addr));
00739 if (fIsMulticast) {
00740 switch (streamingMode) {
00741 case RTP_UDP:
00742 snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
00743 "RTSP/1.0 200 OK\r\n"
00744 "CSeq: %s\r\n"
00745 "%s"
00746 "Transport: RTP/AVP;multicast;destination=%s;source=%s;port=%d-%d;ttl=%d\r\n"
00747 "Session: %d\r\n\r\n",
00748 cseq,
00749 dateHeader(),
00750 destAddrStr, sourceAddrStr, ntohs(serverRTPPort.num()), ntohs(serverRTCPPort.num()), destinationTTL,
00751 fOurSessionId);
00752 break;
00753 case RTP_TCP:
00754
00755 handleCmd_unsupportedTransport(cseq);
00756 break;
00757 case RAW_UDP:
00758 snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
00759 "RTSP/1.0 200 OK\r\n"
00760 "CSeq: %s\r\n"
00761 "%s"
00762 "Transport: %s;multicast;destination=%s;source=%s;port=%d;ttl=%d\r\n"
00763 "Session: %d\r\n\r\n",
00764 cseq,
00765 dateHeader(),
00766 streamingModeString, destAddrStr, sourceAddrStr, ntohs(serverRTPPort.num()), destinationTTL,
00767 fOurSessionId);
00768 break;
00769 }
00770 } else {
00771 switch (streamingMode) {
00772 case RTP_UDP: {
00773 snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
00774 "RTSP/1.0 200 OK\r\n"
00775 "CSeq: %s\r\n"
00776 "%s"
00777 "Transport: RTP/AVP;unicast;destination=%s;source=%s;client_port=%d-%d;server_port=%d-%d\r\n"
00778 "Session: %d\r\n\r\n",
00779 cseq,
00780 dateHeader(),
00781 destAddrStr, sourceAddrStr, ntohs(clientRTPPort.num()), ntohs(clientRTCPPort.num()), ntohs(serverRTPPort.num()), ntohs(serverRTCPPort.num()),
00782 fOurSessionId);
00783 break;
00784 }
00785 case RTP_TCP: {
00786 snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
00787 "RTSP/1.0 200 OK\r\n"
00788 "CSeq: %s\r\n"
00789 "%s"
00790 "Transport: RTP/AVP/TCP;unicast;destination=%s;source=%s;interleaved=%d-%d\r\n"
00791 "Session: %d\r\n\r\n",
00792 cseq,
00793 dateHeader(),
00794 destAddrStr, sourceAddrStr, rtpChannelId, rtcpChannelId,
00795 fOurSessionId);
00796 break;
00797 }
00798 case RAW_UDP: {
00799 snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
00800 "RTSP/1.0 200 OK\r\n"
00801 "CSeq: %s\r\n"
00802 "%s"
00803 "Transport: %s;unicast;destination=%s;source=%s;client_port=%d;server_port=%d\r\n"
00804 "Session: %d\r\n\r\n",
00805 cseq,
00806 dateHeader(),
00807 streamingModeString, destAddrStr, sourceAddrStr, ntohs(clientRTPPort.num()), ntohs(serverRTPPort.num()),
00808 fOurSessionId);
00809 break;
00810 }
00811 }
00812 }
00813 delete[] destAddrStr; delete[] sourceAddrStr; delete[] streamingModeString;
00814 }
00815
00816 void RTSPServer::RTSPClientSession
00817 ::handleCmd_withinSession(char const* cmdName,
00818 char const* urlPreSuffix, char const* urlSuffix,
00819 char const* cseq, char const* fullRequestStr) {
00820
00821
00822
00823
00824
00825
00826
00827 if (fOurServerMediaSession == NULL) {
00828 handleCmd_notSupported(cseq);
00829 return;
00830 }
00831 ServerMediaSubsession* subsession;
00832 if (urlSuffix[0] != '\0' &&
00833 strcmp(fOurServerMediaSession->streamName(), urlPreSuffix) == 0) {
00834
00835
00836 ServerMediaSubsessionIterator iter(*fOurServerMediaSession);
00837 while ((subsession = iter.next()) != NULL) {
00838 if (strcmp(subsession->trackId(), urlSuffix) == 0) break;
00839 }
00840 if (subsession == NULL) {
00841 handleCmd_notFound(cseq);
00842 return;
00843 }
00844 } else if (strcmp(fOurServerMediaSession->streamName(), urlSuffix) == 0 ||
00845 strcmp(fOurServerMediaSession->streamName(), urlPreSuffix) == 0) {
00846
00847 subsession = NULL;
00848 } else {
00849 handleCmd_notFound(cseq);
00850 return;
00851 }
00852
00853 if (strcmp(cmdName, "TEARDOWN") == 0) {
00854 handleCmd_TEARDOWN(subsession, cseq);
00855 } else if (strcmp(cmdName, "PLAY") == 0) {
00856 handleCmd_PLAY(subsession, cseq, fullRequestStr);
00857 } else if (strcmp(cmdName, "PAUSE") == 0) {
00858 handleCmd_PAUSE(subsession, cseq);
00859 } else if (strcmp(cmdName, "GET_PARAMETER") == 0) {
00860 handleCmd_GET_PARAMETER(subsession, cseq, fullRequestStr);
00861 }
00862 }
00863
00864 void RTSPServer::RTSPClientSession
00865 ::handleCmd_TEARDOWN(ServerMediaSubsession* , char const* cseq) {
00866 snprintf((char*)fResponseBuffer, sizeof fResponseBuffer,
00867 "RTSP/1.0 200 OK\r\nCSeq: %s\r\n%s\r\n",
00868 cseq, dateHeader());
00869 fSessionIsActive = False;
00870 }
00871
00872 static Boolean parseScaleHeader(char const* buf, float& scale) {
00873
00874 scale = 1.0;
00875
00876
00877 while (1) {
00878 if (*buf == '\0') return False;
00879 if (_strncasecmp(buf, "Scale: ", 7) == 0) break;
00880 ++buf;
00881 }
00882
00883
00884 char const* fields = buf + 7;
00885 while (*fields == ' ') ++fields;
00886 float sc;
00887 if (sscanf(fields, "%f", &sc) == 1) {
00888 scale = sc;
00889 } else {
00890 return False;
00891 }
00892
00893 return True;
00894 }
00895
00896 void RTSPServer::RTSPClientSession
00897 ::handleCmd_PLAY(ServerMediaSubsession* subsession, char const* cseq,
00898 char const* fullRequestStr) {
00899 char* rtspURL = fOurServer.rtspURL(fOurServerMediaSession, fClientSocket);
00900 unsigned rtspURLSize = strlen(rtspURL);
00901
00903 float scale;
00904 Boolean sawScaleHeader = parseScaleHeader(fullRequestStr, scale);
00905
00906
00907 if (subsession == NULL ) {
00908 fOurServerMediaSession->testScaleFactor(scale);
00909 } else {
00910 subsession->testScaleFactor(scale);
00911 }
00912
00913 char buf[100];
00914 char* scaleHeader;
00915 if (!sawScaleHeader) {
00916 buf[0] = '\0';
00917 } else {
00918 sprintf(buf, "Scale: %f\r\n", scale);
00919 }
00920 scaleHeader = strDup(buf);
00921
00923 float rangeStart = 0.0, rangeEnd = 0.0;
00924 Boolean sawRangeHeader = parseRangeHeader(fullRequestStr, rangeStart, rangeEnd);
00925
00926
00927
00928 float duration = subsession == NULL
00929 ? fOurServerMediaSession->duration() : subsession->duration();
00930 if (duration < 0.0) {
00931
00932
00933 duration = -duration;
00934 }
00935
00936 if (rangeEnd < 0.0 || rangeEnd > duration) rangeEnd = duration;
00937 if (rangeStart < 0.0) {
00938 rangeStart = 0.0;
00939 } else if (rangeEnd > 0.0 && scale > 0.0 && rangeStart > rangeEnd) {
00940 rangeStart = rangeEnd;
00941 }
00942
00943 char* rangeHeader;
00944 if (!sawRangeHeader) {
00945 buf[0] = '\0';
00946 } else if (rangeEnd == 0.0 && scale >= 0.0) {
00947 sprintf(buf, "Range: npt=%.3f-\r\n", rangeStart);
00948 } else {
00949 sprintf(buf, "Range: npt=%.3f-%.3f\r\n", rangeStart, rangeEnd);
00950 }
00951 rangeHeader = strDup(buf);
00952
00953
00954 char const* rtpInfoFmt =
00955 "%s"
00956 "%s"
00957 "url=%s/%s"
00958 ";seq=%d"
00959 #ifdef RTPINFO_INCLUDE_RTPTIME
00960 ";rtptime=%u"
00961 #endif
00962 ;
00963 unsigned rtpInfoFmtSize = strlen(rtpInfoFmt);
00964 char* rtpInfo = strDup("RTP-Info: ");
00965 unsigned i, numRTPInfoItems = 0;
00966
00967
00968 for (i = 0; i < fNumStreamStates; ++i) {
00969 if (subsession == NULL
00970 || subsession == fStreamStates[i].subsession) {
00971 if (sawScaleHeader) {
00972 fStreamStates[i].subsession->setStreamScale(fOurSessionId,
00973 fStreamStates[i].streamToken,
00974 scale);
00975 }
00976 if (sawRangeHeader) {
00977 fStreamStates[i].subsession->seekStream(fOurSessionId,
00978 fStreamStates[i].streamToken,
00979 rangeStart);
00980 }
00981 }
0