#include <RTSPClient.hh>
Inheritance diagram for RTSPClient:


Public Member Functions | |
| int | socketNum () const |
| char * | describeURL (char const *url, Authenticator *authenticator=NULL, Boolean allowKasennaProtocol=False) |
| char * | describeWithPassword (char const *url, char const *username, char const *password, Boolean allowKasennaProtocol=False) |
| Boolean | announceSDPDescription (char const *url, char const *sdpDescription, Authenticator *authenticator=NULL) |
| Boolean | announceWithPassword (char const *url, char const *sdpDescription, char const *username, char const *password) |
| char * | sendOptionsCmd (char const *url, char *username=NULL, char *password=NULL, Authenticator *authenticator=NULL) |
| Boolean | setupMediaSubsession (MediaSubsession &subsession, Boolean streamOutgoing=False, Boolean streamUsingTCP=False, Boolean forceMulticastOnUnspecified=False) |
| Boolean | playMediaSession (MediaSession &session, float start=0.0f, float end=-1.0f, float scale=1.0f) |
| Boolean | playMediaSubsession (MediaSubsession &subsession, float start=0.0f, float end=-1.0f, float scale=1.0f, Boolean hackForDSS=False) |
| Boolean | pauseMediaSession (MediaSession &session) |
| Boolean | pauseMediaSubsession (MediaSubsession &subsession) |
| Boolean | recordMediaSubsession (MediaSubsession &subsession) |
| Boolean | setMediaSessionParameter (MediaSession &session, char const *parameterName, char const *parameterValue) |
| Boolean | getMediaSessionParameter (MediaSession &session, char const *parameterName, char *¶meterValue) |
| Boolean | teardownMediaSession (MediaSession &session) |
| Boolean | teardownMediaSubsession (MediaSubsession &subsession) |
| unsigned | describeStatus () const |
| void | setUserAgentString (char const *userAgentStr) |
| unsigned | sessionTimeoutParameter () const |
| UsageEnvironment & | envir () const |
| char const * | name () const |
| virtual Boolean | isSource () const |
| virtual Boolean | isSink () const |
| virtual Boolean | isRTCPInstance () const |
| virtual Boolean | isRTSPServer () const |
| virtual Boolean | isMediaSession () const |
| virtual Boolean | isServerMediaSession () const |
| virtual Boolean | isDarwinInjector () const |
Static Public Member Functions | |
| static RTSPClient * | createNew (UsageEnvironment &env, int verbosityLevel=0, char const *applicationName=NULL, portNumBits tunnelOverHTTPPortNum=0) |
| static Boolean | lookupByName (UsageEnvironment &env, char const *sourceName, RTSPClient *&resultClient) |
| static Boolean | parseRTSPURL (UsageEnvironment &env, char const *url, NetAddress &address, portNumBits &portNum, char const **urlSuffix=NULL) |
| static Boolean | parseRTSPURLUsernamePassword (char const *url, char *&username, char *&password) |
| static Boolean | lookupByName (UsageEnvironment &env, char const *mediumName, Medium *&resultMedium) |
| static void | close (UsageEnvironment &env, char const *mediumName) |
| static void | close (Medium *medium) |
Protected Member Functions | |
| RTSPClient (UsageEnvironment &env, int verbosityLevel, char const *applicationName, portNumBits tunnelOverHTTPPortNum) | |
| virtual | ~RTSPClient () |
| TaskToken & | nextTask () |
Private Member Functions | |
| virtual Boolean | isRTSPClient () const |
| void | reset () |
| void | resetTCPSockets () |
| Boolean | openConnectionFromURL (char const *url, Authenticator *authenticator) |
| char * | createAuthenticatorString (Authenticator const *authenticator, char const *cmd, char const *url) |
| Boolean | sendRequest (char const *requestString, char const *tag, Boolean base64EncodeIfOverHTTP=True) |
| Boolean | getResponse (char const *tag, unsigned &bytesRead, unsigned &responseCode, char *&firstLine, char *&nextLineStart, Boolean checkFor200Response=True) |
| unsigned | getResponse1 (char *&responseBuffer, unsigned responseBufferSize) |
| Boolean | parseResponseCode (char const *line, unsigned &responseCode) |
| Boolean | parseTransportResponse (char const *line, char *&serverAddressStr, portNumBits &serverPortNum, unsigned char &rtpChannelId, unsigned char &rtcpChannelId) |
| Boolean | parseRTPInfoHeader (char *&line, u_int16_t &seqNum, u_int32_t ×tamp) |
| Boolean | parseScaleHeader (char const *line, float &scale) |
| Boolean | parseGetParameterHeader (char const *line, const char *param, char *&value) |
| char const * | sessionURL (MediaSession const &session) const |
| void | constructSubsessionURL (MediaSubsession const &subsession, char const *&prefix, char const *&separator, char const *&suffix) |
| Boolean | setupHTTPTunneling (char const *urlSuffix, Authenticator *authenticator) |
| void | incomingRequestHandler1 () |
| void | handleCmd_notSupported (char const *cseq) |
Static Private Member Functions | |
| static void | checkForAuthenticationFailure (unsigned responseCode, char *&nextLineStart, Authenticator *authenticator) |
| static void | incomingRequestHandler (void *, int) |
Private Attributes | |
| int | fVerbosityLevel |
| portNumBits | fTunnelOverHTTPPortNum |
| char * | fUserAgentHeaderStr |
| unsigned | fUserAgentHeaderStrSize |
| int | fInputSocketNum |
| int | fOutputSocketNum |
| unsigned | fServerAddress |
| char * | fBaseURL |
| Authenticator | fCurrentAuthenticator |
| unsigned char | fTCPStreamIdCount |
| char * | fLastSessionId |
| unsigned | fSessionTimeoutParameter |
| unsigned | fDescribeStatusCode |
| char * | fResponseBuffer |
| unsigned | fResponseBufferSize |
| Boolean | fServerIsKasenna |
| char * | fKasennaContentType |
| Boolean | fServerIsMicrosoft |
Static Private Attributes | |
| static unsigned | fCSeq = 0 |
Definition at line 34 of file RTSPClient.hh.
| RTSPClient::RTSPClient | ( | UsageEnvironment & | env, | |
| int | verbosityLevel, | |||
| char const * | applicationName, | |||
| portNumBits | tunnelOverHTTPPortNum | |||
| ) | [protected] |
Definition at line 60 of file RTSPClient.cpp.
References fResponseBuffer, fResponseBufferSize, fUserAgentHeaderStr, fUserAgentHeaderStrSize, libVersionStr, LIVEMEDIA_LIBRARY_VERSION_STRING, and NULL.
Referenced by createNew().
00063 : Medium(env), 00064 fVerbosityLevel(verbosityLevel), 00065 fTunnelOverHTTPPortNum(tunnelOverHTTPPortNum), 00066 fInputSocketNum(-1), fOutputSocketNum(-1), fServerAddress(0), 00067 fBaseURL(NULL), fTCPStreamIdCount(0), fLastSessionId(NULL), 00068 fSessionTimeoutParameter(0), 00069 #ifdef SUPPORT_REAL_RTSP 00070 fRealChallengeStr(NULL), fRealETagStr(NULL), 00071 #endif 00072 fServerIsKasenna(False), fKasennaContentType(NULL), 00073 fServerIsMicrosoft(False) 00074 { 00075 fResponseBufferSize = 20000; 00076 fResponseBuffer = new char[fResponseBufferSize+1]; 00077 00078 // Set the "User-Agent:" header to use in each request: 00079 char const* const libName = "LIVE555 Streaming Media v"; 00080 char const* const libVersionStr = LIVEMEDIA_LIBRARY_VERSION_STRING; 00081 char const* libPrefix; char const* libSuffix; 00082 if (applicationName == NULL || applicationName[0] == '\0') { 00083 applicationName = libPrefix = libSuffix = ""; 00084 } else { 00085 libPrefix = " ("; 00086 libSuffix = ")"; 00087 } 00088 char const* const formatStr = "User-Agent: %s%s%s%s%s\r\n"; 00089 unsigned headerSize 00090 = strlen(formatStr) + strlen(applicationName) + strlen(libPrefix) 00091 + strlen(libName) + strlen(libVersionStr) + strlen(libSuffix); 00092 fUserAgentHeaderStr = new char[headerSize]; 00093 sprintf(fUserAgentHeaderStr, formatStr, 00094 applicationName, libPrefix, libName, libVersionStr, libSuffix); 00095 fUserAgentHeaderStrSize = strlen(fUserAgentHeaderStr); 00096 }
| RTSPClient::~RTSPClient | ( | ) | [protected, virtual] |
Definition at line 110 of file RTSPClient.cpp.
References Medium::envir(), fInputSocketNum, fResponseBuffer, fUserAgentHeaderStr, reset(), UsageEnvironment::taskScheduler(), and TaskScheduler::turnOffBackgroundReadHandling().
00110 { 00111 envir().taskScheduler().turnOffBackgroundReadHandling(fInputSocketNum); // must be called before: 00112 reset(); 00113 00114 delete[] fResponseBuffer; 00115 delete[] fUserAgentHeaderStr; 00116 }
| RTSPClient * RTSPClient::createNew | ( | UsageEnvironment & | env, | |
| int | verbosityLevel = 0, |
|||
| char const * | applicationName = NULL, |
|||
| portNumBits | tunnelOverHTTPPortNum = 0 | |||
| ) | [static] |
Definition at line 33 of file RTSPClient.cpp.
References env, and RTSPClient().
Referenced by createClient(), and DarwinInjector::setDestination().
00036 { 00037 return new RTSPClient(env, verbosityLevel, 00038 applicationName, tunnelOverHTTPPortNum); 00039 }
| int RTSPClient::socketNum | ( | ) | const [inline] |
Definition at line 44 of file RTSPClient.hh.
References fInputSocketNum.
Referenced by DarwinInjector::setDestination().
00044 { return fInputSocketNum; }
| Boolean RTSPClient::lookupByName | ( | UsageEnvironment & | env, | |
| char const * | sourceName, | |||
| RTSPClient *& | resultClient | |||
| ) | [static] |
Definition at line 41 of file RTSPClient.cpp.
References env, False, Medium::isRTSPClient(), Medium::lookupByName(), NULL, and True.
00043 { 00044 resultClient = NULL; // unless we succeed 00045 00046 Medium* medium; 00047 if (!Medium::lookupByName(env, instanceName, medium)) return False; 00048 00049 if (!medium->isRTSPClient()) { 00050 env.setResultMsg(instanceName, " is not a RTSP client"); 00051 return False; 00052 } 00053 00054 resultClient = (RTSPClient*)medium; 00055 return True; 00056 }
| char * RTSPClient::describeURL | ( | char const * | url, | |
| Authenticator * | authenticator = NULL, |
|||
| Boolean | allowKasennaProtocol = False | |||
| ) |
Definition at line 165 of file RTSPClient.cpp.
References checkForAuthenticationFailure(), createAuthenticatorString(), describeWithPassword(), Medium::envir(), False, fBaseURL, fCSeq, fCurrentAuthenticator, fDescribeStatusCode, fInputSocketNum, fKasennaContentType, fResponseBuffer, fResponseBufferSize, fServerAddress, fServerIsKasenna, fServerIsMicrosoft, fUserAgentHeaderStr, fUserAgentHeaderStrSize, fVerbosityLevel, getLine(), getResponse(), NULL, openConnectionFromURL(), parseRTSPURLUsernamePassword(), password, readSocket(), reset(), Authenticator::reset(), sendRequest(), UsageEnvironment::setResultMsg(), strDup(), True, and username.
Referenced by describeWithPassword(), and getSDPDescriptionFromURL().
00166 { 00167 char* cmd = NULL; 00168 fDescribeStatusCode = 0; 00169 do { 00170 // First, check whether "url" contains a username:password to be used: 00171 char* username; char* password; 00172 if (authenticator == NULL 00173 && parseRTSPURLUsernamePassword(url, username, password)) { 00174 char* result = describeWithPassword(url, username, password, allowKasennaProtocol); 00175 delete[] username; delete[] password; // they were dynamically allocated 00176 return result; 00177 } 00178 00179 if (!openConnectionFromURL(url, authenticator)) break; 00180 00181 // Send the DESCRIBE command: 00182 00183 // First, construct an authenticator string: 00184 fCurrentAuthenticator.reset(); 00185 char* authenticatorStr 00186 = createAuthenticatorString(authenticator, "DESCRIBE", url); 00187 00188 char const* acceptStr = allowKasennaProtocol 00189 ? "Accept: application/x-rtsp-mh, application/sdp\r\n" 00190 : "Accept: application/sdp\r\n"; 00191 00192 // (Later implement more, as specified in the RTSP spec, sec D.1 #####) 00193 char* const cmdFmt = 00194 "DESCRIBE %s RTSP/1.0\r\n" 00195 "CSeq: %d\r\n" 00196 "%s" 00197 "%s" 00198 "%s" 00199 #ifdef SUPPORT_REAL_RTSP 00200 REAL_DESCRIBE_HEADERS 00201 #endif 00202 "\r\n"; 00203 unsigned cmdSize = strlen(cmdFmt) 00204 + strlen(url) 00205 + 20 /* max int len */ 00206 + strlen(acceptStr) 00207 + strlen(authenticatorStr) 00208 + fUserAgentHeaderStrSize; 00209 cmd = new char[cmdSize]; 00210 sprintf(cmd, cmdFmt, 00211 url, 00212 ++fCSeq, 00213 acceptStr, 00214 authenticatorStr, 00215 fUserAgentHeaderStr); 00216 delete[] authenticatorStr; 00217 00218 if (!sendRequest(cmd, "DESCRIBE")) break; 00219 00220 // Get the response from the server: 00221 unsigned bytesRead; unsigned responseCode; 00222 char* firstLine; char* nextLineStart; 00223 if (!getResponse("DESCRIBE", bytesRead, responseCode, firstLine, nextLineStart, 00224 False /*don't check for response code 200*/)) break; 00225 00226 // Inspect the first line to check whether it's a result code that 00227 // we can handle. 00228 Boolean wantRedirection = False; 00229 char* redirectionURL = NULL; 00230 #ifdef SUPPORT_REAL_RTSP 00231 delete[] fRealETagStr; fRealETagStr = new char[fResponseBufferSize]; 00232 #endif 00233 if (responseCode == 301 || responseCode == 302) { 00234 wantRedirection = True; 00235 redirectionURL = new char[fResponseBufferSize]; // ensures enough space 00236 } else if (responseCode != 200) { 00237 checkForAuthenticationFailure(responseCode, nextLineStart, authenticator); 00238 envir().setResultMsg("cannot handle DESCRIBE response: ", firstLine); 00239 break; 00240 } 00241 00242 // Skip over subsequent header lines, until we see a blank line. 00243 // The remaining data is assumed to be the SDP descriptor that we want. 00244 // While skipping over the header lines, we also check for certain headers 00245 // that we recognize. 00246 // (We should also check for "Content-type: application/sdp", 00247 // "Content-location", "CSeq", etc.) ##### 00248 char* serverType = new char[fResponseBufferSize]; // ensures enough space 00249 int contentLength = -1; 00250 char* lineStart; 00251 while (1) { 00252 lineStart = nextLineStart; 00253 if (lineStart == NULL) break; 00254 00255 nextLineStart = getLine(lineStart); 00256 if (lineStart[0] == '\0') break; // this is a blank line 00257 00258 if (sscanf(lineStart, "Content-Length: %d", &contentLength) == 1 00259 || sscanf(lineStart, "Content-length: %d", &contentLength) == 1) { 00260 if (contentLength < 0) { 00261 envir().setResultMsg("Bad \"Content-length:\" header: \"", 00262 lineStart, "\""); 00263 break; 00264 } 00265 } else if (strncmp(lineStart, "Content-Base:", 13) == 0) { 00266 int cbIndex = 13; 00267 00268 while (lineStart[cbIndex] == ' ' || lineStart[cbIndex] == '\t') ++cbIndex; 00269 if (lineStart[cbIndex] != '\0'/*sanity check*/) { 00270 delete[] fBaseURL; fBaseURL = strDup(&lineStart[cbIndex]); 00271 } 00272 } else if (sscanf(lineStart, "Server: %s", serverType) == 1) { 00273 if (strncmp(serverType, "Kasenna", 7) == 0) fServerIsKasenna = True; 00274 if (strncmp(serverType, "WMServer", 8) == 0) fServerIsMicrosoft = True; 00275 #ifdef SUPPORT_REAL_RTSP 00276 } else if (sscanf(lineStart, "ETag: %s", fRealETagStr) == 1) { 00277 #endif 00278 } else if (wantRedirection) { 00279 if (sscanf(lineStart, "Location: %s", redirectionURL) == 1) { 00280 // Try again with this URL 00281 if (fVerbosityLevel >= 1) { 00282 envir() << "Redirecting to the new URL \"" 00283 << redirectionURL << "\"\n"; 00284 } 00285 reset(); 00286 char* result = describeURL(redirectionURL, authenticator, allowKasennaProtocol); 00287 delete[] redirectionURL; 00288 delete[] serverType; 00289 delete[] cmd; 00290 return result; 00291 } 00292 } 00293 } 00294 delete[] serverType; 00295 00296 // We're now at the end of the response header lines 00297 if (wantRedirection) { 00298 envir().setResultMsg("Saw redirection response code, but not a \"Location:\" header"); 00299 delete[] redirectionURL; 00300 break; 00301 } 00302 if (lineStart == NULL) { 00303 envir().setResultMsg("no content following header lines: ", fResponseBuffer); 00304 break; 00305 } 00306 00307 // Use the remaining data as the SDP descr, but first, check 00308 // the "Content-length:" header (if any) that we saw. We may need to 00309 // read more data, or we may have extraneous data in the buffer. 00310 char* bodyStart = nextLineStart; 00311 if (contentLength >= 0) { 00312 // We saw a "Content-length:" header 00313 unsigned numBodyBytes = &firstLine[bytesRead] - bodyStart; 00314 if (contentLength > (int)numBodyBytes) { 00315 // We need to read more data. First, make sure we have enough 00316 // space for it: 00317 unsigned numExtraBytesNeeded = contentLength - numBodyBytes; 00318 unsigned remainingBufferSize 00319 = fResponseBufferSize - (bytesRead + (firstLine - fResponseBuffer)); 00320 if (numExtraBytesNeeded > remainingBufferSize) { 00321 char tmpBuf[200]; 00322 sprintf(tmpBuf, "Read buffer size (%d) is too small for \"Content-length:\" %d (need a buffer size of >= %d bytes\n", 00323 fResponseBufferSize, contentLength, 00324 fResponseBufferSize + numExtraBytesNeeded - remainingBufferSize); 00325 envir().setResultMsg(tmpBuf); 00326 break; 00327 } 00328 00329 // Keep reading more data until we have enough: 00330 if (fVerbosityLevel >= 1) { 00331 envir() << "Need to read " << numExtraBytesNeeded 00332 << " extra bytes\n"; 00333 } 00334 while (numExtraBytesNeeded > 0) { 00335 struct sockaddr_in fromAddress; 00336 char* ptr = &firstLine[bytesRead]; 00337 int bytesRead2 = readSocket(envir(), fInputSocketNum, (unsigned char*)ptr, 00338 numExtraBytesNeeded, fromAddress); 00339 if (bytesRead2 < 0) break; 00340 ptr[bytesRead2] = '\0'; 00341 if (fVerbosityLevel >= 1) { 00342 envir() << "Read " << bytesRead2 << " extra bytes: " 00343 << ptr << "\n"; 00344 } 00345 00346 bytesRead += bytesRead2; 00347 numExtraBytesNeeded -= bytesRead2; 00348 } 00349 if (numExtraBytesNeeded > 0) break; // one of the reads failed 00350 } 00351 00352 // Remove any '\0' characters from inside the SDP description. 00353 // Any such characters would violate the SDP specification, but 00354 // some RTSP servers have been known to include them: 00355 int from, to = 0; 00356 for (from = 0; from < contentLength; ++from) { 00357 if (bodyStart[from] != '\0') { 00358 if (to != from) bodyStart[to] = bodyStart[from]; 00359 ++to; 00360 } 00361 } 00362 if (from != to && fVerbosityLevel >= 1) { 00363 envir() << "Warning: " << from-to << " invalid 'NULL' bytes were found in (and removed from) the SDP description.\n"; 00364 } 00365 bodyStart[to] = '\0'; // trims any extra data 00366 } 00367 00369 // If necessary, handle Kasenna's non-standard BS response: 00370 if (fServerIsKasenna && strncmp(bodyStart, "<MediaDescription>", 18) == 0) { 00371 // Translate from x-rtsp-mh to sdp 00372 int videoPid, audioPid; 00373 u_int64_t mh_duration; 00374 char* currentWord = new char[fResponseBufferSize]; // ensures enough space 00375 delete[] fKasennaContentType; 00376 fKasennaContentType = new char[fResponseBufferSize]; // ensures enough space 00377 char* currentPos = bodyStart; 00378 00379 while (strcmp(currentWord, "</MediaDescription>") != 0) { 00380 sscanf(currentPos, "%s", currentWord); 00381 00382 if (strcmp(currentWord, "VideoPid") == 0) { 00383 currentPos += strlen(currentWord) + 1; 00384 sscanf(currentPos, "%s", currentWord); 00385 currentPos += strlen(currentWord) + 1; 00386 sscanf(currentPos, "%d", &videoPid); 00387 currentPos += 3; 00388 } 00389 00390 if (strcmp(currentWord, "AudioPid") == 0) { 00391 currentPos += strlen(currentWord) + 1; 00392 sscanf(currentPos, "%s", currentWord); 00393 currentPos += strlen(currentWord) + 1; 00394 sscanf(currentPos, "%d", &audioPid); 00395 currentPos += 3; 00396 } 00397 00398 if (strcmp(currentWord, "Duration") == 0) { 00399 currentPos += strlen(currentWord) + 1; 00400 sscanf(currentPos, "%s", currentWord); 00401 currentPos += strlen(currentWord) + 1; 00402 sscanf(currentPos, "%llu", &mh_duration); 00403 currentPos += 3; 00404 } 00405 00406 if (strcmp(currentWord, "TypeSpecificData") == 0) { 00407 currentPos += strlen(currentWord) + 1; 00408 sscanf(currentPos, "%s", currentWord); 00409 currentPos += strlen(currentWord) + 1; 00410 sscanf(currentPos, "%s", fKasennaContentType); 00411 currentPos += 3; 00412 printf("Kasenna Content Type: %s\n", fKasennaContentType); 00413 } 00414 00415 currentPos += strlen(currentWord) + 1; 00416 } 00417 00418 if (fKasennaContentType != NULL 00419 && strcmp(fKasennaContentType, "PARTNER_41_MPEG-4") == 0) { 00420 char* describeSDP = describeURL(url, authenticator, True); 00421 00422 delete[] currentWord; 00423 delete[] cmd; 00424 return describeSDP; 00425 } 00426 00427 unsigned char byte1 = fServerAddress & 0x000000ff; 00428 unsigned char byte2 = (fServerAddress & 0x0000ff00) >> 8; 00429 unsigned char byte3 = (fServerAddress & 0x00ff0000) >> 16; 00430 unsigned char byte4 = (fServerAddress & 0xff000000) >> 24; 00431 00432 char const* sdpFmt = 00433 "v=0\r\n" 00434 "o=NoSpacesAllowed 1 1 IN IP4 %u.%u.%u.%u\r\n" 00435 "s=%s\r\n" 00436 "c=IN IP4 %u.%u.%u.%u\r\n" 00437 "t=0 0\r\n" 00438 "a=control:*\r\n" 00439 "a=range:npt=0-%llu\r\n" 00440 "m=video 1554 RAW/RAW/UDP 33\r\n" 00441 "a=control:trackID=%d\r\n"; 00442 unsigned sdpBufSize = strlen(sdpFmt) 00443 + 4*3 // IP address 00444 + strlen(url) 00445 + 20 // max int length 00446 + 20; // max int length 00447 char* sdpBuf = new char[sdpBufSize]; 00448 sprintf(sdpBuf, sdpFmt, 00449 byte1, byte2, byte3, byte4, 00450 url, 00451 byte1, byte2, byte3, byte4, 00452 mh_duration/1000000, 00453 videoPid); 00454 00455 char* result = strDup(sdpBuf); 00456 delete[] sdpBuf; delete[] currentWord; 00457 delete[] cmd; 00458 return result; 00459 } 00461 00462 delete[] cmd; 00463 return strDup(bodyStart); 00464 } while (0); 00465 00466 delete[] cmd; 00467 if (fDescribeStatusCode == 0) fDescribeStatusCode = 2; 00468 return NULL; 00469 }
| char * RTSPClient::describeWithPassword | ( | char const * | url, | |
| char const * | username, | |||
| char const * | password, | |||
| Boolean | allowKasennaProtocol = False | |||
| ) |
Definition at line 472 of file RTSPClient.cpp.
References describeURL(), fCurrentAuthenticator, NULL, Authenticator::realm(), and Authenticator::setUsernameAndPassword().
Referenced by describeURL(), and getSDPDescriptionFromURL().
00474 { 00475 Authenticator authenticator; 00476 authenticator.setUsernameAndPassword(username, password); 00477 char* describeResult = describeURL(url, &authenticator, allowKasennaProtocol); 00478 if (describeResult != NULL) { 00479 // We are already authorized 00480 return describeResult; 00481 } 00482 00483 // The "realm" field should have been filled in: 00484 if (authenticator.realm() == NULL) { 00485 // We haven't been given enough information to try again, so fail: 00486 return NULL; 00487 } 00488 00489 // Try again: 00490 describeResult = describeURL(url, &authenticator, allowKasennaProtocol); 00491 if (describeResult != NULL) { 00492 // The authenticator worked, so use it in future requests: 00493 fCurrentAuthenticator = authenticator; 00494 } 00495 00496 return describeResult; 00497 }
| Boolean RTSPClient::announceSDPDescription | ( | char const * | url, | |
| char const * | sdpDescription, | |||
| Authenticator * | authenticator = NULL | |||
| ) |
Definition at line 647 of file RTSPClient.cpp.
References checkForAuthenticationFailure(), createAuthenticatorString(), Medium::envir(), False, fCSeq, fCurrentAuthenticator, getResponse(), NULL, openConnectionFromURL(), Authenticator::reset(), sendRequest(), UsageEnvironment::setResultMsg(), and True.
Referenced by announceWithPassword(), and DarwinInjector::setDestination().
00649 { 00650 char* cmd = NULL; 00651 do { 00652 if (!openConnectionFromURL(url, authenticator)) break; 00653 00654 // Send the ANNOUNCE command: 00655 00656 // First, construct an authenticator string: 00657 fCurrentAuthenticator.reset(); 00658 char* authenticatorStr 00659 = createAuthenticatorString(authenticator, "ANNOUNCE", url); 00660 00661 char* const cmdFmt = 00662 "ANNOUNCE %s RTSP/1.0\r\n" 00663 "CSeq: %d\r\n" 00664 "Content-Type: application/sdp\r\n" 00665 "%s" 00666 "Content-length: %d\r\n\r\n" 00667 "%s"; 00668 // Note: QTSS hangs if an "ANNOUNCE" contains a "User-Agent:" field (go figure), so don't include one here 00669 unsigned sdpSize = strlen(sdpDescription); 00670 unsigned cmdSize = strlen(cmdFmt) 00671 + strlen(url) 00672 + 20 /* max int len */ 00673 + strlen(authenticatorStr) 00674 + 20 /* max int len */ 00675 + sdpSize; 00676 cmd = new char[cmdSize]; 00677 sprintf(cmd, cmdFmt, 00678 url, 00679 ++fCSeq, 00680 authenticatorStr, 00681 sdpSize, 00682 sdpDescription); 00683 delete[] authenticatorStr; 00684 00685 if (!sendRequest(cmd, "ANNOUNCE")) break; 00686 00687 // Get the response from the server: 00688 unsigned bytesRead; unsigned responseCode; 00689 char* firstLine; char* nextLineStart; 00690 if (!getResponse("ANNOUNCE", bytesRead, responseCode, firstLine, nextLineStart, 00691 False /*don't check for response code 200*/)) break; 00692 00693 // Inspect the first line to check whether it's a result code 200 00694 if (responseCode != 200) { 00695 checkForAuthenticationFailure(responseCode, nextLineStart, authenticator); 00696 envir().setResultMsg("cannot handle ANNOUNCE response: ", firstLine); 00697 break; 00698 } 00699 00700 delete[] cmd; 00701 return True; 00702 } while (0); 00703 00704 delete[] cmd; 00705 return False; 00706 }
| Boolean RTSPClient::announceWithPassword | ( | char const * | url, | |
| char const * | sdpDescription, | |||
| char const * | username, | |||
| char const * | password | |||
| ) |
Definition at line 709 of file RTSPClient.cpp.
References announceSDPDescription(), False, fCurrentAuthenticator, NULL, Authenticator::realm(), Authenticator::setUsernameAndPassword(), and True.
Referenced by DarwinInjector::setDestination().
00710 { 00711 Authenticator authenticator; 00712 authenticator.setUsernameAndPassword(username, password); 00713 if (announceSDPDescription(url, sdpDescription, &authenticator)) { 00714 // We are already authorized 00715 return True; 00716 } 00717 00718 // The "realm" field should have been filled in: 00719 if (authenticator.realm() == NULL) { 00720 // We haven't been given enough information to try again, so fail: 00721 return False; 00722 } 00723 00724 // Try again: 00725 Boolean secondTrySuccess 00726 = announceSDPDescription(url, sdpDescription, &authenticator); 00727 00728 if (secondTrySuccess) { 00729 // The authenticator worked, so use it in future requests: 00730 fCurrentAuthenticator = authenticator; 00731 } 00732 00733 return secondTrySuccess; 00734 }
| char * RTSPClient::sendOptionsCmd | ( | char const * | url, | |
| char * | username = NULL, |
|||
| char * | password = NULL, |
|||
| Authenticator * | authenticator = NULL | |||
| ) |
Definition at line 499 of file RTSPClient.cpp.
References _strncasecmp, checkForAuthenticationFailure(), createAuthenticatorString(), Medium::envir(), False, fCSeq, fUserAgentHeaderStr, fUserAgentHeaderStrSize, getLine(), getResponse(), NULL, openConnectionFromURL(), parseRTSPURLUsernamePassword(), Authenticator::realm(), sendRequest(), UsageEnvironment::setResultMsg(), Authenticator::setUsernameAndPassword(), strDup(), and True.
Referenced by getOptionsResponse().
00501 { 00502 char* result = NULL; 00503 char* cmd = NULL; 00504 Boolean haveAllocatedAuthenticator = False; 00505 do { 00506 if (authenticator == NULL) { 00507 // First, check whether "url" contains a username:password to be used 00508 // (and no username,password pair was supplied separately): 00509 if (username == NULL && password == NULL 00510 && parseRTSPURLUsernamePassword(url, username, password)) { 00511 Authenticator newAuthenticator; 00512 newAuthenticator.setUsernameAndPassword(username, password); 00513 result = sendOptionsCmd(url, username, password, &newAuthenticator); 00514 delete[] username; delete[] password; // they were dynamically allocated 00515 break; 00516 } else if (username != NULL && password != NULL) { 00517 // Use the separately supplied username and password: 00518 authenticator = new Authenticator; 00519 haveAllocatedAuthenticator = True; 00520 authenticator->setUsernameAndPassword(username, password); 00521 00522 result = sendOptionsCmd(url, username, password, authenticator); 00523 if (result != NULL) break; // We are already authorized 00524 00525 // The "realm" field should have been filled in: 00526 if (authenticator->realm() == NULL) { 00527 // We haven't been given enough information to try again, so fail: 00528 break; 00529 } 00530 // Try again: 00531 } 00532 } 00533 00534 if (!openConnectionFromURL(url, authenticator)) break; 00535 00536 // Send the OPTIONS command: 00537 00538 // First, construct an authenticator string: 00539 char* authenticatorStr 00540 = createAuthenticatorString(authenticator, "OPTIONS", url); 00541 00542 char* const cmdFmt = 00543 "OPTIONS %s RTSP/1.0\r\n" 00544 "CSeq: %d\r\n" 00545 "%s" 00546 "%s" 00547 #ifdef SUPPORT_REAL_RTSP 00548 REAL_OPTIONS_HEADERS 00549 #endif 00550 "\r\n"; 00551 unsigned cmdSize = strlen(cmdFmt) 00552 + strlen(url) 00553 + 20 /* max int len */ 00554 + strlen(authenticatorStr) 00555 + fUserAgentHeaderStrSize; 00556 cmd = new char[cmdSize]; 00557 sprintf(cmd, cmdFmt, 00558 url, 00559 ++fCSeq, 00560 authenticatorStr, 00561 fUserAgentHeaderStr); 00562 delete[] authenticatorStr; 00563 00564 if (!sendRequest(cmd, "OPTIONS")) break; 00565 00566 // Get the response from the server: 00567 unsigned bytesRead; unsigned responseCode; 00568 char* firstLine; char* nextLineStart; 00569 if (!getResponse("OPTIONS", bytesRead, responseCode, firstLine, nextLineStart, 00570 False /*don't check for response code 200*/)) break; 00571 if (responseCode != 200) { 00572 checkForAuthenticationFailure(responseCode, nextLineStart, authenticator); 00573 envir().setResultMsg("cannot handle OPTIONS response: ", firstLine); 00574 break; 00575 } 00576 00577 // Look for a "Public:" header (which will contain our result str): 00578 char* lineStart; 00579 while (1) { 00580 lineStart = nextLineStart; 00581 if (lineStart == NULL) break; 00582 00583 nextLineStart = getLine(lineStart); 00584 00585 if (_strncasecmp(lineStart, "Public: ", 8) == 0) { 00586 delete[] result; result = strDup(&lineStart[8]); 00587 #ifdef SUPPORT_REAL_RTSP 00588 } else if (_strncasecmp(lineStart, "RealChallenge1: ", 16) == 0) { 00589 delete[] fRealChallengeStr; fRealChallengeStr = strDup(&lineStart[16]); 00590 #endif 00591 } 00592 } 00593 } while (0); 00594 00595 delete[] cmd; 00596 if (haveAllocatedAuthenticator) delete authenticator; 00597 return result; 00598 }
| Boolean RTSPClient::setupMediaSubsession | ( | MediaSubsession & | subsession, | |
| Boolean | streamOutgoing = False, |
|||
| Boolean | streamUsingTCP = False, |
|||
| Boolean | forceMulticastOnUnspecified = False | |||
| ) |
Definition at line 736 of file RTSPClient.cpp.
References MediaSubsession::clientPortNum(), MediaSubsession::connectionEndpointAddress(), MediaSubsession::connectionEndpointName(), constructSubsessionURL(), createAuthenticatorString(), Medium::envir(), False, fBaseURL, fCSeq, fCurrentAuthenticator, fInputSocketNum, fLastSessionId, fResponseBufferSize, fServerAddress, fServerIsMicrosoft, fSessionTimeoutParameter, fTCPStreamIdCount, fUserAgentHeaderStr, fUserAgentHeaderStrSize, getLine(), getResponse(), getResponse1(), IsMulticastAddress(), MediaSession::mediaSessionType(), NULL, MediaSubsession::parentSession(), parseTransportResponse(), MediaSession::playEndTime(), MediaSubsession::pro