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


Public Types | |
| typedef void( | responseHandler )(RTSPClient *rtspClient, int resultCode, char *resultString) |
Public Member Functions | |
| unsigned | sendDescribeCommand (responseHandler *responseHandler, Authenticator *authenticator=NULL) |
| unsigned | sendOptionsCommand (responseHandler *responseHandler, Authenticator *authenticator=NULL) |
| unsigned | sendAnnounceCommand (char const *sdpDescription, responseHandler *responseHandler, Authenticator *authenticator=NULL) |
| unsigned | sendSetupCommand (MediaSubsession &subsession, responseHandler *responseHandler, Boolean streamOutgoing=False, Boolean streamUsingTCP=False, Boolean forceMulticastOnUnspecified=False, Authenticator *authenticator=NULL) |
| unsigned | sendPlayCommand (MediaSession &session, responseHandler *responseHandler, double start=0.0f, double end=-1.0f, float scale=1.0f, Authenticator *authenticator=NULL) |
| unsigned | sendPlayCommand (MediaSubsession &subsession, responseHandler *responseHandler, double start=0.0f, double end=-1.0f, float scale=1.0f, Authenticator *authenticator=NULL) |
| unsigned | sendPauseCommand (MediaSession &session, responseHandler *responseHandler, Authenticator *authenticator=NULL) |
| unsigned | sendPauseCommand (MediaSubsession &subsession, responseHandler *responseHandler, Authenticator *authenticator=NULL) |
| unsigned | sendRecordCommand (MediaSession &session, responseHandler *responseHandler, Authenticator *authenticator=NULL) |
| unsigned | sendRecordCommand (MediaSubsession &subsession, responseHandler *responseHandler, Authenticator *authenticator=NULL) |
| unsigned | sendTeardownCommand (MediaSession &session, responseHandler *responseHandler, Authenticator *authenticator=NULL) |
| unsigned | sendTeardownCommand (MediaSubsession &subsession, responseHandler *responseHandler, Authenticator *authenticator=NULL) |
| unsigned | sendSetParameterCommand (MediaSession &session, responseHandler *responseHandler, char const *parameterName, char const *parameterValue, Authenticator *authenticator=NULL) |
| unsigned | sendGetParameterCommand (MediaSession &session, responseHandler *responseHandler, char const *parameterName, Authenticator *authenticator=NULL) |
| Boolean | changeResponseHandler (unsigned cseq, responseHandler *newResponseHandler) |
| int | socketNum () const |
| void | setUserAgentString (char const *userAgentName) |
| unsigned | sessionTimeoutParameter () const |
| char const * | url () const |
| char * | describeURL (char const *url, Authenticator *authenticator=NULL, Boolean allowKasennaProtocol=False, int timeout=-1) |
| char * | describeWithPassword (char const *url, char const *username, char const *password, Boolean allowKasennaProtocol=False, int timeout=-1) |
| char * | sendOptionsCmd (char const *url, char *username=NULL, char *password=NULL, Authenticator *authenticator=NULL, int timeout=-1) |
| Boolean | announceSDPDescription (char const *url, char const *sdpDescription, Authenticator *authenticator=NULL, int timeout=-1) |
| Boolean | announceWithPassword (char const *url, char const *sdpDescription, char const *username, char const *password, int timeout=-1) |
| Boolean | setupMediaSubsession (MediaSubsession &subsession, Boolean streamOutgoing=False, Boolean streamUsingTCP=False, Boolean forceMulticastOnUnspecified=False) |
| Boolean | playMediaSession (MediaSession &session, double start=0.0f, double end=-1.0f, float scale=1.0f) |
| Boolean | playMediaSubsession (MediaSubsession &subsession, double start=0.0f, double 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) |
| 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, char const *rtspURL, 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, char *&username, char *&password, NetAddress &address, portNumBits &portNum, char const **urlSuffix=NULL) |
| static RTSPClient * | createNew (UsageEnvironment &env, int verbosityLevel=0, char const *applicationName=NULL, portNumBits tunnelOverHTTPPortNum=0) |
| 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) |
Static Public Attributes | |
| static unsigned | responseBufferSize = 20000 |
Protected Member Functions | |
| RTSPClient (UsageEnvironment &env, char const *rtspURL, int verbosityLevel, char const *applicationName, portNumBits tunnelOverHTTPPortNum) | |
| virtual | ~RTSPClient () |
| void | setBaseURL (char const *url) |
| TaskToken & | nextTask () |
Private Member Functions | |
| virtual Boolean | isRTSPClient () const |
| void | reset () |
| void | resetTCPSockets () |
| void | resetResponseBuffer () |
| int | openConnection () |
| int | connectToServer (int socketNum, portNumBits remotePortNum) |
| char * | createAuthenticatorString (char const *cmd, char const *url) |
| unsigned | sendRequest (RequestRecord *request) |
| void | handleRequestError (RequestRecord *request) |
| Boolean | parseResponseCode (char const *line, unsigned &responseCode, char const *&responseString) |
| void | handleIncomingRequest () |
| Boolean | parseTransportParams (char const *paramsStr, char *&serverAddressStr, portNumBits &serverPortNum, unsigned char &rtpChannelId, unsigned char &rtcpChannelId) |
| Boolean | parseScaleParam (char const *paramStr, float &scale) |
| Boolean | parseRTPInfoParams (char const *¶mStr, u_int16_t &seqNum, u_int32_t ×tamp) |
| Boolean | handleSETUPResponse (MediaSubsession &subsession, char const *sessionParamsStr, char const *transportParamsStr, Boolean streamUsingTCP) |
| Boolean | handlePLAYResponse (MediaSession &session, MediaSubsession &subsession, char const *scaleParamsStr, char const *rangeParamsStr, char const *rtpInfoParamsStr) |
| Boolean | handleTEARDOWNResponse (MediaSession &session, MediaSubsession &subsession) |
| Boolean | handleGET_PARAMETERResponse (char const *parameterName, char *&resultValueString) |
| Boolean | handleAuthenticationFailure (char const *wwwAuthenticateParamsStr) |
| Boolean | resendCommand (RequestRecord *request) |
| char const * | sessionURL (MediaSession const &session) const |
| void | handleAlternativeRequestByte1 (u_int8_t requestByte) |
| void | constructSubsessionURL (MediaSubsession const &subsession, char const *&prefix, char const *&separator, char const *&suffix) |
| Boolean | setupHTTPTunneling1 () |
| void | responseHandlerForHTTP_GET1 (int responseCode, char *responseString) |
| Boolean | setupHTTPTunneling2 () |
| void | connectionHandler1 () |
| void | incomingDataHandler1 () |
| void | handleResponseBytes (int newBytesRead) |
| void | responseHandlerForSyncInterface1 (int responseCode, char *responseString) |
| void | timeoutHandlerForSyncInterface1 () |
Static Private Member Functions | |
| static Boolean | checkForHeader (char const *line, char const *headerName, unsigned headerNameLength, char const *&headerParams) |
| static void | handleAlternativeRequestByte (void *, u_int8_t requestByte) |
| static void | responseHandlerForHTTP_GET (RTSPClient *rtspClient, int responseCode, char *responseString) |
| static void | connectionHandler (void *, int) |
| static void | incomingDataHandler (void *, int) |
| static void | responseHandlerForSyncInterface (RTSPClient *rtspClient, int responseCode, char *responseString) |
| static void | timeoutHandlerForSyncInterface (void *rtspClient) |
Private Attributes | |
| int | fVerbosityLevel |
| portNumBits | fTunnelOverHTTPPortNum |
| char * | fUserAgentHeaderStr |
| unsigned | fUserAgentHeaderStrLen |
| int | fInputSocketNum |
| int | fOutputSocketNum |
| netAddressBits | fServerAddress |
| unsigned | fCSeq |
| char * | fBaseURL |
| Authenticator | fCurrentAuthenticator |
| unsigned char | fTCPStreamIdCount |
| char * | fLastSessionId |
| unsigned | fSessionTimeoutParameter |
| char * | fResponseBuffer |
| unsigned | fResponseBytesAlreadySeen |
| unsigned | fResponseBufferBytesLeft |
| RequestQueue | fRequestsAwaitingConnection |
| RequestQueue | fRequestsAwaitingHTTPTunneling |
| RequestQueue | fRequestsAwaitingResponse |
| char | fSessionCookie [33] |
| unsigned | fSessionCookieCounter |
| Boolean | fHTTPTunnelingConnectionIsPending |
| TaskToken | fTimeoutTask |
| char | fWatchVariableForSyncInterface |
| char * | fResultString |
| int | fResultCode |
Friends | |
| class | MediaLookupTable |
Data Structures | |
| class | RequestQueue |
| class | RequestRecord |
Definition at line 36 of file RTSPClient.hh.
| typedef void( RTSPClient::responseHandler)(RTSPClient *rtspClient, int resultCode, char *resultString) |
Definition at line 46 of file RTSPClient.hh.
| RTSPClient::RTSPClient | ( | UsageEnvironment & | env, | |
| char const * | rtspURL, | |||
| int | verbosityLevel, | |||
| char const * | applicationName, | |||
| portNumBits | tunnelOverHTTPPortNum | |||
| ) | [protected] |
Definition at line 282 of file RTSPClient.cpp.
References fResponseBuffer, libVersionStr, LIVEMEDIA_LIBRARY_VERSION_STRING, NULL, resetResponseBuffer(), responseBufferSize, setBaseURL(), and setUserAgentString().
Referenced by createNew().
00285 : Medium(env), 00286 fVerbosityLevel(verbosityLevel), fTunnelOverHTTPPortNum(tunnelOverHTTPPortNum), 00287 fUserAgentHeaderStr(NULL), fUserAgentHeaderStrLen(0), fInputSocketNum(-1), fOutputSocketNum(-1), fServerAddress(0), fCSeq(1), 00288 fBaseURL(NULL), fTCPStreamIdCount(0), fLastSessionId(NULL), fSessionTimeoutParameter(0), 00289 fSessionCookieCounter(0), fHTTPTunnelingConnectionIsPending(False) { 00290 setBaseURL(rtspURL); 00291 00292 fResponseBuffer = new char[responseBufferSize+1]; 00293 resetResponseBuffer(); 00294 00295 // Set the "User-Agent:" header to use in each request: 00296 char const* const libName = "LIVE555 Streaming Media v"; 00297 char const* const libVersionStr = LIVEMEDIA_LIBRARY_VERSION_STRING; 00298 char const* libPrefix; char const* libSuffix; 00299 if (applicationName == NULL || applicationName[0] == '\0') { 00300 applicationName = libPrefix = libSuffix = ""; 00301 } else { 00302 libPrefix = " ("; 00303 libSuffix = ")"; 00304 } 00305 unsigned userAgentNameSize 00306 = strlen(applicationName) + strlen(libPrefix) + strlen(libName) + strlen(libVersionStr) + strlen(libSuffix) + 1; 00307 char* userAgentName = new char[userAgentNameSize]; 00308 sprintf(userAgentName, "%s%s%s%s%s", applicationName, libPrefix, libName, libVersionStr, libSuffix); 00309 setUserAgentString(userAgentName); 00310 delete[] userAgentName; 00311 }
| RTSPClient::~RTSPClient | ( | ) | [protected, virtual] |
Definition at line 313 of file RTSPClient.cpp.
References fResponseBuffer, fUserAgentHeaderStr, and reset().
00313 { 00314 reset(); 00315 00316 delete[] fResponseBuffer; 00317 delete[] fUserAgentHeaderStr; 00318 }
| RTSPClient * RTSPClient::createNew | ( | UsageEnvironment & | env, | |
| char const * | rtspURL, | |||
| int | verbosityLevel = 0, |
|||
| char const * | applicationName = NULL, |
|||
| portNumBits | tunnelOverHTTPPortNum = 0 | |||
| ) | [static] |
Reimplemented in ourRTSPClient.
Definition at line 30 of file RTSPClient.cpp.
References env, and RTSPClient().
Referenced by createClient().
00033 { 00034 return new RTSPClient(env, rtspURL, 00035 verbosityLevel, applicationName, tunnelOverHTTPPortNum); 00036 }
| unsigned RTSPClient::sendDescribeCommand | ( | responseHandler * | responseHandler, | |
| Authenticator * | authenticator = NULL | |||
| ) |
Definition at line 38 of file RTSPClient.cpp.
References fCSeq, fCurrentAuthenticator, NULL, and sendRequest().
Referenced by getSDPDescription(), and openURL().
00038 { 00039 if (authenticator != NULL) fCurrentAuthenticator = *authenticator; 00040 return sendRequest(new RequestRecord(++fCSeq, "DESCRIBE", responseHandler)); 00041 }
| unsigned RTSPClient::sendOptionsCommand | ( | responseHandler * | responseHandler, | |
| Authenticator * | authenticator = NULL | |||
| ) |
Definition at line 43 of file RTSPClient.cpp.
References fCSeq, fCurrentAuthenticator, NULL, and sendRequest().
Referenced by getOptions().
00043 { 00044 if (authenticator != NULL) fCurrentAuthenticator = *authenticator; 00045 return sendRequest(new RequestRecord(++fCSeq, "OPTIONS", responseHandler)); 00046 }
| unsigned RTSPClient::sendAnnounceCommand | ( | char const * | sdpDescription, | |
| responseHandler * | responseHandler, | |||
| Authenticator * | authenticator = NULL | |||
| ) |
Definition at line 48 of file RTSPClient.cpp.
References False, fCSeq, fCurrentAuthenticator, NULL, and sendRequest().
Referenced by DarwinInjector::setDestination().
00048 { 00049 if (authenticator != NULL) fCurrentAuthenticator = *authenticator; 00050 return sendRequest(new RequestRecord(++fCSeq, "ANNOUNCE", responseHandler, NULL, NULL, False, 0.0, 0.0, 0.0, sdpDescription)); 00051 }
| unsigned RTSPClient::sendSetupCommand | ( | MediaSubsession & | subsession, | |
| responseHandler * | responseHandler, | |||
| Boolean | streamOutgoing = False, |
|||
| Boolean | streamUsingTCP = False, |
|||
| Boolean | forceMulticastOnUnspecified = False, |
|||
| Authenticator * | authenticator = NULL | |||
| ) |
Definition at line 53 of file RTSPClient.cpp.
References fCSeq, fCurrentAuthenticator, fTunnelOverHTTPPortNum, NULL, sendRequest(), subsession, and True.
Referenced by DarwinInjector::setDestination(), setupNextSubsession(), and setupSubsession().
00055 { 00056 if (fTunnelOverHTTPPortNum != 0) streamUsingTCP = True; // RTSP-over-HTTP tunneling uses TCP (by definition) 00057 if (authenticator != NULL) fCurrentAuthenticator = *authenticator; 00058 00059 u_int32_t booleanFlags = 0; 00060 if (streamUsingTCP) booleanFlags |= 0x1; 00061 if (streamOutgoing) booleanFlags |= 0x2; 00062 if (forceMulticastOnUnspecified) booleanFlags |= 0x4; 00063 return sendRequest(new RequestRecord(++fCSeq, "SETUP", responseHandler, NULL, &subsession, booleanFlags)); 00064 }
| unsigned RTSPClient::sendPlayCommand | ( | MediaSession & | session, | |
| responseHandler * | responseHandler, | |||
| double | start = 0.0f, |
|||
| double | end = -1.0f, |
|||
| float | scale = 1.0f, |
|||
| Authenticator * | authenticator = NULL | |||
| ) |
Definition at line 66 of file RTSPClient.cpp.
References fCSeq, fCurrentAuthenticator, NULL, sendRequest(), and session.
Referenced by DarwinInjector::setDestination(), setupNextSubsession(), and startPlayingSession().
00068 { 00069 if (authenticator != NULL) fCurrentAuthenticator = *authenticator; 00070 return sendRequest(new RequestRecord(++fCSeq, "PLAY", responseHandler, &session, NULL, 0, start, end, scale)); 00071 }
| unsigned RTSPClient::sendPlayCommand | ( | MediaSubsession & | subsession, | |
| responseHandler * | responseHandler, | |||
| double | start = 0.0f, |
|||
| double | end = -1.0f, |
|||
| float | scale = 1.0f, |
|||
| Authenticator * | authenticator = NULL | |||
| ) |
Definition at line 73 of file RTSPClient.cpp.
References fCSeq, fCurrentAuthenticator, NULL, sendRequest(), and subsession.
00075 { 00076 if (authenticator != NULL) fCurrentAuthenticator = *authenticator; 00077 return sendRequest(new RequestRecord(++fCSeq, "PLAY", responseHandler, NULL, &subsession, 0, start, end, scale)); 00078 }
| unsigned RTSPClient::sendPauseCommand | ( | MediaSession & | session, | |
| responseHandler * | responseHandler, | |||
| Authenticator * | authenticator = NULL | |||
| ) |
Definition at line 80 of file RTSPClient.cpp.
References fCSeq, fCurrentAuthenticator, NULL, sendRequest(), and session.
00080 { 00081 if (authenticator != NULL) fCurrentAuthenticator = *authenticator; 00082 return sendRequest(new RequestRecord(++fCSeq, "PAUSE", responseHandler, &session)); 00083 }
| unsigned RTSPClient::sendPauseCommand | ( | MediaSubsession & | subsession, | |
| responseHandler * | responseHandler, | |||
| Authenticator * | authenticator = NULL | |||
| ) |
Definition at line 85 of file RTSPClient.cpp.
References fCSeq, fCurrentAuthenticator, NULL, sendRequest(), and subsession.
00085 { 00086 if (authenticator != NULL) fCurrentAuthenticator = *authenticator; 00087 return sendRequest(new RequestRecord(++fCSeq, "PAUSE", responseHandler, NULL, &subsession)); 00088 }
| unsigned RTSPClient::sendRecordCommand | ( | MediaSession & | session, | |
| responseHandler * | responseHandler, | |||
| Authenticator * | authenticator = NULL | |||
| ) |
Definition at line 90 of file RTSPClient.cpp.
References fCSeq, fCurrentAuthenticator, NULL, sendRequest(), and session.
00090 { 00091 if (authenticator != NULL) fCurrentAuthenticator = *authenticator; 00092 return sendRequest(new RequestRecord(++fCSeq, "RECORD", responseHandler, &session)); 00093 }
| unsigned RTSPClient::sendRecordCommand | ( | MediaSubsession & | subsession, | |
| responseHandler * | responseHandler, | |||
| Authenticator * | authenticator = NULL | |||
| ) |
Definition at line 95 of file RTSPClient.cpp.
References fCSeq, fCurrentAuthenticator, NULL, sendRequest(), and subsession.
00095 { 00096 if (authenticator != NULL) fCurrentAuthenticator = *authenticator; 00097 return sendRequest(new RequestRecord(++fCSeq, "RECORD", responseHandler, NULL, &subsession)); 00098 }
| unsigned RTSPClient::sendTeardownCommand | ( | MediaSession & | session, | |
| responseHandler * | responseHandler, | |||
| Authenticator * | authenticator = NULL | |||
| ) |
Definition at line 100 of file RTSPClient.cpp.
References fCSeq, fCurrentAuthenticator, NULL, sendRequest(), and session.
Referenced by shutdownStream(), tearDownSession(), and DarwinInjector::~DarwinInjector().
00100 { 00101 if (authenticator != NULL) fCurrentAuthenticator = *authenticator; 00102 return sendRequest(new RequestRecord(++fCSeq, "TEARDOWN", responseHandler, &session)); 00103 }
| unsigned RTSPClient::sendTeardownCommand | ( | MediaSubsession & | subsession, | |
| responseHandler * | responseHandler, | |||
| Authenticator * | authenticator = NULL | |||
| ) |
Definition at line 105 of file RTSPClient.cpp.
References fCSeq, fCurrentAuthenticator, NULL, sendRequest(), and subsession.
00105 { 00106 if (authenticator != NULL) fCurrentAuthenticator = *authenticator; 00107 return sendRequest(new RequestRecord(++fCSeq, "TEARDOWN", responseHandler, NULL, &subsession)); 00108 }
| unsigned RTSPClient::sendSetParameterCommand | ( | MediaSession & | session, | |
| responseHandler * | responseHandler, | |||
| char const * | parameterName, | |||
| char const * | parameterValue, | |||
| Authenticator * | authenticator = NULL | |||
| ) |
Definition at line 110 of file RTSPClient.cpp.
References False, fCSeq, fCurrentAuthenticator, NULL, sendRequest(), and session.
00112 { 00113 if (authenticator != NULL) fCurrentAuthenticator = *authenticator; 00114 char* paramString = new char[strlen(parameterName) + strlen(parameterValue) + 10]; 00115 sprintf(paramString, "%s: %s\r\n", parameterName, parameterValue); 00116 unsigned result = sendRequest(new RequestRecord(++fCSeq, "SET_PARAMETER", responseHandler, &session, NULL, False, 0.0, 0.0, 0.0, paramString)); 00117 delete[] paramString; 00118 return result; 00119 }
| unsigned RTSPClient::sendGetParameterCommand | ( | MediaSession & | session, | |
| responseHandler * | responseHandler, | |||
| char const * | parameterName, | |||
| Authenticator * | authenticator = NULL | |||
| ) |
Definition at line 121 of file RTSPClient.cpp.
References False, fCSeq, fCurrentAuthenticator, NULL, sendRequest(), and session.
00122 { 00123 if (authenticator != NULL) fCurrentAuthenticator = *authenticator; 00124 00125 // We assume that: 00126 // parameterName is NULL means: Send no body in the request. 00127 // parameterName is "" means: Send only \r\n in the request body. 00128 // parameterName is non-empty means: Send "<parameterName>\r\n" as the request body. 00129 unsigned parameterNameLen = parameterName == NULL ? 0 : strlen(parameterName); 00130 char* paramString = new char[parameterNameLen + 3]; // the 3 is for \r\n + the '\0' byte 00131 if (parameterName == NULL) { 00132 paramString[0] = '\0'; 00133 } else { 00134 sprintf(paramString, "%s\r\n", parameterName); 00135 } 00136 unsigned result = sendRequest(new RequestRecord(++fCSeq, "GET_PARAMETER", responseHandler, &session, NULL, False, 0.0, 0.0, 0.0, paramString)); 00137 delete[] paramString; 00138 return result; 00139 }
| Boolean RTSPClient::changeResponseHandler | ( | unsigned | cseq, | |
| responseHandler * | newResponseHandler | |||
| ) |
Definition at line 141 of file RTSPClient.cpp.
References False, RTSPClient::RequestQueue::findByCSeq(), fRequestsAwaitingConnection, fRequestsAwaitingHTTPTunneling, fRequestsAwaitingResponse, RTSPClient::RequestRecord::handler(), NULL, and True.
00141 { 00142 // Look for the matching request record in each of our 'pending requests' queues: 00143 RequestRecord* request; 00144 if ((request = fRequestsAwaitingConnection.findByCSeq(cseq)) != NULL 00145 || (request = fRequestsAwaitingHTTPTunneling.findByCSeq(cseq)) != NULL 00146 || (request = fRequestsAwaitingResponse.findByCSeq(cseq)) != NULL) { 00147 request->handler() = newResponseHandler; 00148 return True; 00149 } 00150 00151 return False; 00152 }
| int RTSPClient::socketNum | ( | ) | const [inline] |
Definition at line 140 of file RTSPClient.hh.
References fInputSocketNum.
Referenced by DarwinInjector::setDestination().
00140 { return fInputSocketNum; }
| Boolean RTSPClient::lookupByName | ( | UsageEnvironment & | env, | |
| char const * | sourceName, | |||
| RTSPClient *& | resultClient | |||
| ) | [static] |
Definition at line 154 of file RTSPClient.cpp.
References env, False, Medium::isRTSPClient(), Medium::lookupByName(), NULL, and True.
00156 { 00157 resultClient = NULL; // unless we succeed 00158 00159 Medium* medium; 00160 if (!Medium::lookupByName(env, instanceName, medium)) return False; 00161 00162 if (!medium->isRTSPClient()) { 00163 env.setResultMsg(instanceName, " is not a RTSP client"); 00164 return False; 00165 } 00166 00167 resultClient = (RTSPClient*)medium; 00168 return True; 00169 }
| Boolean RTSPClient::parseRTSPURL | ( | UsageEnvironment & | env, | |
| char const * | url, | |||
| char *& | username, | |||
| char *& | password, | |||
| NetAddress & | address, | |||
| portNumBits & | portNum, | |||
| char const ** | urlSuffix = NULL | |||
| ) | [static] |
Definition at line 171 of file RTSPClient.cpp.
References _strncasecmp, env, False, NetAddressList::firstAddress(), NULL, NetAddressList::numAddresses(), UsageEnvironment::setResultMsg(), and True.
Referenced by openConnection(), and sendRequest().
00175 { 00176 do { 00177 // Parse the URL as "rtsp://[<username>[:<password>]@]<server-address-or-name>[:<port>][/<stream-name>]" 00178 char const* prefix = "rtsp://"; 00179 unsigned const prefixLength = 7; 00180 if (_strncasecmp(url, prefix, prefixLength) != 0) { 00181 env.setResultMsg("URL is not of the form \"", prefix, "\""); 00182 break; 00183 } 00184 00185 unsigned const parseBufferSize = 100; 00186 char parseBuffer[parseBufferSize]; 00187 char const* from = &url[prefixLength]; 00188 00189 // Check whether "<username>[:<password>]@" occurs next. 00190 // We do this by checking whether '@' appears before the end of the URL, or before the first '/'. 00191 username = password = NULL; // default return values 00192 char const* colonPasswordStart = NULL; 00193 char const* p; 00194 for (p = from; *p != '\0' && *p != '/'; ++p) { 00195 if (*p == ':' && colonPasswordStart == NULL) { 00196 colonPasswordStart = p; 00197 } else if (*p == '@') { 00198 // We found <username> (and perhaps <password>). Copy them into newly-allocated result strings: 00199 if (colonPasswordStart == NULL) colonPasswordStart = p; 00200 00201 char const* usernameStart = from; 00202 unsigned usernameLen = colonPasswordStart - usernameStart; 00203 username = new char[usernameLen + 1] ; // allow for the trailing '\0' 00204 for (unsigned i = 0; i < usernameLen; ++i) username[i] = usernameStart[i]; 00205 username[usernameLen] = '\0'; 00206 00207 char const* passwordStart = colonPasswordStart; 00208 if (passwordStart < p) ++passwordStart; // skip over the ':' 00209 unsigned passwordLen = p - passwordStart; 00210 password = new char[passwordLen + 1]; // allow for the trailing '\0' 00211 for (unsigned j = 0; j < passwordLen; ++j) password[j] = passwordStart[j]; 00212 password[passwordLen] = '\0'; 00213 00214 from = p + 1; // skip over the '@' 00215 break; 00216 } 00217 } 00218 00219 // Next, parse <server-address-or-name> 00220 char* to = &parseBuffer[0]; 00221 unsigned i; 00222 for (i = 0; i < parseBufferSize; ++i) { 00223 if (*from == '\0' || *from == ':' || *from == '/') { 00224 // We've completed parsing the address 00225 *to = '\0'; 00226 break; 00227 } 00228 *to++ = *from++; 00229 } 00230 if (i == parseBufferSize) { 00231 env.setResultMsg("URL is too long"); 00232 break; 00233 } 00234 00235 NetAddressList addresses(parseBuffer); 00236 if (addresses.numAddresses() == 0) { 00237 env.setResultMsg("Failed to find network address for \"", 00238 parseBuffer, "\""); 00239 break; 00240 } 00241 address = *(addresses.firstAddress()); 00242 00243 portNum = 554; // default value 00244 char nextChar = *from; 00245 if (nextChar == ':') { 00246 int portNumInt; 00247 if (sscanf(++from, "%d", &portNumInt) != 1) { 00248 env.setResultMsg("No port number follows ':'"); 00249 break; 00250 } 00251 if (portNumInt < 1 || portNumInt > 65535) { 00252 env.setResultMsg("Bad port number"); 00253 break; 00254 } 00255 portNum = (portNumBits)portNumInt; 00256 while (*from >= '0' && *from <= '9') ++from; // skip over port number 00257 } 00258 00259 // The remainder of the URL is the suffix: 00260 if (urlSuffix != NULL) *urlSuffix = from; 00261 00262 return True; 00263 } while (0); 00264 00265 return False; 00266 }
| void RTSPClient::setUserAgentString | ( | char const * | userAgentName | ) |
Definition at line 268 of file RTSPClient.cpp.
References fUserAgentHeaderStr, fUserAgentHeaderStrLen, and NULL.
Referenced by RTSPClient().
00268 { 00269 if (userAgentName == NULL) return; 00270 00271 // Change the existing user agent header string: 00272 char const* const formatStr = "User-Agent: %s\r\n"; 00273 unsigned const headerSize = strlen(formatStr) + strlen(userAgentName); 00274 delete[] fUserAgentHeaderStr; 00275 fUserAgentHeaderStr = new char[headerSize]; 00276 sprintf(fUserAgentHeaderStr, formatStr, userAgentName); 00277 fUserAgentHeaderStrLen = strlen(fUserAgentHeaderStr); 00278 }
| unsigned RTSPClient::sessionTimeoutParameter | ( | ) | const [inline] |
Definition at line 154 of file RTSPClient.hh.
References fSessionTimeoutParameter.
00154 { return fSessionTimeoutParameter; }
| char const* RTSPClient::url | ( | ) | const [inline] |
Definition at line 156 of file RTSPClient.hh.
References fBaseURL.
Referenced by operator<<(), and sessionURL().
00156 { return fBaseURL; }
| void RTSPClient::setBaseURL | ( | char const * | url | ) | [protected] |
Definition at line 353 of file RTSPClient.cpp.
References fBaseURL, and strDup().
Referenced by handleResponseBytes(), reset(), and RTSPClient().
| Boolean RTSPClient::isRTSPClient | ( | ) | const [private, virtual] |
Reimplemented from Medium.
Definition at line 320 of file RTSPClient.cpp.
References True.
00320 { 00321 return True; 00322 }
| void RTSPClient::reset | ( | ) | [private] |
Definition at line 324 of file RTSPClient.cpp.
References fCurrentAuthenticator, fLastSessionId, fServerAddress, NULL, Authenticator::reset(), resetResponseBuffer(), resetTCPSockets(), and setBaseURL().
Referenced by ~RTSPClient().
00324 { 00325 resetTCPSockets(); 00326 resetResponseBuffer(); 00327 fServerAddress = 0; 00328 00329 setBaseURL(NULL); 00330 00331 fCurrentAuthenticator.reset(); 00332 00333 delete[] fLastSessionId; fLastSessionId = NULL; 00334 }
| void RTSPClient::resetTCPSockets | ( | ) | [private] |
Definition at line 336 of file RTSPClient.cpp.
References closeSocket, TaskScheduler::disableBackgroundHandling(), Medium::envir(), fInputSocketNum, fOutputSocketNum, and UsageEnvironment::taskScheduler().
Referenced by connectionHandler1(), handleResponseBytes(), openConnection(), reset(), and responseHandlerForHTTP_GET1().
00336 { 00337 if (fInputSocketNum >= 0) { 00338 envir().taskScheduler().disableBackgroundHandling(fInputSocketNum); 00339 ::closeSocket(fInputSocketNum); 00340 if (fOutputSocketNum != fInputSocketNum) { 00341 envir().taskScheduler().disableBackgroundHandling(fOutputSocketNum); 00342 ::closeSocket(fOutputSocketNum); 00343 } 00344 } 00345 fInputSocketNum = fOutputSocketNum = -1; 00346 }
| void RTSPClient::resetResponseBuffer | ( | ) | [private] |
Definition at line 348 of file RTSPClient.cpp.
References fResponseBufferBytesLeft, fResponseBytesAlreadySeen, and responseBufferSize.
Referenced by handleResponseBytes(), reset(), and RTSPClient().
00348 { 00349 fResponseBytesAlreadySeen = 0; 00350 fResponseBufferBytesLeft = responseBufferSize; 00351 }
| int RTSPClient::openConnection | ( | ) | [private] |
Definition at line 357 of file RTSPClient.cpp.
References connectToServer(), NetAddress::data(), Medium::envir(), fBaseURL, fCurrentAuthenticator, fInputSocketNum, fOutputSocketNum, fServerAddress, fTunnelOverHTTPPortNum, incomingDataHandler(), NULL, parseRTSPURL(), password, resetTCPSockets(), TaskScheduler::setBackgroundHandling(), setupStreamSocket(), Authenticator::setUsernameAndPassword(), SOCKET_READABLE, UsageEnvironment::taskScheduler(), and username.
Referenced by sendRequest().
00357 { 00358 do { 00359 // Set up a connection to the server. Begin by parsing the URL: 00360 00361 char* username; 00362 char* password; 00363 NetAddress destAddress; 00364 portNumBits urlPortNum; 00365 char const* urlSuffix; 00366 if (!parseRTSPURL(envir(), fBaseURL, username, password, destAddress, urlPortNum, &urlSuffix)) break; 00367 portNumBits destPortNum = fTunnelOverHTTPPortNum == 0 ? urlPortNum : fTunnelOverHTTPPortNum; 00368 if (username != NULL || password != NULL) { 00369 fCurrentAuthenticator.setUsernameAndPassword(username, password); 00370 delete[] username; 00371 delete[] password; 00372 } 00373 00374 // We don't yet have a TCP socket (or we used to have one, but it got closed). Set it up now. 00375 fInputSocketNum = fOutputSocketNum = setupStreamSocket(envir(), 0); 00376 if (fInputSocketNum < 0) break; 00377 00378 // Connect to the remote endpoint: 00379 fServerAddress = *(netAddressBits*)(destAddress.data()); 00380 int connectResult = connectToServer(fInputSocketNum, destPortNum); 00381 if (connectResult < 0) break; 00382 else if (connectResult > 0) { 00383 // The connection succeeded. Arrange to handle responses to requests sent on it: 00384 envir().taskScheduler().setBackgroundHandling(fInputSocketNum, SOCKET_READABLE, 00385 (TaskScheduler::BackgroundHandlerProc*)&incomingDataHandler, this); 00386 } 00387 return connectResult; 00388 } while (0); 00389 00390 resetTCPSockets(); 00391 return -1; 00392 }
| int RTSPClient::connectToServer | ( | int | socketNum, | |
| portNumBits | remotePortNum | |||
| ) | [private] |
Definition at line 394 of file RTSPClient.cpp.
References connectionHandler(), Medium::envir(), fServerAddress, fVerbosityLevel, UsageEnvironment::getErrno(), UsageEnvironment::getResultMsg(), MAKE_SOCKADDR_IN, TaskScheduler::setBackgroundHandling(), UsageEnvironment::setResultErrMsg(), SOCKET_EXCEPTION, SOCKET_WRITABLE, and UsageEnvironment::taskScheduler().
Referenced by openConnection(), and responseHandlerForHTTP_GET1().
00394 { 00395 MAKE_SOCKADDR_IN(remoteName, fServerAddress, htons(remotePortNum)); 00396 if (fVerbosityLevel >= 1) { 00397 envir() << "Opening connection to " << AddressString(remoteName).val() << ", port " << remotePortNum << "...\n"; 00398 } 00399 if (connect(socketNum, (struct sockaddr*) &remoteName, sizeof remoteName) != 0) { 00400 int const err = envir().getErrno(); 00401 if (err == EINPROGRESS || err == EWOULDBLOCK) { 00402 // The connection is pending; we'll need to handle it later. Wait for our socket to be 'writable', or have an exception. 00403 envir().taskScheduler().setBackgroundHandling(socketNum, SOCKET_WRITABLE|SOCKET_EXCEPTION, 00404 (TaskScheduler::BackgroundHandlerProc*)&connectionHandler, this); 00405 return 0; 00406 } 00407 envir().setResultErrMsg("connect() failed: "); 00408 if (fVerbosityLevel >= 1) envir() << "..." << envir().getResultMsg() << "\n"; 00409 return -1; 00410 } 00411 if (fVerbosityLevel >= 1) envir() << "...local connection opened\n"; 00412 00413 return 1; 00414 }
| char * RTSPClient::createAuthenticatorString | ( | char const * | cmd, | |
| char const * | url | |||
| ) | [private] |
Definition at line 417 of file RTSPClient.cpp.
References base64Encode(), Authenticator::computeDigestResponse(), fCurrentAuthenticator, Authenticator::nonce(), NULL, Authenticator::password(), Authenticator::realm(), Authenticator::reclaimDigestResponse(), strDup(), and Authenticator::username().
Referenced by sendRequest().
00417 { 00418 Authenticator& auth = fCurrentAuthenticator; // alias, for brevity 00419 if (auth.realm() != NULL && auth.username() != NULL && auth.password() != NULL) { 00420 // We have a filled-in authenticator, so use it: 00421 char* authenticatorStr; 00422 if (auth.nonce() != NULL) { // Digest authentication 00423 char const* const authFmt = 00424 "Authorization: Digest username=\"%s\", realm=\"%s\", " 00425 "nonce=\"%s\", uri=\"%s\", response=\"%s\"\r\n"; 00426 char const* response = auth.computeDigestResponse(cmd, url); 00427 unsigned authBufSize = strlen(authFmt) 00428 + strlen(auth.username()) + strlen(auth.realm()) 00429 + strlen(auth.nonce()) + strlen(url) + strlen(response); 00430 authenticatorStr = new char[authBufSize]; 00431 sprintf(authenticatorStr, authFmt, 00432 auth.username(), auth.realm(), 00433 auth.nonce(), url, response); 00434 auth.reclaimDigestResponse(response); 00435 } else { // Basic authentication 00436 char const* const authFmt = "Authorization: Basic %s\r\n"; 00437 00438 unsigned usernamePasswordLength = strlen(auth.username()) + 1 + strlen(auth.password()); 00439 char* usernamePassword = new char[usernamePasswordLength+1]; 00440 sprintf(usernamePassword, "%s:%s", auth.username(), auth.password()); 00441 00442 char* response = base64Encode(usernamePassword, usernamePasswordLength); 00443 unsigned const authBufSize = strlen(authFmt) + strlen(response) + 1; 00444 authenticatorStr = new char[authBufSize]; 00445 sprintf(authenticatorStr, authFmt, response); 00446 delete[] response; delete[] usernamePassword; 00447 } 00448 00449 return authenticatorStr; 00450 } 00451 00452 // We don't have a (filled-in) authenticator. 00453 return strDup(""); 00454 }
| unsigned RTSPClient::sendRequest | ( | RequestRecord * | request | ) | [private] |
Definition at line 498 of file RTSPClient.cpp.
References base64Encode(), RTSPClient::RequestRecord::booleanFlags(), MediaSubsession::clientPortNum(), RTSPClient::RequestRecord::commandName(), MediaSubsession::connectionEndpointAddress(), constructSubsessionURL(), RTSPClient::RequestRecord::contentStr(), createAuthenticatorString(), createRangeString(), createScaleString(), createSessionString(), RTSPClient::RequestRecord::cseq(), RTSPClient::RequestRecord::end(), RTSPClient::RequestQueue::enqueue(), Medium::envir(), False, fBaseURL, fInputSocketNum, fLastSessionId, fOutputSocketNum, fRequestsAwaitingConnection, fRequestsAwaitingHTTPTunneling, fRequestsAwaitingResponse, fSessionCookie, fSessionCookieCounter, fTCPStreamIdCount, fTunnelOverHTTPPortNum, fUserAgentHeaderStr, fUserAgentHeaderStrLen, fVerbosityLevel, handleRequestError(), RTSPClient::RequestQueue::isEmpty(), IsMulticastAddress(), NULL, openConnection(), our_MD5Data(), parseRTSPURL(), password, MediaSubsession::protocolName(), RTSPClient::RequestRecord::scale(), MediaSubsession::scale(), MediaSession::scale(), RTSPClient::RequestRecord::session(), MediaSubsession::sessionId(), sessionURL(), UsageEnvironment::setResultErrMsg(), UsageEnvironment::setResultMsg(), setupHTTPTunneling1(), RTSPClient::RequestRecord::start(), streamUsingTCP, RTSPClient::RequestRecord::subsession(), subsession, True, and username.
Referenced by connectionHandler1(), resendCommand(), responseHandlerForHTTP_GET1(), sendAnnounceCommand(), sendDescribeCommand(), sendGetParameterCommand(), sendOptionsCommand(), sendPauseCommand(), sendPlayCommand(), sendRecordCommand(), sendSetParameterCommand(), sendSetupCommand(), sendTeardownCommand(), setupHTTPTunneling1(), and setupHTTPTunneling2().
00498 { 00499 char* cmd = NULL; 00500 do { 00501 Boolean connectionIsPending = False; 00502 if (!fRequestsAwaitingConnection.isEmpty()) { 00503 // A connection is currently pending (with at least one enqueued request). Enqueue this request also: 00504 connectionIsPending = True; 00505 } else if (fInputSocketNum < 0) { // we need to open a connection 00506 int connectResult = openConnection(); 00507 if (connectResult < 0) break; // an error occurred 00508 else if (connectResult == 0) { 00509 // A connection is pending 00510 connectionIsPending = True; 00511 } // else the connection succeeded. Continue sending the command.u 00512 } 00513 if (connectionIsPending) { 00514 fRequestsAwaitingConnection.enqueue(request); 00515 return request->cseq(); 00516 } 00517 00518 // If requested (and we're not already doing it, or have done it), set up the special protocol for tunneling RTSP-over-HTTP: 00519 if (fTunnelOverHTTPPortNum != 0 && strcmp(request->commandName(), "GET") != 0 && fOutputSocketNum == fInputSocketNum) { 00520 if (!setupHTTPTunneling1()) break; 00521 fRequestsAwaitingHTTPTunneling.enqueue(request); 00522 return request->cseq(); 00523 } 00524 00525 // Construct and send the command: 00526 00527 // First, construct command-specific headers that we need: 00528 00529 char* cmdURL = fBaseURL; // by default 00530 Boolean cmdURLWasAllocated = False; 00531 00532 char const* protocolStr = "RTSP/1.0"; // by default 00533 00534 char* extraHeaders = (char*)""; // by default 00535 Boolean extraHeadersWereAllocated = False; 00536 00537 char* contentLengthHeader = (char*)""; // by default 00538 Boolean contentLengthHeaderWasAllocated = False; 00539 00540 char const* contentStr = request->contentStr(); // by default 00541 if (contentStr == NULL) contentStr = ""; 00542 unsigned contentStrLen = strlen(contentStr); 00543 if (contentStrLen > 0) { 00544 char const* contentLengthHeaderFmt = 00545 "Content-Length: %d\r\n"; 00546 unsigned contentLengthHeaderSize = strlen(contentLengthHeaderFmt) 00547 + 20 /* max int len */; 00548 contentLengthHeader = new char[contentLengthHeaderSize]; 00549 sprintf(contentLengthHeader, contentLengthHeaderFmt, contentStrLen); 00550 contentLengthHeaderWasAllocated = True; 00551 } 00552 00553 if (strcmp(request->commandName(), "DESCRIBE") == 0) { 00554 extraHeaders = (char*)"Accept: application/sdp\r\n"; 00555 } else if (strcmp(request->commandName(), "OPTIONS") == 0) { 00556 } else if (strcmp(request->commandName(), "ANNOUNCE") == 0) { 00557 extraHeaders = (char*)"Content-Type: application/sdp\r\n"; 00558 } else if (strcmp(request->commandName(), "SETUP") == 0) { 00559 MediaSubsession& subsession = *request->subsession(); 00560 Boolean streamUsingTCP = (request->booleanFlags()&0x1) != 0; 00561 Boolean streamOutgoing = (request->booleanFlags()&0x2) != 0; 00562 Boolean forceMulticastOnUnspecified = (request->booleanFlags()&0x4) != 0; 00563 00564 char const *prefix, *separator, *suffix; 00565 constructSubsessionURL(subsession, prefix, separator, suffix); 00566 00567 char const* transportFmt; 00568 if (strcmp(subsession.protocolName(), "UDP") == 0) { 00569 suffix = ""; 00570 transportFmt = "Transport: RAW/RAW/UDP%s%s%s=%d-%d\r\n"; 00571 } else { 00572 transportFmt = "Transport: RTP/AVP%s%s%s=%d-%d\r\n"; 00573 } 00574 00575 cmdURL = new char[strlen(prefix) + strlen(separator) + strlen(suffix) + 1]; 00576 cmdURLWasAllocated = True; 00577 sprintf(cmdURL, "%s%s%s", prefix, separator, suffix); 00578 00579 // Construct a "Transport:" header. 00580 char const* transportTypeStr; 00581 char const* modeStr = streamOutgoing ? ";mode=receive" : ""; 00582 // Note: I think the above is nonstandard, but DSS wants it this way 00583 char const* portTypeStr; 00584 portNumBits rtpNumber, rtcpNumber; 00585 if (streamUsingTCP) { // streaming over the RTSP connection 00586 transportTypeStr = "/TCP;unicast"; 00587 portTypeStr = ";interleaved"; 00588 rtpNumber = fTCPStreamIdCount++; 00589 rtcpNumber = fTCPStreamIdCount++; 00590 } else { // normal RTP streaming 00591 unsigned connectionAddress = subsession.connectionEndpointAddress(); 00592 Boolean requestMulticastStreaming 00593 = IsMulticastAddress(connectionAddress) || (connectionAddress == 0 && forceMulticastOnUnspecified); 00594 transportTypeStr = requestMulticastStreaming ? ";multicast" : ";unicast"; 00595 portTypeStr = ";client_port"; 00596 rtpNumber = subsession.clientPortNum(); 00597 if (rtpNumber == 0) { 00598 envir().setResultMsg("Client port number unknown\n"); 00599 delete[] cmdURL; 00600 break; 00601 } 00602 rtcpNumber = rtpNumber + 1; 00603 } 00604 unsigned transportSize = strlen(transportFmt) 00605 + strlen(transportTypeStr) + strlen(modeStr) + strlen(portTypeStr) + 2*5 /* max port len */; 00606 char* transportStr = new char[transportSize]; 00607 sprintf(transportStr, transportFmt, 00608 transportTypeStr, modeStr, portTypeStr, rtpNumber, rtcpNumber); 00609 00610 // When sending more than one "SETUP" request, include a "Session:" header in the 2nd and later commands: 00611 char* sessionStr = createSessionString(fLastSessionId); 00612 00613 // The "Transport:" and "Session:" (if present) headers make up the 'extra headers': 00614 extraHeaders = new char[transportSize + strlen(sessionStr)]; 00615 extraHeadersWereAllocated = True; 00616 sprintf(extraHeaders, "%s%s", transportStr, sessionStr); 00617 delete[] transportStr; delete[] sessionStr; 00618 } else if (strcmp(request->commandName(), "GET") == 0 || strcmp(request->commandName(), "POST") == 0) { 00619 // We will be sending a HTTP (not a RTSP) request. 00620 // Begin by re-parsing our RTSP URL, just to get the stream name, which we'll use as our 'cmdURL' in the subsequent request: 00621 char* username; 00622 char* password; 00623 NetAddress destAddress; 00624 portNumBits urlPortNum; 00625 if (!parseRTSPURL(envir(), fBaseURL, username, password, destAddress, urlPortNum, (char const**)&cmdURL)) break; 00626 if (cmdURL[0] == '\0') cmdURL = (char*)"/"; 00627 delete[] username; 00628 delete[] password; 00629 00630 protocolStr = "HTTP/1.0"; 00631 00632 if (strcmp(request->commandName(), "GET") == 0) { 00633 // Create a 'session cookie' string, using MD5: 00634 struct { 00635 struct timeval timestamp; 00636 unsigned counter; 00637 } seedData; 00638 gettimeofday(&seedData.timestamp, NULL); 00639 seedData.counter = ++fSessionCookieCounter; 00640 our_MD5Data((unsigned char*)(&seedData), sizeof seedData, fSessionCookie); 00641 // DSS seems to require that the 'session cookie' string be 22 bytes long: 00642 fSessionCookie[23] = '\0'; 00643 00644 char const* const extraHeadersFmt = 00645 "x-sessioncookie: %s\r\n" 00646 "Accept: application/x-rtsp-tunnelled\r\n" 00647 "Pragma: no-cache\r\n" 00648 "Cache-Control: no-cache\r\n"; 00649 unsigned extraHeadersSize = strlen(extraHeadersFmt) 00650 + strlen(fSessionCookie); 00651 extraHeaders = new char[extraHeadersSize]; 00652 extraHeadersWereAllocated = True; 00653 sprintf(extraHeaders, extraHeadersFmt, 00654 fSessionCookie); 00655 } else { // "POST" 00656 char const* const extraHeadersFmt = 00657 "x-sessioncookie: %s\r\n" 00658 "Content-Type: application/x-rtsp-tunnelled\r\n" 00659 "Pragma: no-cache\r\n" 00660 "Cache-Control: no-cache\r\n" 00661 "Content-Length: 32767\r\n" 00662 "Expires: Sun, 9 Jan 1972 00:00:00 GMT\r\n"; 00663 unsigned extraHeadersSize = strlen(extraHeadersFmt) 00664 + strlen(fSessionCookie); 00665 extraHeaders = new char[extraHeadersSize]; 00666 extraHeadersWereAllocated = True; 00667 sprintf(extraHeaders, extraHeadersFmt, 00668 fSessionCookie); 00669 } 00670 } else { // "PLAY", "PAUSE", "TEARDOWN", "RECORD", "SET_PARAMETER", "GET_PARAMETER" 00671 // First, make sure that we have a RTSP session in progress 00672 if (fLastSessionId == NULL) { 00673 envir().setResultMsg("No RTSP session is currently in progress\n"); 00674 break; 00675 } 00676 00677 char const* sessionId; 00678 float originalScale; 00679 if (request->session() != NULL) { 00680 // Session-level operation 00681 cmdURL = (char*)sessionURL(*request->session()); 00682 00683 sessionId = fLastSessionId; 00684 originalScale = request->session()->scale(); 00685 } else { 00686 // Media-level operation 00687 char const *prefix, *separator, *suffix; 00688 constructSubsessionURL(*request->subsession(), prefix, separator, suffix); 00689 cmdURL = new char[strlen(prefix) + strlen(separator) + strlen(suffix) + 1]; 00690 cmdURLWasAllocated = True; 00691 sprintf(cmdURL, "%s%s%s", prefix, separator, suffix); 00692 00693 sessionId = request->subsession()->sessionId(); 00694 originalScale = request->subsession()->scale(); 00695 } 00696 00697 if (strcmp(request->commandName(), "PLAY") == 0) { 00698 // Create "Session:", "Scale:", and "Range:" headers; these make up the 'extra headers': 00699 char* sessionStr = createSessionString(sessionId); 00700 char* scaleStr = createScaleString(request->scale(), originalScale); 00701 char* rangeStr = createRangeString(request->start(), request->end()); 00702 extraHeaders = new char[strlen(sessionStr) + strlen(scaleStr) + strlen(rangeStr) + 1]; 00703 extraHeadersWereAllocated = True; 00704 sprintf(extraHeaders, "%s%s%s", sessionStr, scaleStr, rangeStr); 00705 delete[] sessionStr; delete[] scaleStr; delete[] rangeStr; 00706 } else { 00707 // Create a "Session:" header; this makes up our 'extra headers': 00708 extraHeaders = createSessionString(sessionId); 00709 extraHeadersWereAllocated = True; 00710 } 00711 } 00712 00713 char* authenticatorStr = createAuthenticatorString(request->commandName(), fBaseURL); 00714 00715 char const* const cmdFmt = 00716 "%s %s %s\r\n" 00717 "CSeq: %d\r\n" 00718 "%s" 00719 "%s" 00720 "%s" 00721 "%s" 00722 "\r\n" 00723 "%s"; 00724 unsigned cmdSize = strlen(cmdFmt) 00725 + strlen(request->commandName()) + strlen(cmdURL) + strlen(protocolStr) 00726 + 20 /* max int len */ 00727 + strlen(authenticatorStr) 00728 + fUserAgentHeaderStrLen 00729 + strlen(extraHeaders) 00730 + strlen(contentLengthHeader) 00731 + contentStrLen; 00732 cmd = new char[cmdSize]; 00733 sprintf(cmd, cmdFmt, 00734 request->commandName(), cmdURL, protocolStr, 00735 request->cseq(), 00736 authenticatorStr, 00737 fUserAgentHeaderStr, 00738 extraHeaders, 00739 contentLengthHeader, 00740 contentStr); 00741 delete[] authenticatorStr; 00742 if (cmdURLWasAllocated) delete[] cmdURL; 00743 if (extraHeadersWereAllocated) delete[] extraHeaders; 00744 if (contentLengthHeaderWasAllocated) delete[] contentLengthHeader; 00745 00746 if (fVerbosityLevel >= 1) envir() << "Sending request: " << cmd << "\n"; 00747 00748 if (fTunnelOverHTTPPortNum != 0 && strcmp(request->commandName(), "GET") != 0 && strcmp(request->commandName(), "POST") != 0) { 00749 // When we're tunneling RTSP-over-HTTP, we Base-64-encode the request before we send it. 00750 // (However, we don't do this for the HTTP "GET" and "POST" commands that we use to set up the tunnel.) 00751 char* origCmd = cmd; 00752 cmd = base64Encode(origCmd, strlen(cmd)); 00753 if (fVerbosityLevel >= 1) envir() << "\tThe request was base-64 encoded to: " << cmd << "\n\n"; 00754 delete[] origCmd; 00755 } 00756 00757 if (send(fOutputSocketNum, cmd, strlen(cmd), 0) < 0) { 00758 char const* errFmt = "%s send() failed: "; 00759 unsigned const errLength = strlen(errFmt) + strlen(request->commandName()); 00760 char* err = new char[errLength]; 00761 sprintf(err, errFmt, request->commandName()); 00762 envir().setResultErrMsg(err); 00763 delete[] err; 00764 break; 00765 } 00766 00767 // The command send succeeded, so enqueue the request record, so that its response (when it comes) can be handled: 00768 fRequestsAwaitingResponse.enqueue(request); 00769 00770 delete[] cmd; 00771 return request->cseq(); 00772 } while (0); 00773 00774 // An error occurred, so call the response handler immediately (indicating the error): 00775 delete[] cmd; 00776 handleRequestError(request); 00777 delete request; 00778 return 0; 00779 }
| void RTSPClient::handleRequestError | ( | RequestRecord * | request | ) | [private] |
Definition at line 781 of file RTSPClient.cpp.
References Medium::envir(), UsageEnvironment::getErrno(), RTSPClient::RequestRecord::handler(), NULL, and strDup().
Referenced by connectionHandler1(), handleResponseBytes(), responseHandlerForHTTP_GET1(), and sendRequest().
00781 { 00782 int resultCode = -envir().getErrno(); 00783 if (resultCode == 0) { 00784 // Choose some generic error code instead: 00785 #if defined(__WIN32__) || defined(_WIN32) || defined(_QNX4) 00786 resultCode = -WSAENOTCONN; 00787 #else 00788 resultCode = -ENOTCONN; 00789 #endif 00790 } 00791 if (request->handler() != NULL) (*request->handler())(this, resultCode, strDup(envir().getResultMsg())); 00792 }
| Boolean RTSPClient::parseResponseCode | ( | char const * | line, | |
| unsigned & | responseCode, | |||
| char const *& | responseString | |||
| ) | [private] |
Definition at line 795 of file RTSPClient.cpp.
Referenced by handleResponseBytes().
00795 { 00796 if (sscanf(line, "RTSP/%*s%u", &responseCode) != 1 && 00797 sscanf(line, "HTTP/%*s%u", &responseCode) != 1) return False; 00798 // Note: We check for HTTP responses as well as RTSP responses, both in order to setup RTSP-over-HTTP tunneling, 00799 // and so that we get back a meaningful error if the client tried to mistakenly send a RTSP command to a HTTP-only server. 00800 00801 // Use everything after the RTSP/* (or HTTP/*) as the response string: 00802 responseString = line; 00803 while (responseString[0] != '\0' && responseString[0] != ' ' && responseString[0] != '\t') ++responseString; 00804 while (responseString[0] != '\0' && (responseString[0] == ' ' || responseString[0] == '\t')) ++responseString; // skip whitespace 00805 00806 return True; 00807 }
| void RTSPClient::handleIncomingRequest | ( | ) | [private] |
Definition at line 809 of file RTSPClient.cpp.
References Medium::envir(), fOutputSocketNum, fResponseBuffer, fResponseBytesAlreadySeen, fVerbosityLevel, parseRTSPRequestString(), and RTSP_PARAM_STRING_MAX.
Referenced by handleResponseBytes().
00809 { 00810 // Parse the request string into command name and 'CSeq', then 'handle' the command (by responding that we don't support it): 00811 char cmdName[RTSP_PARAM_STRING_MAX]; 00812 char urlPreSuffix[RTSP_PARAM_STRING_MAX]; 00813 char urlSuffix[RTSP_PARAM_STRING_MAX]; 00814 char cseq[RTSP_PARAM_STRING_MAX]; 00815 unsigned contentLength; 00816 if (!parseRTSPRequestString(fResponseBuffer, fResponseBytesAlreadySeen, 00817 cmdName, sizeof cmdName, 00818 urlPreSuffix, sizeof urlPreSuffix, 00819 urlSuffix, sizeof urlSuffix, 00820 cseq, sizeof cseq, 00821 contentLength)) { 00822 return; 00823 } else { 00824 if (fVerbosityLevel >= 1) { 00825 envir() << "Received incoming RTSP request: " << fResponseBuffer << "\n"; 00826 } 00827 char tmpBuf[2*RTSP_PARAM_STRING_MAX]; 00828 snprintf((char*)tmpBuf, sizeof tmpBuf, 00829 "RTSP/1.0 405 Method Not Allowed\r\nCSeq: %s\r\n\r\n", cseq); 00830 send(fOutputSocketNum, tmpBuf, strlen(tmpBuf), 0); 00831 } 00832 }
| Boolean RTSPClient::checkForHeader | ( | char const * | line, | |
| char const * | headerName, | |||
| unsigned | headerNameLength, | |||
| char const *& | headerParams | |||
| ) | [static, private] |
Definition at line 834 of file RTSPClient.cpp.
References _strncasecmp, False, and True.
Referenced by handleResponseBytes().
00834 { 00835 if (_strncasecmp(line, headerName, headerNameLength) != 0) return False; 00836 00837 // The line begins with the desired header name. Trim off any whitespace, and return the header parameters: 00838 unsigned paramIndex = headerNameLength; 00839 while (line[paramIndex] != '\0' && (line[paramIndex] == ' ' || line[paramIndex] == '\t')) ++paramIndex; 00840 if (&line[paramIndex] == '\0') return False; // the header is assumed to be bad if it has no parameters 00841 00842 headerParams = &line[paramIndex]; 00843 return True; 00844 }
| Boolean RTSPClient::parseTransportParams | ( | char const * | paramsStr, | |
| char *& | serverAddressStr, | |||
| portNumBits & | serverPortNum, | |||
| unsigned char & | rtpChannelId, | |||
| unsigned char & | rtcpChannelId | |||
| ) | [private] |
Definition at line 846 of file RTSPClient.cpp.
References _strncasecmp, False, NULL, strDup(), strDupSize(), and True.
Referenced by handleSETUPResponse().
00848 { 00849 // Initialize the return parameters to 'not found' values: 00850 serverAddressStr = NULL; 00851 serverPortNum = 0; 00852 rtpChannelId = rtcpChannelId = 0xFF; 00853 00854 char* foundServerAddressStr = NULL; 00855 Boolean foundServerPortNum = False; 00856 portNumBits clientPortNum = 0; 00857 Boolean foundClientPortNum = False; 00858 Boolean foundChannelIds = False; 00859 unsigned rtpCid, rtcpCid; 00860 Boolean isMulticast = True; // by default 00861 char* foundDestinationStr = NULL; 00862 portNumBits multicastPortNumRTP, multicastPortNumRTCP; 00863 Boolean foundMulticastPortNum = False; 00864 00865 // Run through each of the parameters, looking for ones that we handle: 00866 char const* fields = paramsStr; 00867 char* field = strDupSize(fields); 00868 while (sscanf(fields, "%[^;]", field) == 1) { 00869 if (sscanf(field, "server_port=%hu", &serverPortNum) == 1) { 00870 foundServerPortNum = True; 00871 } else if (sscanf(field, "client_port=%hu", &clientPortNum) == 1) { 00872 foundClientPortNum = True; 00873 } else if (_strncasecmp(field, "source=", 7) == 0) { 00874 delete[] foundServerAddressStr; 00875 foundServerAddressStr = strDup(field+7); 00876 } else if (sscanf(field, "interleaved=%u-%u", &rtpCid, &rtcpCid) == 2) { 00877 rtpChannelId = (unsigned char)rtpCid; 00878 rtcpChannelId = (unsigned char)rtcpCid; 00879 foundChannelIds = True; 00880 } else if (strcmp(field, "unicast") == 0) { 00881 isMulticast = False; 00882 } else if (_strncasecmp(field, "destination=", 12) == 0) { 00883 delete[] foundDestinationStr; 00884 foundDestinationStr = strDup(field+12); 00885 } else if (sscanf(field, "port=%hu-%hu", &multicastPortNumRTP, &multicastPortNumRTCP) == 2 || 00886 sscanf(field, "port=%hu", &multicastPortNumRTP) == 1) { 00887 foundMulticastPortNum = True; 00888 } 00889 00890 fields += strlen(field); 00891 while (fields[0] == ';') ++fields; // skip over all leading ';' chars 00892 if (fields[0] == '\0') break; 00893 } 00894 delete[] field; 00895 00896 // If we're multicast, and have a "destination=" (multicast) address, then use this 00897 // as the 'server' address (because some weird servers don't specify the multicast 00898 // address earlier, in the "DESCRIBE" response's SDP: 00899 if (isMulticast && foundDestinationStr != NULL && foundMulticastPortNum) { 00900 delete[] foundServerAddressStr; 00901 serverAddressStr = foundDestinationStr; 00902 serverPortNum = multicastPortNumRTP; 00903 return True; 00904 } 00905 delete[] foundDestinationStr; 00906 00907 // We have a valid "Transport:" header if any of the following are true: 00908 // - We saw a "interleaved=" field, indicating RTP/RTCP-over-TCP streaming, or 00909 // - We saw a "server_port=" field, or 00910 // - We saw a "client_port=" field. 00911 // If we didn't also see a "server_port=" field, then the server port is assumed to be the same as the client port. 00912 if (foundChannelIds || foundServerPortNum || foundClientPortNum) { 00913 if (foundClientPortNum && !foundServerPortNum) { 00914 serverPortNum = clientPortNum; 00915 } 00916 serverAddressStr = foundServerAddressStr; 00917 return True; 00918 } 00919 00920 delete[] foundServerAddressStr; 00921 return False; 00922 }
| Boolean RTSPClient::parseScaleParam | ( | char const * | paramStr, | |
| float & | scale | |||
| ) | [private] |
Definition at line 924 of file RTSPClient.cpp.
References Numeric.
Referenced by handlePLAYResponse().
| Boolean RTSPClient::parseRTPInfoParams | ( | char const *& | paramStr, | |
| u_int16_t & | seqNum, | |||
| u_int32_t & | timestamp | |||
| ) | [private] |
Definition at line 929 of file RTSPClient.cpp.
References strDupSize(), and True.
Referenced by handlePLAYResponse().
00929 { 00930 while (paramsStr[0] == ',') ++paramsStr; 00931 00932 // "paramsStr" now consists of a ';'-separated list of parameters, ending with ',' or '\0'. 00933 char* field = strDupSize(paramsStr); 00934 00935 while (sscanf(paramsStr, "%[^;,]", field) == 1) { 00936 if (sscanf(field, "seq=%hu", &seqNum) == 1 || 00937 sscanf(field, "rtptime=%u", ×tamp) == 1) { 00938 } 00939 00940 paramsStr += strlen(field); 00941 if (paramsStr[0] == '\0' || paramsStr[0] == ',') break; 00942 // ASSERT: paramsStr[0] == ';' 00943 ++paramsStr; // skip over the ';' 00944 } 00945 00946 delete[] field; 00947 return True; 00948 }
| Boolean RTSPClient::handleSETUPResponse | ( | MediaSubsession & | subsession, | |
| char const * | sessionParamsStr, | |||
| char const * | transportParamsStr, | |||
| Boolean | streamUsingTCP | |||
| ) | [private] |
Definition at line 950 of file RTSPClient.cpp.
References MediaSubsession::connectionEndpointAddress(), MediaSubsession::connectionEndpointName(), Medium::envir(), False, fInputSocketNum, fLastSessionId, fServerAddress, fSessionTimeoutParameter, handleAlternativeRequestByte(), NULL, Groupsock::output(), parseTransportParams(), responseBufferSize, MediaSubsession::rtcpChannelId, MediaSubsession::rtcpInstance(), MediaSubsession::rtpChannelId, RTPSource::RTPgs(), MediaSubsession::rtpSource(), MediaSubsession::serverPortNum, MediaSubsession::setDestinations(), UsageEnvironment::setResultMsg(), RTPSource::setServerRequestAlternativeByteHandler(), MediaSubsession::setSessionId(), RTCPInstance::setStreamSocket(), RTPSource::setStreamSocket(), strDup(), subsession, and True.
Referenced by handleResponseBytes().
00951 { 00952 char* sessionId = new char[responseBufferSize]; // ensures we have enough space 00953 Boolean success = False; 00954 do { 00955 // Check for a session id: 00956 if (sessionParamsStr == NULL || sscanf(sessionParamsStr, "%[^;]", sessionId) != 1) { 00957 envir().setResultMsg("Missing or bad \"Session:\" header"); 00958 break; 00959 } 00960 subsession.setSessionId(sessionId); 00961 delete[] fLastSessionId; fLastSessionId = strDup(sessionId); 00962 00963 // Also look for an optional "; timeout = " parameter following this: 00964 char const* afterSessionId = sessionParamsStr + strlen(sessionId); 00965 int timeoutVal; 00966 if (sscanf(afterSessionId, "; timeout = %d", &timeoutVal) == 1) { 00967 fSessionTimeoutParameter = timeoutVal; 00968 } 00969 00970 // Parse the "Transport:" header parameters: 00971 char* serverAddressStr; 00972 portNumBits serverPortNum; 00973 unsigned char rtpChannelId, rtcpChannelId; 00974 if (!parseTransportParams(transportParamsStr, serverAddressStr, serverPortNum, rtpChannelId, rtcpChannelId)) { 00975 envir().setResultMsg("Missing or bad \"Transport:\" header"); 00976 break; 00977 } 00978 delete[] subsession.connectionEndpointName(); 00979 subsession.connectionEndpointName() = serverAddressStr; 00980 subsession.serverPortNum = serverPortNum; 00981 subsession.rtpChannelId = rtpChannelId; 00982 subsession.rtcpChannelId = rtcpChannelId; 00983 00984 if (streamUsingTCP) { 00985 // Tell the subsession to receive RTP (and send/receive RTCP) over the RTSP stream: 00986 if (subsession.rtpSource() != NULL) { 00987 subsession.rtpSource()->setStreamSocket(fInputSocketNum, subsession.rtpChannelId); 00988 subsession.rtpSource()->setServerRequestAlternativeByteHandler(fInputSocketNum, handleAlternativeRequestByte, this); 00989 } 00990 if (subsession.rtcpInstance() != NULL) subsession.rtcpInstance()->setStreamSocket(fInputSocketNum, subsession.rtcpChannelId); 00991 } else { 00992 // Normal case. 00993 // Set the RTP and RTCP sockets' destination address and port from the information in the SETUP response (if present): 00994 netAddressBits destAddress = subsession.connectionEndpointAddress(); 00995 if (destAddress == 0) destAddress = fServerAddress; 00996 subsession.setDestinations(destAddress); 00997 00998 // Hack: To increase the likelihood of UDP packets from the server reaching us, if we're behind a NAT, send a few 'dummy' 00999 // UDP packets to the server now. (We do this only for RTP, not RTCP, because for RTCP our regular RTCP "RR" packets will 01000 // have the same effect.) 01001 if (subsession.rtpSource() != NULL) { 01002 Groupsock* gs = subsession.rtpSource()->RTPgs(); 01003 if (gs != NULL) { 01004 u_int32_t dummy = 0xFEEDFACE; 01005 unsigned const numDummyPackets = 2; 01006 for (unsigned i = 0; i < numDummyPackets; ++i) gs->output(envir(), 255, (unsigned char*)&dummy, sizeof dummy); 01007 } 01008 } 01009 } 01010 01011 success = True; 01012 } while (0); 01013 01014 delete[] sessionId; 01015 return success; 01016 }
| Boolean RTSPClient::handlePLAYResponse | ( | MediaSession & | session, | |
| MediaSubsession & | subsession, | |||
| char const * | scaleParamsStr, | |||
| char const * | rangeParamsStr, | |||
| char const * | rtpInfoParamsStr | |||
| ) | [private] |
Definition at line 1018 of file RTSPClient.cpp.
References MediaSubsession::_playEndTime(), MediaSubsession::_playStartTime(), Medium::envir(), False, MediaSubsession::infoIsNew, iter, MediaSubsessionIterator::next(), NULL, parseRangeParam(), parseRTPInfoParams(), parseScaleParam(), MediaSession::playEndTime(), MediaSession::playStartTime(), MediaSubsession::rtpInfo, MediaSubsession::scale(), MediaSession::scale(), MediaSubsession::seqNum, session, UsageEnvironment::setResultMsg(), subsession, MediaSubsession::timestamp, and True.
Referenced by handleResponseBytes().
01019 { 01020 Boolean scaleOK = False, rangeOK = False; 01021 do { 01022 if (&session != NULL) { 01023 // The command was on the whole session 01024 if (scaleParamsStr != NULL && !parseScaleParam(scaleParamsStr, session.scale())) break; 01025 scaleOK = True; 01026 if (rangeParamsStr != NULL && !parseRangeParam(rangeParamsStr, session.playStartTime(), session.playEndTime())) break; 01027 rangeOK = True; 01028 01029 u_int16_t seqNum; u_int32_t timestamp; 01030 if (rtpInfoParamsStr != NULL) { 01031 if (!parseRTPInfoParams(rtpInfoParamsStr, seqNum, timestamp)) break; 01032 // This is data for our first subsession. Fill it in, and do the same for our other subsessions: 01033 MediaSubsessionIterator iter(session); 01034 MediaSubsession* subsession; 01035 while ((subsession = iter.next()) != NULL) { 01036 subsession->rtpInfo.seqNum = seqNum; 01037 subsession->rtpInfo.timestamp = timestamp; 01038 subsession->rtpInfo.infoIsNew = True; 01039 01040 if (!parseRTPInfoParams(rtpInfoParamsStr, seqNum, timestamp)) break; 01041 } 01042 } 01043 } else { 01044 // The command was on a subsession 01045 if (scaleParamsStr != NULL && !parseScaleParam(scaleParamsStr, subsession.scale())) break; 01046 scaleOK = True; 01047 if (rangeParamsStr != NULL && !parseRangeParam(rangeParamsStr, subsession._playStartTime(), subsession._playEndTime())) break; 01048 rangeOK = True; 01049 01050 u_int16_t seqNum; u_int32_t timestamp; 01051 if (rtpInfoParamsStr != NULL) { 01052 if (!parseRTPInfoParams(rtpInfoParamsStr, seqNum, timestamp)) break; 01053 subsession.rtpInfo.seqNum = seqNum; 01054 subsession.rtpInfo.timestamp = timestamp; 01055 subsession.rtpInfo.infoIsNew = True; 01056 } 01057 } 01058 01059 return True; 01060 } while (0); 01061 01062 // An error occurred: 01063 if (!scaleOK) { 01064 envir().setResultMsg("Bad \"Scale:\" header"); 01065 } else if (!rangeOK) { 01066 envir().setResultMsg("Bad \"Range:\" header"); 01067 } else { 01068 envir().setResultMsg("Bad \"RTP-Info:\" header"); 01069 } 01070 return False; 01071 }
| Boolean RTSPClient::handleTEARDOWNResponse | ( | MediaSession & | session, | |
| MediaSubsession & | subsession | |||
| ) | [private] |
Definition at line 1073 of file RTSPClient.cpp.
References True.
Referenced by handleResponseBytes().
01073 { 01074 // Because we don't expect to always get a response to "TEARDOWN", we don't need to do anything if we do get one: 01075 return True; 01076 }
| Boolean RTSPClient::handleGET_PARAMETERResponse | ( | char const * | parameterName, | |
| char *& | resultValueString | |||
| ) | [private] |
Definition at line 1078 of file RTSPClient.cpp.
References _strncasecmp, Medium::envir(), False, NULL, UsageEnvironment::setResultMsg(), and True.
Referenced by handleResponseBytes().
01078 { 01079 do { 01080 // If "parameterName" is non-empty, it should be (possibly followed by ':' and whitespace) at the start of the result string: 01081 if (parameterName != NULL && parameterName[0] != '\0') { 01082 if (parameterName[1] == '\0') break; // sanity check; there should have been \r\n at the end of "parameterName" 01083 01084 unsigned parameterNameLen = strlen(parameterName); 01085 // ASSERT: parameterNameLen >= 2; 01086 parameterNameLen -= 2; // because of the trailing \r\n 01087 if (_strncasecmp(resultValueString, parameterName, parameterNameLen) != 0) { 01088 // The parameter name wasn't in the output, so just return an empty string: 01089 resultValueString[0] = '\0'; 01090 return True; 01091 } 01092 resultValueString += parameterNameLen; 01093 if (resultValueString[0] == ':') ++resultValueString; 01094 while (resultValueString[0] == ' ' || resultValueString[0] == '\t') ++resultValueString; 01095 } 01096 01097 // The rest of "resultValueStr" should be our desired result, but first trim off any \r and/or \n characters at the end: 01098 unsigned resultLen = strlen(resultValueString); 01099 while (resultLen > 0 && (resultValueString[resultLen-1] == '\r' || resultValueString[resultLen-1] == '\n')) --resultLen; 01100 resultValueString[resultLen] = '\0'; 01101 01102 return True; 01103 } while (0); 01104 01105 // An error occurred: 01106 envir().setResultMsg("Bad \"GET_PARAMETER\" response"); 01107 return False; 01108 }
| Boolean RTSPClient::handleAuthenticationFailure | ( | char const * | wwwAuthenticateParamsStr | ) | [private] |
Definition at line 1110 of file RTSPClient.cpp.
References False, fCurrentAuthenticator, NULL, Authenticator::password(), Authenticator::realm(), Authenticator::setRealmAndNonce(), strDupSize(), True, and Authenticator::username().
Referenced by handleResponseBytes().
01110 { 01111 if (paramsStr == NULL) return False; // There was no "WWW-Authenticate:" header; we can't proceed. 01112 01113 // Fill in "fCurrentAuthenticator" with the information from the "WWW-Authenticate:" header: 01114 Boolean alreadyHadRealm = fCurrentAuthenticator.realm() != NULL; 01115 char* realm = strDupSize(paramsStr); 01116 char* nonce = strDupSize(paramsStr); 01117 Boolean success = True; 01118 if (sscanf(paramsStr, "Digest realm=\"%[^\"]\", nonce=\"%[^\"]\"", realm, nonce) == 2) { 01119 fCurrentAuthenticator.setRealmAndNonce(realm, nonce); 01120 } else if (sscanf(paramsStr, "Basic realm=\"%[^\"]\"", realm) == 1) { 01121 fCurrentAuthenticator.setRealmAndNonce(realm, NULL); // Basic authentication 01122 } else { 01123 success = False; // bad "WWW-Authenticate:" header 01124 } 01125 delete[] realm; delete[] nonce; 01126 01127 if (alreadyHadRealm || fCurrentAuthenticator.username() == NULL || fCurrentAuthenticator.password() == NULL) { 01128 // We already had a 'realm', or don't have a username and/or password, 01129 // so the new "WWW-Authenticate:" header information won't help us. We remain unauthenticated. 01130 success = False; 01131 } 01132 01133 return success; 01134 }
| Boolean RTSPClient::resendCommand | ( | RequestRecord * | request | ) | [private] |
Definition at line 1136 of file RTSPClient.cpp.
References RTSPClient::RequestRecord::commandName(), RTSPClient::RequestRecord::cseq(), Medium::envir(), fCSeq, fVerbosityLevel, NULL, and sendRequest().
Referenced by handleResponseBytes().
01136 { 01137 if (fVerbosityLevel >= 1) envir() << "Resending...\n"; 01138 if (request != NULL && strcmp(request->commandName(), "GET") != 0) request->cseq() = ++fCSeq; 01139 return sendRequest(request) != 0; 01140 }
| char const * RTSPClient::sessionURL | ( | MediaSession const & | session | ) | const [private] |
Definition at line 1142 of file RTSPClient.cpp.
References MediaSession::controlPath(), fBaseURL, NULL, session, and url().
Referenced by constructSubsessionURL(), and sendRequest().
01142 { 01143 char const* url = session.controlPath(); 01144 if (url == NULL || strcmp(url, "*") == 0) url = fBaseURL; 01145 01146 return url; 01147 }
| void RTSPClient::handleAlternativeRequestByte | ( | void * | , | |
| u_int8_t | requestByte | |||
| ) | [static, private] |
Definition at line 1149 of file RTSPClient.cpp.
Referenced by handleSETUPResponse().
01149 { 01150 ((RTSPClient*)rtspClient)->handleAlternativeRequestByte1(requestByte); 01151 }
| void RTSPClient::handleAlternativeRequestByte1 | ( | u_int8_t | requestByte | ) | [private] |
Definition at line 1153 of file RTSPClient.cpp.
References fResponseBuffer, fResponseBytesAlreadySeen, and handleResponseBytes().
01153 { 01154 fResponseBuffer[fResponseBytesAlreadySeen] = requestByte; 01155 handleResponseBytes(1); 01156 }
| void RTSPClient::constructSubsessionURL | ( | MediaSubsession const & | subsession, | |
| char const *& | prefix, | |||
| char const *& | separator, | |||
| char const *& | suffix | |||
| ) | [private] |
Definition at line 1169 of file RTSPClient.cpp.
References MediaSubsession::controlPath(), isAbsoluteURL(), NULL, MediaSubsession::parentSession(), sessionURL(), and subsession.
Referenced by sendRequest().
01172 { 01173 // Figure out what the URL describing "subsession" will look like. 01174 // The URL is returned in three parts: prefix; separator; suffix 01175 //##### NOTE: This code doesn't really do the right thing if "sessionURL()" 01176 // doesn't end with a "/", and "subsession.controlPath()" is relative. 01177 // The right thing would have been to truncate "sessionURL()" back to the 01178 // rightmost "/", and then add "subsession.controlPath()". 01179 // In practice, though, each "DESCRIBE" response typically contains 01180 // a "Content-Base:" header that consists of "sessionURL()" followed by 01181 // a "/", in which case this code ends up giving the correct result. 01182 // However, we should really fix this code to do the right thing, and 01183 // also check for and use the "Content-Base:" header appropriately. ##### 01184 prefix = sessionURL(subsession.parentSession()); 01185 if (prefix == NULL) prefix = ""; 01186 01187 suffix = subsession.controlPath(); 01188 if (suffix == NULL) suffix = ""; 01189 01190 if (isAbsoluteURL(suffix)) { 01191 prefix = separator = ""; 01192 } else { 01193 unsigned prefixLen = strlen(prefix); 01194 separator = (prefixLen == 0 || prefix[prefixLen-1] == '/' || suffix[0] == '/') ? "" : "/"; 01195 } 01196 }
| Boolean RTSPClient::setupHTTPTunneling1 | ( | ) | [private] |
Definition at line 1198 of file RTSPClient.cpp.
References Medium::envir(), fTunnelOverHTTPPortNum, fVerbosityLevel, responseHandlerForHTTP_GET(), and sendRequest().
Referenced by sendRequest().
01198 { 01199 // Set up RTSP-over-HTTP tunneling, as described in 01200 // http://developer.apple.com/quicktime/icefloe/dispatch028.html and http://images.apple.com/br/quicktime/pdf/QTSS_Modules.pdf 01201 if (fVerbosityLevel >= 1) { 01202 envir() << "Requesting RTSP-over-HTTP tunneling (on port " << fTunnelOverHTTPPortNum << ")\n\n"; 01203 } 01204 01205 // Begin by sending a HTTP "GET", to set up the server->client link. Continue when we handle the response: 01206 return sendRequest(new RequestRecord(1, "GET", responseHandlerForHTTP_GET)) != 0; 01207 }
| void RTSPClient::responseHandlerForHTTP_GET | ( | RTSPClient * | rtspClient, | |
| int | responseCode, | |||
| char * | responseString | |||
| ) | [static, private] |
Definition at line 1209 of file RTSPClient.cpp.
References NULL, and responseHandlerForHTTP_GET1().
Referenced by setupHTTPTunneling1().
01209 { 01210 if (rtspClient != NULL) rtspClient->responseHandlerForHTTP_GET1(responseCode, responseString); 01211 }
| void RTSPClient::responseHandlerForHTTP_GET1 | ( | int | responseCode, | |
| char * | responseString | |||
| ) | [private] |
Definition at line 1213 of file RTSPClient.cpp.
References connectToServer(), RTSPClient::RequestQueue::dequeue(), RTSPClient::RequestQueue::enqueue(), Medium::envir(), False, fHTTPTunnelingConnectionIsPending, fOutputSocketNum, fRequestsAwaitingConnection, fRequestsAwaitingHTTPTunneling, fTunnelOverHTTPPortNum, handleRequestError(), NULL, resetTCPSockets(), sendRequest(), setupHTTPTunneling2(), setupStreamSocket(), and True.
Referenced by responseHandlerForHTTP_GET().
01213 { 01214 RequestRecord* request; 01215 do { 01216 if (responseCode != 0) break; // The HTTP "GET" failed. 01217 01218 // Having successfully set up (using the HTTP "GET" command) the server->client link, set up a second TCP connection 01219 // (to the same server & port as before) for the client->server link. All future output will be to this new socket. 01220 fOutputSocketNum = setupStreamSocket(envir(), 0); 01221 if (fOutputSocketNum < 0) break; 01222 01223 fHTTPTunnelingConnectionIsPending = True; 01224 int connectResult = connectToServer(fOutputSocketNum, fTunnelOverHTTPPortNum); 01225 if (connectResult < 0) break; // an error occurred 01226 else if (connectResult == 0) { 01227 // A connection is pending. Continue setting up RTSP-over-HTTP when the connection completes. 01228 // First, move the pending requests to the 'awaiting connection' queue: 01229 while ((request = fRequestsAwaitingHTTPTunneling.dequeue()) != NULL) { 01230 fRequestsAwaitingConnection.enqueue(request); 01231 } 01232 return; 01233 } 01234 01235 // The connection succeeded. Continue setting up RTSP-over-HTTP: 01236 if (!setupHTTPTunneling2()) break; 01237 01238 // RTSP-over-HTTP tunneling succeeded. Resume the pending request(s): 01239 while ((request = fRequestsAwaitingHTTPTunneling.dequeue()) != NULL) { 01240 sendRequest(request); 01241 } 01242 return; 01243 } while (0); 01244 01245 // An error occurred. Dequeue the pending request(s), and tell them about the error: 01246 fHTTPTunnelingConnectionIsPending = False; 01247 while ((request = fRequestsAwaitingHTTPTunneling.dequeue()) != NULL) { 01248 handleRequestError(request); 01249 delete request; 01250 } 01251 resetTCPSockets(); 01252 }
| Boolean RTSPClient::setupHTTPTunneling2 | ( | ) | [private] |
Definition at line 1254 of file RTSPClient.cpp.
References False, fHTTPTunnelingConnectionIsPending, NULL, and sendRequest().
Referenced by connectionHandler1(), and responseHandlerForHTTP_GET1().
01254 { 01255 fHTTPTunnelingConnectionIsPending = False; 01256 01257 // Send a HTTP "POST", to set up the client->server link. (Note that we won't see a reply to the "POST".) 01258 return sendRequest(new RequestRecord(1, "POST", NULL)) != 0; 01259 }
| void RTSPClient::connectionHandler | ( | void * | , | |
| int | ||||
| ) | [static, private] |
Definition at line 1261 of file RTSPClient.cpp.
References connectionHandler1().
Referenced by connectToServer().
01261 { 01262 RTSPClient* client = (RTSPClient*)instance; 01263 client->connectionHandler1(); 01264 }
| void RTSPClient::connectionHandler1 | ( | ) | [private] |
Definition at line 1266 of file RTSPClient.cpp.
References RTSPClient::RequestQueue::dequeue(), TaskScheduler::disableBackgroundHandling(), RTSPClient::RequestQueue::enqueue(), Medium::envir(), fHTTPTunnelingConnectionIsPending, fInputSocketNum, fOutputSocketNum, fRequestsAwaitingConnection, fVerbosityLevel, UsageEnvironment::getResultMsg(), handleRequestError(), incomingDataHandler(), NULL, resetTCPSockets(), sendRequest(), TaskScheduler::setBackgroundHandling(), UsageEnvironment::setResultErrMsg(), setupHTTPTunneling2(), SOCKET_READABLE, SOCKLEN_T, and UsageEnvironment::taskScheduler().
Referenced by connectionHandler().
01266 { 01267 // Restore normal handling on our sockets: 01268 envir().taskScheduler().disableBackgroundHandling(fOutputSocketNum); 01269 envir().taskScheduler().setBackgroundHandling(fInputSocketNum, SOCKET_READABLE, 01270 (TaskScheduler::BackgroundHandlerProc*)&incomingDataHandler, this); 01271 01272 // Move all requests awaiting connection into a new, temporary queue, to clear "fRequestsAwaitingConnection" 01273 // (so that "sendRequest()" doesn't get confused by "fRequestsAwaitingConnection" being nonempty, and enqueue them all over again). 01274 RequestQueue tmpRequestQueue; 01275 RequestRecord* request; 01276 while ((request = fRequestsAwaitingConnection.dequeue()) != NULL) { 01277 tmpRequestQueue.enqueue(request); 01278 } 01279 01280 // Find out whether the connection succeeded or failed: 01281 do { 01282 int err = 0; 01283 SOCKLEN_T len = sizeof err; 01284 if (getsockopt(fInputSocketNum, SOL_SOCKET, SO_ERROR, (char*)&err, &len) < 0 || err != 0) { 01285 envir().setResultErrMsg("Connection to server failed: ", err); 01286 if (fVerbosityLevel >= 1) envir() << "..." << envir().getResultMsg() << "\n"; 01287 break; 01288 } 01289 01290 // The connection succeeded. If the connection came about from an attempt to set up RTSP-over-HTTP, finish this now: 01291 if (fVerbosityLevel >= 1) envir() << "...remote connection opened\n"; 01292 if (fHTTPTunnelingConnectionIsPending && !setupHTTPTunneling2()) break; 01293 01294 // Resume sending all pending requests: 01295 while ((request = tmpRequestQueue.dequeue()) != NULL) { 01296 sendRequest(request); 01297 } 01298 return; 01299 } while (0); 01300 01301 // An error occurred. Tell all pending requests about the error: 01302 while ((request = tmpRequestQueue.dequeue()) != NULL) { 01303 handleRequestError(request); 01304 delete request; 01305 } 01306 resetTCPSockets(); 01307 }
| void RTSPClient::incomingDataHandler | ( | void * | , | |
| int | ||||
| ) | [static, private] |
Definition at line 1309 of file RTSPClient.cpp.
References incomingDataHandler1().
Referenced by connectionHandler1(), and openConnection().
01309 { 01310 RTSPClient* client = (RTSPClient*)instance; 01311 client->incomingDataHandler1(); 01312 }
| void RTSPClient::incomingDataHandler1 | ( | ) | [private] |
Definition at line 1314 of file RTSPClient.cpp.
References Medium::envir(), fInputSocketNum, fResponseBuffer, fResponseBufferBytesLeft, fResponseBytesAlreadySeen, handleResponseBytes(), and readSocket().
Referenced by incomingDataHandler().
01314 { 01315 struct sockaddr_in dummy; // 'from' address - not used 01316 01317 int bytesRead = readSocket(envir(), fInputSocketNum, (unsigned char*)&fResponseBuffer[fResponseBytesAlreadySeen], fResponseBufferBytesLeft, dummy); 01318 handleResponseBytes(bytesRead); 01319 }
| void RTSPClient::handleResponseBytes | ( | int | newBytesRead | ) | [private] |
Definition at line 1340 of file RTSPClient.cpp.
References _strncasecmp, RTSPClient::RequestRecord::booleanFlags(), checkForHeader(), RTSPClient::RequestRecord::commandName(), RTSPClient::RequestRecord::contentStr(), RTSPClient::RequestRecord::cseq(), RTSPClient::RequestQueue::dequeue(), Medium::envir(), False, fRequestsAwaitingResponse, fResponseBuffer, fResponseBufferBytesLeft, fResponseBytesAlreadySeen, fVerbosityLevel, getLine(), handleAuthenticationFailure(), handleGET_PARAMETERResponse(), handleIncomingRequest(), handlePLAYResponse(), RTSPClient::RequestRecord::handler(), handleRequestError(), handleSETUPResponse(), handleTEARDOWNResponse(), NULL, parseResponseCode(), RTSPClient::RequestQueue::putAtHead(), resendCommand(), resetResponseBuffer(), resetTCPSockets(), responseBufferSize, RTSPClient::RequestRecord::session(), setBaseURL(), UsageEnvironment::setResultMsg(), strDup(), RTSPClient::RequestRecord::subsession(), and True.
Referenced by handleAlternativeRequestByte1(), and incomingDataHandler1().
01340 { 01341 do { 01342 if (newBytesRead > 0 && (unsigned)newBytesRead < fResponseBufferBytesLeft) break; // data was read OK; process it below 01343 01344 if ((unsigned)newBytesRead >= fResponseBufferBytesLeft) { 01345 // We filled up our response buffer. Treat this as an error (for the first response handler): 01346 envir().setResultMsg("RTSP response was truncated. Increase \"RTSPClient::responseBufferSize\""); 01347 } 01348 01349 // An error occurred while reading our TCP socket. Call all pending response handlers, indicating this error: 01350 RequestRecord* request; 01351 while ((request = fRequestsAwaitingResponse.dequeue()) != NULL) { 01352 handleRequestError(request); 01353 delete request; 01354 01355 if (newBytesRead > 0) break; // The "RTSP response was truncated" error is applied to the first response handler only 01356 } 01357 01358 if (newBytesRead <= 0) resetTCPSockets(); 01359 resetResponseBuffer(); 01360 return; 01361 } while (0); 01362 01363 fResponseBufferBytesLeft -= newBytesRead; 01364 fResponseBytesAlreadySeen += newBytesRead; 01365 fResponseBuffer[fResponseBytesAlreadySeen] = '\0'; 01366 if (fVerbosityLevel >= 1 && newBytesRead > 1) envir() << "Received " << newBytesRead << " new bytes of response data.\n"; 01367 01368 // Data was read OK. Look through the data that we've read so far, to see if it contains <CR><LF><CR><LF>. 01369 // (If not, wait for more data to arrive.) 01370 Boolean endOfHeaders = False; 01371 if (fResponseBytesAlreadySeen > 3) { 01372 char const* const ptrEnd = &fResponseBuffer[fResponseBytesAlreadySeen-3]; 01373 char const* ptr = fResponseBuffer; 01374 while (ptr < ptrEnd) { 01375 if (*ptr++ == '\r' && *ptr++ == '\n' && *ptr++ == '\r' && *ptr++ == '\n') { 01376 // This is it 01377 endOfHeaders = True; 01378 break; 01379 } 01380 } 01381 } 01382 01383 if (!endOfHeaders) return; // subsequent reads will be needed to get the complete response 01384 01385 // Now that we have the complete response headers (ending with <CR><LF><CR><LF>), parse them to get the response code, CSeq, 01386 // and various other header parameters. To do this, we first make a copy of the received header data, because we'll be modifying 01387 // it by adding '\0' bytes. 01388 char* headerDataCopy; 01389 unsigned responseCode = 200; 01390 char const* responseStr = NULL; 01391 RequestRecord* foundRequest = NULL; 01392 char const* sessionParamsStr = NULL; 01393 char const* transportParamsStr = NULL; 01394 char const* scaleParamsStr = NULL; 01395 char const* rangeParamsStr = NULL; 01396 char const* rtpInfoParamsStr = NULL; 01397 char const* wwwAuthenticateParamsStr = NULL; 01398 char const* publicParamsStr = NULL; 01399 char* bodyStart = NULL; 01400 unsigned numBodyBytes = 0; 01401 Boolean responseSuccess = False; // by default 01402 do { 01403 headerDataCopy = new char[responseBufferSize]; 01404 strncpy(headerDataCopy, fResponseBuffer, fResponseBytesAlreadySeen); 01405 headerDataCopy[fResponseBytesAlreadySeen] = '\0'; 01406 01407 char* lineStart = headerDataCopy; 01408 char* nextLineStart = getLine(lineStart); 01409 if (!parseResponseCode(lineStart, responseCode, responseStr)) { 01410 // This does not appear to be a RTSP response; perhaps it's a RTSP request instead? 01411 handleIncomingRequest(); 01412 break; // we're done with this data 01413 } 01414 01415 // Scan through the headers, handling the ones that we're interested in: 01416 Boolean reachedEndOfHeaders; 01417 unsigned cseq = 0; 01418 unsigned contentLength = 0; 01419 01420 while (1) { 01421 reachedEndOfHeaders = True; // by default; may get changed below 01422 lineStart = nextLineStart; 01423 if (lineStart == NULL) break; 01424 01425 nextLineStart = getLine(lineStart); 01426 if (lineStart[0] == '\0') break; // this is a blank line 01427 reachedEndOfHeaders = False; 01428 01429 char const* headerParamsStr; 01430 if (checkForHeader(lineStart, "CSeq:", 5, headerParamsStr)) { 01431 if (sscanf(headerParamsStr, "%u", &cseq) != 1 || cseq <= 0) { 01432 envir().setResultMsg("Bad \"CSeq:\" header: \"", lineStart, "\""); 01433 break; 01434 } 01435 // Find the handler function for "cseq": 01436 RequestRecord* request; 01437 while ((request = fRequestsAwaitingResponse.dequeue()) != NULL) { 01438 if (request->cseq() < cseq) { // assumes that the CSeq counter will never wrap around 01439 // We never received (and will never receive) a response for this handler, so delete it: 01440 delete request; 01441 } else if (request->cseq() == cseq) { 01442 // This is the handler that we want. Remove its record, but remember it, so that we can later call its handler: 01443 foundRequest = request; 01444 break; 01445 } else { // request->cseq() > cseq 01446 // No handler was registered for this response, so ignore it. 01447 break; 01448 } 01449 } 01450 } else if (checkForHeader(lineStart, "Content-Length:", 15, headerParamsStr)) { 01451 if (sscanf(headerParamsStr, "%u", &contentLength) != 1) { 01452 envir().setResultMsg("Bad \"Content-Length:\" header: \"", lineStart, "\""); 01453 break; 01454 } 01455 } else if (checkForHeader(lineStart, "Content-Base:", 13, headerParamsStr)) { 01456 setBaseURL(headerParamsStr); 01457 } else if (checkForHeader(lineStart, "Session:", 8, sessionParamsStr)) { 01458 } else if (checkForHeader(lineStart, "Transport:", 10, transportParamsStr)) { 01459 } else if (checkForHeader(lineStart, "Scale:", 6, scaleParamsStr)) { 01460 } else if (checkForHeader(lineStart, "Range:", 6, rangeParamsStr)) { 01461 } else if (checkForHeader(lineStart, "RTP-Info:", 9, rtpInfoParamsStr)) { 01462 } else if (checkForHeader(lineStart, "WWW-Authenticate:", 17, headerParamsStr)) { 01463 // If we've already seen a "WWW-Authenticate:" header, then we replace it with this new one only if 01464 // the new one specifies "Digest" authentication: 01465 if (wwwAuthenticateParamsStr == NULL || _strncasecmp(headerParamsStr, "Digest", 6) == 0) { 01466 wwwAuthenticateParamsStr = headerParamsStr; 01467 } 01468 } else if (checkForHeader(lineStart, "Public:", 7, publicParamsStr)) { 01469 } else if (checkForHeader(lineStart, "Allow:", 6, publicParamsStr)) { 01470 // Note: we accept "Allow:" instead of "Public:", so that "OPTIONS" requests made to HTTP servers will work. 01471 } else if (checkForHeader(lineStart, "Location:", 9, headerParamsStr)) { 01472 setBaseURL(headerParamsStr); 01473 } 01474 } 01475 if (!reachedEndOfHeaders) break; // an error occurred 01476 01477 if (foundRequest == NULL) { 01478 // Hack: The response didn't have a "CSeq:" header; assume it's for our most recent request: 01479 foundRequest = fRequestsAwaitingResponse.dequeue(); 01480 } 01481 01482 // If we saw a "Content-Length:" header, then make sure that we have the amount of data that it specified: 01483 unsigned bodyOffset = nextLineStart - headerDataCopy; 01484 bodyStart = &fResponseBuffer[bodyOffset]; 01485 numBodyBytes = fResponseBytesAlreadySeen - bodyOffset; 01486 if (contentLength > numBodyBytes) { 01487 // We need to read more data. First, make sure we have enough space for it: 01488 unsigned numExtraBytesNeeded = contentLength - numBodyBytes; 01489 unsigned remainingBufferSize = responseBufferSize - fResponseBytesAlreadySeen; 01490 if (numExtraBytesNeeded > remainingBufferSize) { 01491 char tmpBuf[200]; 01492 sprintf(tmpBuf, "Response buffer size (%d) is too small for \"Content-Length:\" %d (need a buffer size of >= %d bytes\n", 01493 responseBufferSize, contentLength, fResponseBytesAlreadySeen + numExtraBytesNeeded); 01494 envir().setResultMsg(tmpBuf); 01495 break; 01496 } 01497 01498 if (fVerbosityLevel >= 1) { 01499 envir() << "Have received " << fResponseBytesAlreadySeen << " total bytes of a " 01500 << (foundRequest != NULL ? foundRequest->commandName() : "(unknown)") 01501 << " RTSP response; awaiting " << numExtraBytesNeeded << " bytes more.\n"; 01502 } 01503 delete[] headerDataCopy; 01504 if (foundRequest != NULL) fRequestsAwaitingResponse.putAtHead(foundRequest); // put back our request record; we need it again 01505 return; // We need to read more data 01506 } 01507 01508 // We now have a complete response (including all bytes specified by the "Content-Length:" header, if any). 01509 if (fVerbosityLevel >= 1) { 01510 envir() << "Received a complete " 01511 << (foundRequest != NULL ? foundRequest->commandName() : "(unknown)") 01512 << " response:\n" << fResponseBuffer << "\n"; 01513 } 01514 01515 if (foundRequest != NULL) { 01516 Boolean needToResendCommand = False; // by default... 01517 if (responseCode == 200) { 01518 // Do special-case response handling for some commands: 01519 if (strcmp(foundRequest->commandName(), "SETUP") == 0) { 01520 if (!handleSETUPResponse(*foundRequest->subsession(), sessionParamsStr, transportParamsStr, foundRequest->booleanFlags()&0x1)) break; 01521 } else if (strcmp(foundRequest->commandName(), "PLAY") == 0) { 01522 if (!handlePLAYResponse(*foundRequest->session(), *foundRequest->subsession(), scaleParamsStr, rangeParamsStr, rtpInfoParamsStr)) break; 01523 } else if (strcmp(foundRequest->commandName(), "TEARDOWN") == 0) { 01524 if (!handleTEARDOWNResponse(*foundRequest->session(), *foundRequest->subsession())) break; 01525 } else if (strcmp(foundRequest->commandName(), "GET_PARAMETER") == 0) { 01526 if (!handleGET_PARAMETERResponse(foundRequest->contentStr(), bodyStart)) break; 01527 } 01528 } else if (responseCode == 401 && handleAuthenticationFailure(wwwAuthenticateParamsStr)) { 01529 // We need to resend the command, with an "Authorization:" header: 01530 needToResendCommand = True; 01531 01532 if (strcmp(foundRequest->commandName(), "GET") == 0) { 01533 // Note: If a HTTP "GET" command (for RTSP-over-HTTP tunneling) returns "401 Unauthorized", then we resend it 01534 // (with an "Authorization:" header), just as we would for a RTSP command. However, we do so using a new TCP connection, 01535 // because some servers close the original connection after returning the "401 Unauthorized". 01536 resetTCPSockets(); // forces the opening of a new connection for the resent command 01537 } 01538 } else if (responseCode == 301 || responseCode == 302) { // redirection 01539 resetTCPSockets(); // because we need to connect somewhere else next 01540 needToResendCommand = True; 01541 } 01542 01543 if (needToResendCommand) { 01544 resetResponseBuffer(); 01545 if (!resendCommand(foundRequest)) break; 01546 delete[] headerDataCopy; 01547 return; // without calling our response handler; the response to the resent command will do that 01548 } 01549 } 01550 01551 responseSuccess = True; 01552 } while (0); 01553 01554 // If we have a handler function for this response, call it: 01555 resetResponseBuffer(); // in preparation for our next response. Do this now, in case the handler function goes to the event loop. 01556 if (foundRequest != NULL && foundRequest->handler() != NULL) { 01557 int resultCode; 01558 char* resultString; 01559 if (responseSuccess) { 01560 if (responseCode == 200) { 01561 resultCode = 0; 01562 resultString = numBodyBytes != 0 ? strDup(bodyStart) : strDup(publicParamsStr); 01563 // Note: The "strDup(bodyStart)" call assumes that the body is encoded without interior '\0' bytes 01564 } else { 01565 resultCode = responseCode; 01566 resultString = strDup(responseStr); 01567 envir().setResultMsg(responseStr); 01568 } 01569 (*foundRequest->handler())(this, resultCode, resultString); 01570 } else { 01571 // An error occurred parsing the response, so call the handler, indicating an error: 01572 handleRequestError(foundRequest); 01573 } 01574 } 01575 delete foundRequest; 01576 delete[] headerDataCopy; 01577 }
| static RTSPClient* RTSPClient::createNew | ( | UsageEnvironment & | env, | |
| int | verbosityLevel = 0, |
|||
| char const * | applicationName = NULL, |
|||
| portNumBits | tunnelOverHTTPPortNum = 0 | |||
| ) | [static] |
| char* RTSPClient::describeURL | ( | char const * | url, | |
| Authenticator * | authenticator = NULL, |
|||
| Boolean | allowKasennaProtocol = False, |
|||
| int | timeout = -1 | |||
| ) |
| char* RTSPClient::describeWithPassword | ( | char const * | url, | |
| char const * | username, | |||
| char const * | password, | |||
| Boolean | allowKasennaProtocol = False, |
|||
| int | timeout = -1 | |||
| ) |
| char* RTSPClient::sendOptionsCmd | ( | char const * | url, | |
| char * | username = NULL, |
|||
| char * | password = NULL, |
|||
| Authenticator * | authenticator = NULL, |
|||
| int | timeout = -1 | |||
| ) |
| Boolean RTSPClient::announceSDPDescription | ( | char const * | url, | |
| char const * | sdpDescription, | |||
| Authenticator * | authenticator = NULL, |
|||
| int | timeout = -1 | |||
| ) |
| Boolean RTSPClient::announceWithPassword | ( | char const * | url, | |
| char const * | sdpDescription, | |||
| char const * | username, | |||
| char const * | password, | |||
| int | timeout = -1 | |||
| ) |
| Boolean RTSPClient::setupMediaSubsession | ( | MediaSubsession & | subsession, | |
| Boolean | streamOutgoing = False, |
|||
| Boolean | streamUsingTCP = False, |
|||
| Boolean | forceMulticastOnUnspecified = False | |||
| ) |
| Boolean RTSPClient::playMediaSession | ( | MediaSession & | session, | |
| double | start = 0.0f, |
|||
| double | end = -1.0f, |
|||
| float | scale = 1.0f | |||
| ) |
| Boolean RTSPClient::playMediaSubsession | ( | MediaSubsession & | subsession, | |
| double | start = 0.0f, |
|||
| double | end = -1.0f, |
|||
| float | scale = 1.0f, |
|||
| Boolean | hackForDSS = False | |||
| ) |
| Boolean RTSPClient::pauseMediaSession | ( | MediaSession & | session | ) |
| Boolean RTSPClient::pauseMediaSubsession | ( | MediaSubsession & | subsession | ) |
| Boolean RTSPClient::recordMediaSubsession | ( | MediaSubsession & | subsession | ) |
| Boolean RTSPClient::setMediaSessionParameter | ( | MediaSession & | session, | |
| char const * | parameterName, | |||
| char const * | parameterValue | |||
| ) |
| Boolean RTSPClient::getMediaSessionParameter | ( | MediaSession & | session, | |
| char const * | parameterName, | |||
| char *& | parameterValue | |||
| ) |
| Boolean RTSPClient::teardownMediaSession | ( | MediaSession & | session | ) |
| Boolean RTSPClient::teardownMediaSubsession | ( | MediaSubsession & | subsession | ) |
| static Boolean RTSPClient::parseRTSPURLUsernamePassword | ( | char const * | url, | |
| char *& | username, | |||
| char *& | password | |||
| ) | [static] |
| static void RTSPClient::responseHandlerForSyncInterface | ( | RTSPClient * | rtspClient, | |
| int | responseCode, | |||
| char * | responseString | |||
| ) | [static, private] |
| void RTSPClient::responseHandlerForSyncInterface1 | ( | int | responseCode, | |
| char * | responseString | |||
| ) | [private] |
| static void RTSPClient::timeoutHandlerForSyncInterface | ( | void * | rtspClient | ) | [static, private] |
| void RTSPClient::timeoutHandlerForSyncInterface1 | ( | ) | [private] |
| Boolean Medium::lookupByName | ( | UsageEnvironment & | env, | |
| char const * | mediumName, | |||
| Medium *& | resultMedium | |||
| ) | [static, inherited] |
Definition at line 41 of file Media.cpp.
References env, False, MediaLookupTable::lookup(), NULL, MediaLookupTable::ourMedia(), UsageEnvironment::setResultMsg(), and True.
Referenced by ServerMediaSession::lookupByName(), RTSPServer::lookupByName(), lookupByName(), RTCPInstance::lookupByName(), MediaSource::lookupByName(), MediaSink::lookupByName(), MediaSession::lookupByName(), and DarwinInjector::lookupByName().
00042 { 00043 resultMedium = MediaLookupTable::ourMedia(env)->lookup(mediumName); 00044 if (resultMedium == NULL) { 00045 env.setResultMsg("Medium ", mediumName, " does not exist"); 00046 return False; 00047 } 00048 00049 return True; 00050 }
| void Medium::close | ( | UsageEnvironment & | env, | |
| char const * | mediumName | |||
| ) | [static, inherited] |
Definition at line 52 of file Media.cpp.
References env, MediaLookupTable::ourMedia(), and MediaLookupTable::remove().
Referenced by afterPlaying(), Medium::close(), closeMediaSinks(), OnDemandServerMediaSubsession::closeStreamSource(), continueAfterTEARDOWN(), WAVAudioFileSource::createNew(), QuickTimeFileSink::createNew(), QCELPAudioRTPSource::createNew(), MP3HTTPSource::createNew(), MP3FileSource::createNew(), AVIFileSink::createNew(), AMRAudioRTPSource::createNew(), WAVAudioFileServerMediaSubsession::createNewStreamSource(), MPEG1or2DemuxedServerMediaSubsession::createNewStreamSource(), MediaSubsession::deInitiate(), RTSPServerSupportingHTTPStreaming::RTSPClientSessionSupportingHTTPStreaming::handleHTTPCmd_StreamingGET(), MediaSubsession::initiate(), MPEG1or2ProgramStreamFileDuration(), MPEG1or2Demux::noteElementaryStreamDeletion(), ByteStreamMultiFileSource::onSourceClosure1(), StreamState::reclaim(), RTSPServer::removeServerMediaSession(), OnDemandServerMediaSubsession::sdpLines(), shutdownStream(), T140TextRTPSink::stopPlaying(), H264VideoRTPSink::stopPlaying(), subsessionAfterPlaying(), ClientTrickPlayState::updateStateOnScaleChange(), AMRDeinterleaver::~AMRDeinterleaver(), ByteStreamMultiFileSource::~ByteStreamMultiFileSource(), DarwinInjector::~DarwinInjector(), FramedFilter::~FramedFilter(), InputESSourceRecord::~InputESSourceRecord(), MatroskaFileParser::~MatroskaFileParser(), MatroskaFileServerDemux::~MatroskaFileServerDemux(), MPEG1or2Demux::~MPEG1or2Demux(), MPEG1or2FileServerDemux::~MPEG1or2FileServerDemux(), MPEG2TransportFileServerMediaSubsession::~MPEG2TransportFileServerMediaSubsession(), MPEG2TransportStreamFromPESSource::~MPEG2TransportStreamFromPESSource(), RTSPServerSupportingHTTPStreaming::RTSPClientSessionSupportingHTTPStreaming::~RTSPClientSessionSupportingHTTPStreaming(), ServerMediaSession::~ServerMediaSession(), ServerMediaSubsession::~ServerMediaSubsession(), StreamClientState::~StreamClientState(), and StreamReplicator::~StreamReplicator().
00052 { 00053 MediaLookupTable::ourMedia(env)->remove(name); 00054 }
| void Medium::close | ( | Medium * | medium | ) | [static, inherited] |
Definition at line 56 of file Media.cpp.
References Medium::close(), Medium::envir(), Medium::name(), and NULL.
00056 { 00057 if (medium == NULL) return; 00058 00059 close(medium->envir(), medium->name()); 00060 }
| UsageEnvironment& Medium::envir | ( | ) | const [inline, inherited] |
Definition at line 59 of file Media.hh.
References Medium::fEnviron.
Referenced by QuickTimeFileSink::addArbitraryString(), FileSink::addData(), RTCPInstance::addStreamSocket(), MPEG2IFrameIndexFromTransportStream::addToTail(), StreamParser::afterGettingBytes1(), DummySink::afterGettingFrame(), T140IdleFilter::afterGettingFrame(), MultiFramedRTPSink::afterGettingFrame1(), InputESSourceRecord::afterGettingFrame1(), MPEG2TransportStreamFramer::afterGettingFrame1(), MPEG2IFrameIndexFromTransportStream::afterGettingFrame1(), H264VideoStreamDiscreteFramer::afterGettingFrame1(), BasicUDPSink::afterGettingFrame1(), MPEG4VideoFileServerMediaSubsession::afterPlayingDummy1(), H264VideoFileServerMediaSubsession::afterPlayingDummy1(), MPEG4VideoStreamParser::analyzeVOLHeader(), announceStream(), RTSPServer::RTSPClientSession::changeClientInputSocket(), MPEG4VideoFileServerMediaSubsession::checkForAuxSDPLine1(), H264VideoFileServerMediaSubsession::checkForAuxSDPLine1(), Medium::close(), MPEG2IFrameIndexFromTransportStream::compactParseBuffer(), connectionHandler1(), connectToServer(), T140TextRTPSink::continuePlaying(), QuickTimeFileSink::continuePlaying(), H264VideoRTPSink::continuePlaying(), AVIFileSink::continuePlaying(), VP8VideoMatroskaFileServerMediaSubsession::createNewRTPSink(), VorbisAudioMatroskaFileServerMediaSubsession::createNewRTPSink(), T140TextMatroskaFileServerMediaSubsession::createNewRTPSink(), MPEG4VideoFileServerMediaSubsession::createNewRTPSink(), MPEG2TransportUDPServerMediaSubsession::createNewRTPSink(), MPEG2TransportFileServerMediaSubsession::createNewRTPSink(), MPEG1or2VideoFileServerMediaSubsession::createNewRTPSink(), MPEG1or2DemuxedServerMediaSubsession::createNewRTPSink(), MP3AudioFileServerMediaSubsession::createNewRTPSink(), H264VideoFileServerMediaSubsession::createNewRTPSink(), H263plusVideoFileServerMediaSubsession::createNewRTPSink(), DVVideoFileServerMediaSubsession::createNewRTPSink(), AMRAudioFileServerMediaSubsession::createNewRTPSink(), ADTSAudioFileServerMediaSubsession::createNewRTPSink(), AC3AudioMatroskaFileServerMediaSubsession::createNewRTPSink(), AC3AudioFileServerMediaSubsession::createNewRTPSink(), AACAudioMatroskaFileServerMediaSubsession::createNewRTPSink(), MPEG4VideoFileServerMediaSubsession::createNewStreamSource(), MPEG2TransportUDPServerMediaSubsession::createNewStreamSource(), MPEG2TransportFileServerMediaSubsession::createNewStreamSource(), MPEG1or2VideoFileServerMediaSubsession::createNewStreamSource(), MPEG1or2DemuxedServerMediaSubsession::createNewStreamSource(), MP3AudioFileServerMediaSubsession::createNewStreamSource(), H264VideoMatroskaFileServerMediaSubsession::createNewStreamSource(), H264VideoFileServerMediaSubsession::createNewStreamSource(), H263plusVideoFileServerMediaSubsession::createNewStreamSource(), DVVideoFileServerMediaSubsession::createNewStreamSource(), AMRAudioFileServerMediaSubsession::createNewStreamSource(), ADTSAudioFileServerMediaSubsession::createNewStreamSource(), AC3AudioFileServerMediaSubsession::createNewStreamSource(), AMRDeinterleavingBuffer::deliverIncomingFrame(), MPEG2IFrameIndexFromTransportStream::deliverIndexRecord(), SegmentQueue::dequeue(), DeviceSource::DeviceSource(), WAVAudioFileSource::doGetNextFrame(), T140IdleFilter::doGetNextFrame(), MPEG2IFrameIndexFromTransportStream::doGetNextFrame(), MP3FileSource::doGetNextFrame(), H264FUAFragmenter::doGetNextFrame(), ByteStreamMultiFileSource::doGetNextFrame(), ByteStreamFileSource::doGetNextFrame(), BasicUDPSource::doGetNextFrame(), AMRAudioFileSource::doGetNextFrame(), ADTSAudioFileSource::doGetNextFrame(), MultiFramedRTPSource::doGetNextFrame1(), MP3FileSource::doGetNextFrame1(), ADUFromMP3Source::doGetNextFrame1(), SIPClient::doInviteStateMachine(), ByteStreamFileSource::doReadFromFile(), MPEG1or2VideoRTPSink::doSpecialFrameHandling(), MP3ADURTPSink::doSpecialFrameHandling(), H263plusVideoRTPSink::doSpecialFrameHandling(), T140IdleFilter::doStopGettingFrames(), ByteStreamFileSource::doStopGettingFrames(), BasicUDPSource::doStopGettingFrames(), SegmentQueue::enqueueNewSegment(), StreamParser::ensureValidBytes1(), MediaSubsession::env(), SubsessionIOState::envir(), RTSPServer::RTSPClientSession::envir(), RTPInterface::envir(), AVISubsessionIOState::envir(), ServerMediaSession::generateSDPDescription(), RTPSource::getAttributes(), MP3FileSource::getAttributes(), MP3ADUTranscoder::getAttributes(), MediaSource::getAttributes(), MPEG4VideoFileServerMediaSubsession::getAuxSDPLine(), H264VideoFileServerMediaSubsession::getAuxSDPLine(), getMPEG1or2TimeCode(), FramedSource::getNextFrame(), getOptions(), DVVideoStreamFramer::getProfile(), SIPClient::getResponse(), SIPClient::getResponseCode(), getSDPDescription(), OnDemandServerMediaSubsession::getStreamParameters(), handleGET_PARAMETERResponse(), RTSPServerSupportingHTTPStreaming::RTSPClientSessionSupportingHTTPStreaming::handleHTTPCmd_StreamingGET(), handleIncomingRequest(), handlePLAYResponse(), handleRequestError(), handleResponseBytes(), handleSETUPResponse(), RTSPServer::incomingConnectionHandler(), incomingDataHandler1(), RTCPInstance::incomingReportHandler1(), MP3FileSource::initializeStream(), MediaSession::initializeWithSDP(), MediaSession::initiateByMediaType(), SIPClient::invite1(), DynamicRTSPServer::lookupServerMediaSession(), MatroskaDemux::MatroskaDemux(), MatroskaFile::MatroskaFile(), MPEG4GenericRTPSource::MPEG4GenericRTPSource(), MatroskaDemux::newDemuxedTrack(), MPEG1or2FileServerDemux::newElementaryStream(), MPEG1or2Demux::newElementaryStream(), MPEG4GenericBufferedPacket::nextEnclosedFrameSize(), AMRBufferedPacket::nextEnclosedFrameSize(), openConnection(), MPEG2TransportStreamIndexFile::openFid(), MPEG2IFrameIndexFromTransportStream::parseFrame(), AC3AudioStreamParser::parseFrame(), MPEGProgramStreamParser::parsePackHeader(), MPEGProgramStreamParser::parsePESPacket(), SIPClient::parseResponseCode(), MediaSession::parseSDPLine(), MPEG1or2VideoStreamParser::parseSlice(), MatroskaFileParser::parseStartOfFile(), MPEGProgramStreamParser::parseSystemHeader(), MPEG4VideoStreamParser::parseVideoObjectLayer(), MPEG4VideoStreamParser::parseVideoObjectPlane(), MPEG4VideoStreamParser::parseVisualObject(), TCPStreamSink::processBuffer(), SIPClient::processURL(), AC3AudioStreamParser::readAndSaveAFrame(), MPEG1or2Demux::registerReadInterest(), RTCPInstance::reschedule(), resendCommand(), resetTCPSockets(), responseHandlerForHTTP_GET1(), RTSPServer::rtspURLPrefix(), RTCPInstance::schedule(), OnDemandServerMediaSubsession::sdpLines(), SIPClient::sendACK(), SIPClient::sendBYE(), SIPClient::sendINVITE(), MultiFramedRTPSink::sendPacketIfNecessary(), SIPClient::sendRequest(), sendRequest(), DarwinInjector::setDestination(), setupHTTPTunneling1(), setupNextSubsession(), RTSPServer::setUpTunnelingOverHTTP(), QuickTimeFileSink::setWord(), AVIFileSink::setWord(), QuickTimeFileSink::setWord64(), shutdownStream(), SIPClient::SIPClient(), TCPStreamSink::socketWritableHandler1(), AMRAudioRTPSink::sourceIsCompatibleWithUs(), QuickTimeFileSink::startPlaying(), StreamState::startPlaying(), MediaSink::startPlaying(), AVIFileSink::startPlaying(), startPlayingSession(), PassiveServerMediaSubsession::startStream(), MediaSink::stopPlaying(), tearDownSession(), SIPClient::timerAHandler(), SIPClient::timerBHandler(), SIPClient::timerDHandler(), ClientTrickPlayState::updateStateOnScaleChange(), MPEG2TransportStreamFramer::updateTSPacketDurationEstimate(), BasicUDPSource::~BasicUDPSource(), ByteStreamFileSource::~ByteStreamFileSource(), DeviceSource::~DeviceSource(), RTSPServer::~RTSPServer(), StreamClientState::~StreamClientState(), and T140IdleFilter::~T140IdleFilter().
00059 {return fEnviron;}
| char const* Medium::name | ( | ) | const [inline, inherited] |
Definition at line 61 of file Media.hh.
References Medium::fMediumName.
Referenced by QuickTimeFileSink::addAtom_hdlr2(), Medium::close(), MP3ADUTranscoder::createNew(), MP3FromADUSource::createNew(), ADUFromMP3Source::createNew(), and MP3FileSource::initializeStream().
00061 {return fMediumName;}
| Boolean Medium::isSource | ( | ) | const [virtual, inherited] |
Reimplemented in MediaSource.
Definition at line 62 of file Media.cpp.
References False.
Referenced by MediaSource::lookupByName().
00062 { 00063 return False; // default implementation 00064 }
| Boolean Medium::isSink | ( | ) | const [virtual, inherited] |
| Boolean Medium::isRTCPInstance | ( | ) | const [virtual, inherited] |
Reimplemented in RTCPInstance.
Definition at line 70 of file Media.cpp.
References False.
Referenced by RTCPInstance::lookupByName().
00070 { 00071 return False; // default implementation 00072 }
| Boolean Medium::isRTSPServer | ( | ) | const [virtual, inherited] |
Reimplemented in RTSPServer.
Definition at line 78 of file Media.cpp.
References False.
Referenced by RTSPServer::lookupByName().
00078 { 00079 return False; // default implementation 00080 }
| Boolean Medium::isMediaSession | ( | ) | const [virtual, inherited] |
Reimplemented in MediaSession.
Definition at line 82 of file Media.cpp.
References False.
Referenced by MediaSession::lookupByName().
00082 { 00083 return False; // default implementation 00084 }
| Boolean Medium::isServerMediaSession | ( | ) | const [virtual, inherited] |
Reimplemented in ServerMediaSession.
Definition at line 86 of file Media.cpp.
References False.
Referenced by ServerMediaSession::lookupByName().
00086 { 00087 return False; // default implementation 00088 }
| Boolean Medium::isDarwinInjector | ( | ) | const [virtual, inherited] |
Reimplemented in DarwinInjector.
Definition at line 90 of file Media.cpp.
References False.
Referenced by DarwinInjector::lookupByName().
00090 { 00091 return False; // default implementation 00092 }
| TaskToken& Medium::nextTask | ( | ) | [inline, protected, inherited] |
Definition at line 78 of file Media.hh.
References Medium::fNextTask.
Referenced by BasicUDPSink::afterGettingFrame1(), MPEG4VideoFileServerMediaSubsession::afterPlayingDummy1(), H264VideoFileServerMediaSubsession::afterPlayingDummy1(), MPEG4VideoFileServerMediaSubsession::checkForAuxSDPLine1(), H264VideoFileServerMediaSubsession::checkForAuxSDPLine1(), WAVAudioFileSource::doGetNextFrame(), MP3FileSource::doGetNextFrame(), AMRAudioFileSource::doGetNextFrame(), ADTSAudioFileSource::doGetNextFrame(), MultiFramedRTPSource::doGetNextFrame1(), ByteStreamFileSource::doReadFromFile(), RTCPInstance::reschedule(), RTCPInstance::schedule(), MultiFramedRTPSink::sendPacketIfNecessary(), and MediaSink::stopPlaying().
00078 { 00079 return fNextTask; 00080 }
friend class MediaLookupTable [friend, inherited] |
unsigned RTSPClient::responseBufferSize = 20000 [static] |
Definition at line 158 of file RTSPClient.hh.
Referenced by handleResponseBytes(), handleSETUPResponse(), resetResponseBuffer(), and RTSPClient().
int RTSPClient::fVerbosityLevel [private] |
Definition at line 269 of file RTSPClient.hh.
Referenced by connectionHandler1(), connectToServer(), handleIncomingRequest(), handleResponseBytes(), resendCommand(), sendRequest(), and setupHTTPTunneling1().
Definition at line 270 of file RTSPClient.hh.
Referenced by openConnection(), responseHandlerForHTTP_GET1(), sendRequest(), sendSetupCommand(), and setupHTTPTunneling1().
char* RTSPClient::fUserAgentHeaderStr [private] |
Definition at line 271 of file RTSPClient.hh.
Referenced by sendRequest(), setUserAgentString(), and ~RTSPClient().
unsigned RTSPClient::fUserAgentHeaderStrLen [private] |
Definition at line 272 of file RTSPClient.hh.
Referenced by sendRequest(), and setUserAgentString().
int RTSPClient::fInputSocketNum [private] |
Definition at line 273 of file RTSPClient.hh.
Referenced by connectionHandler1(), handleSETUPResponse(), incomingDataHandler1(), openConnection(), resetTCPSockets(), sendRequest(), and socketNum().
int RTSPClient::fOutputSocketNum [private] |
Definition at line 273 of file RTSPClient.hh.
Referenced by connectionHandler1(), handleIncomingRequest(), openConnection(), resetTCPSockets(), responseHandlerForHTTP_GET1(), and sendRequest().
netAddressBits RTSPClient::fServerAddress [private] |
Definition at line 274 of file RTSPClient.hh.
Referenced by connectToServer(), handleSETUPResponse(), openConnection(), and reset().
unsigned RTSPClient::fCSeq [private] |
Definition at line 275 of file RTSPClient.hh.
Referenced by resendCommand(), sendAnnounceCommand(), sendDescribeCommand(), sendGetParameterCommand(), sendOptionsCommand(), sendPauseCommand(), sendPlayCommand(), sendRecordCommand(), sendSetParameterCommand(), sendSetupCommand(), and sendTeardownCommand().
char* RTSPClient::fBaseURL [private] |
Definition at line 276 of file RTSPClient.hh.
Referenced by openConnection(), sendRequest(), sessionURL(), setBaseURL(), and url().
Definition at line 277 of file RTSPClient.hh.
Referenced by createAuthenticatorString(), handleAuthenticationFailure(), openConnection(), reset(), sendAnnounceCommand(), sendDescribeCommand(), sendGetParameterCommand(), sendOptionsCommand(), sendPauseCommand(), sendPlayCommand(), sendRecordCommand(), sendSetParameterCommand(), sendSetupCommand(), and sendTeardownCommand().
unsigned char RTSPClient::fTCPStreamIdCount [private] |
char* RTSPClient::fLastSessionId [private] |
Definition at line 279 of file RTSPClient.hh.
Referenced by handleSETUPResponse(), reset(), and sendRequest().
unsigned RTSPClient::fSessionTimeoutParameter [private] |
Definition at line 280 of file RTSPClient.hh.
Referenced by handleSETUPResponse(), and sessionTimeoutParameter().
char* RTSPClient::fResponseBuffer [private] |
Definition at line 281 of file RTSPClient.hh.
Referenced by handleAlternativeRequestByte1(), handleIncomingRequest(), handleResponseBytes(), incomingDataHandler1(), RTSPClient(), and ~RTSPClient().
unsigned RTSPClient::fResponseBytesAlreadySeen [private] |
Definition at line 282 of file RTSPClient.hh.
Referenced by handleAlternativeRequestByte1(), handleIncomingRequest(), handleResponseBytes(), incomingDataHandler1(), and resetResponseBuffer().
unsigned RTSPClient::fResponseBufferBytesLeft [private] |
Definition at line 282 of file RTSPClient.hh.
Referenced by handleResponseBytes(), incomingDataHandler1(), and resetResponseBuffer().
Definition at line 283 of file RTSPClient.hh.
Referenced by changeResponseHandler(), connectionHandler1(), responseHandlerForHTTP_GET1(), and sendRequest().
Definition at line 283 of file RTSPClient.hh.
Referenced by changeResponseHandler(), responseHandlerForHTTP_GET1(), and sendRequest().
Definition at line 283 of file RTSPClient.hh.
Referenced by changeResponseHandler(), handleResponseBytes(), and sendRequest().
char RTSPClient::fSessionCookie[33] [private] |
unsigned RTSPClient::fSessionCookieCounter [private] |
Definition at line 288 of file RTSPClient.hh.
Referenced by connectionHandler1(), responseHandlerForHTTP_GET1(), and setupHTTPTunneling2().
TaskToken RTSPClient::fTimeoutTask [private] |
Definition at line 345 of file RTSPClient.hh.
char RTSPClient::fWatchVariableForSyncInterface [private] |
Definition at line 346 of file RTSPClient.hh.
char* RTSPClient::fResultString [private] |
Definition at line 347 of file RTSPClient.hh.
int RTSPClient::fResultCode [private] |
Definition at line 348 of file RTSPClient.hh.
1.5.2