liveMedia/include/RTSPClient.hh

Go to the documentation of this file.
00001 /**********
00002 This library is free software; you can redistribute it and/or modify it under
00003 the terms of the GNU Lesser General Public License as published by the
00004 Free Software Foundation; either version 2.1 of the License, or (at your
00005 option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
00006 
00007 This library is distributed in the hope that it will be useful, but WITHOUT
00008 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00009 FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
00010 more details.
00011 
00012 You should have received a copy of the GNU Lesser General Public License
00013 along with this library; if not, write to the Free Software Foundation, Inc.,
00014 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
00015 **********/
00016 // "liveMedia"
00017 // Copyright (c) 1996-2013 Live Networks, Inc.  All rights reserved.
00018 // A generic RTSP client - for a single "rtsp://" URL
00019 // C++ header
00020 
00021 #ifndef _RTSP_CLIENT_HH
00022 #define _RTSP_CLIENT_HH
00023 
00024 #ifndef _MEDIA_SESSION_HH
00025 #include "MediaSession.hh"
00026 #endif
00027 #ifndef _NET_ADDRESS_HH
00028 #include "NetAddress.hh"
00029 #endif
00030 #ifndef _DIGEST_AUTHENTICATION_HH
00031 #include "DigestAuthentication.hh"
00032 #endif
00033 
00034 class RTSPClient: public Medium {
00035 public:
00036   static RTSPClient* createNew(UsageEnvironment& env, char const* rtspURL,
00037                                int verbosityLevel = 0,
00038                                char const* applicationName = NULL,
00039                                portNumBits tunnelOverHTTPPortNum = 0);
00040   // If "tunnelOverHTTPPortNum" is non-zero, we tunnel RTSP (and RTP)
00041   // over a HTTP connection with the given port number, using the technique
00042   // described in Apple's document <http://developer.apple.com/documentation/QuickTime/QTSS/Concepts/chapter_2_section_14.html>
00043 
00044   typedef void (responseHandler)(RTSPClient* rtspClient,
00045                                  int resultCode, char* resultString);
00046       // A function that is called in response to a RTSP command.  The parameters are as follows:
00047       //     "rtspClient": The "RTSPClient" object on which the original command was issued.
00048       //     "resultCode": If zero, then the command completed successfully.  If non-zero, then the command did not complete
00049       //         successfully, and "resultCode" indicates the error, as follows:
00050       //             A positive "resultCode" is a RTSP error code (for example, 404 means "not found")
00051       //             A negative "resultCode" indicates a socket/network error; 0-"resultCode" is the standard "errno" code.
00052       //     "resultString": A ('\0'-terminated) string returned along with the response, or else NULL.
00053       //         In particular:
00054       //             "resultString" for a successful "DESCRIBE" command will be the media session's SDP description.
00055       //             "resultString" for a successful "OPTIONS" command will be a list of allowed commands.
00056       //         Note that this string can be present (i.e., not NULL) even if "resultCode" is non-zero - i.e., an error message.
00057       //         Also, "resultString" can be NULL, even if "resultCode" is zero (e.g., if the RTSP command succeeded, but without
00058       //             including an appropriate result header).
00059       //         Note also that this string is dynamically allocated, and must be freed by the handler (or the caller)
00060       //             - using "delete[]".
00061 
00062   unsigned sendDescribeCommand(responseHandler* responseHandler, Authenticator* authenticator = NULL);
00063       // Issues a RTSP "DESCRIBE" command, then returns the "CSeq" sequence number that was used in the command.
00064       // The (programmer-supplied) "responseHandler" function is called later to handle the response
00065       //     (or is called immediately - with an error code - if the command cannot be sent).
00066       // "authenticator" (optional) is used for access control.  If you have username and password strings, you can use this by
00067       //     passing an actual parameter that you created by creating an "Authenticator(username, password) object".
00068       //     (Note that if you supply a non-NULL "authenticator" parameter, you need do this only for the first command you send.)
00069 
00070   unsigned sendOptionsCommand(responseHandler* responseHandler, Authenticator* authenticator = NULL);
00071       // Issues a RTSP "OPTIONS" command, then returns the "CSeq" sequence number that was used in the command.
00072       // (The "responseHandler" and "authenticator" parameters are as described for "sendDescribeCommand".)
00073 
00074   unsigned sendAnnounceCommand(char const* sdpDescription, responseHandler* responseHandler, Authenticator* authenticator = NULL);
00075       // Issues a RTSP "ANNOUNCE" command (with "sdpDescription" as parameter),
00076       //     then returns the "CSeq" sequence number that was used in the command.
00077       // (The "responseHandler" and "authenticator" parameters are as described for "sendDescribeCommand".)
00078 
00079   unsigned sendSetupCommand(MediaSubsession& subsession, responseHandler* responseHandler,
00080                             Boolean streamOutgoing = False,
00081                             Boolean streamUsingTCP = False,
00082                             Boolean forceMulticastOnUnspecified = False,
00083                             Authenticator* authenticator = NULL);
00084       // Issues a RTSP "SETUP" command, then returns the "CSeq" sequence number that was used in the command.
00085       // (The "responseHandler" and "authenticator" parameters are as described for "sendDescribeCommand".)
00086 
00087   unsigned sendPlayCommand(MediaSession& session, responseHandler* responseHandler,
00088                            double start = 0.0f, double end = -1.0f, float scale = 1.0f,
00089                            Authenticator* authenticator = NULL);
00090       // Issues an aggregate RTSP "PLAY" command on "session", then returns the "CSeq" sequence number that was used in the command.
00091       // (Note: start=-1 means 'resume'; end=-1 means 'play to end')
00092       // (The "responseHandler" and "authenticator" parameters are as described for "sendDescribeCommand".)
00093   unsigned sendPlayCommand(MediaSubsession& subsession, responseHandler* responseHandler,
00094                            double start = 0.0f, double end = -1.0f, float scale = 1.0f,
00095                            Authenticator* authenticator = NULL);
00096       // Issues a RTSP "PLAY" command on "subsession", then returns the "CSeq" sequence number that was used in the command.
00097       // (Note: start=-1 means 'resume'; end=-1 means 'play to end')
00098       // (The "responseHandler" and "authenticator" parameters are as described for "sendDescribeCommand".)
00099 
00100   // Alternative forms of "sendPlayCommand()", used to send "PLAY" commands that include an 'absolute' time range:
00101   // (The "absStartTime" string (and "absEndTime" string, if present) *must* be of the form
00102   //  "YYYYMMDDTHHMMSSZ" or "YYYYMMDDTHHMMSS.<frac>Z")
00103   unsigned sendPlayCommand(MediaSession& session, responseHandler* responseHandler,
00104                            char const* absStartTime, char const* absEndTime = NULL, float scale = 1.0f,
00105                            Authenticator* authenticator = NULL);
00106   unsigned sendPlayCommand(MediaSubsession& subsession, responseHandler* responseHandler,
00107                            char const* absStartTime, char const* absEndTime = NULL, float scale = 1.0f,
00108                            Authenticator* authenticator = NULL);
00109 
00110   unsigned sendPauseCommand(MediaSession& session, responseHandler* responseHandler, Authenticator* authenticator = NULL);
00111       // Issues an aggregate RTSP "PAUSE" command on "session", then returns the "CSeq" sequence number that was used in the command.
00112       // (The "responseHandler" and "authenticator" parameters are as described for "sendDescribeCommand".)
00113   unsigned sendPauseCommand(MediaSubsession& subsession, responseHandler* responseHandler, Authenticator* authenticator = NULL);
00114       // Issues a RTSP "PAUSE" command on "subsession", then returns the "CSeq" sequence number that was used in the command.
00115       // (The "responseHandler" and "authenticator" parameters are as described for "sendDescribeCommand".)
00116 
00117   unsigned sendRecordCommand(MediaSession& session, responseHandler* responseHandler, Authenticator* authenticator = NULL);
00118       // Issues an aggregate RTSP "RECORD" command on "session", then returns the "CSeq" sequence number that was used in the command.
00119       // (The "responseHandler" and "authenticator" parameters are as described for "sendDescribeCommand".)
00120   unsigned sendRecordCommand(MediaSubsession& subsession, responseHandler* responseHandler, Authenticator* authenticator = NULL);
00121       // Issues a RTSP "RECORD" command on "subsession", then returns the "CSeq" sequence number that was used in the command.
00122       // (The "responseHandler" and "authenticator" parameters are as described for "sendDescribeCommand".)
00123 
00124   unsigned sendTeardownCommand(MediaSession& session, responseHandler* responseHandler, Authenticator* authenticator = NULL);
00125       // Issues an aggregate RTSP "TEARDOWN" command on "session", then returns the "CSeq" sequence number that was used in the command.
00126       // (The "responseHandler" and "authenticator" parameters are as described for "sendDescribeCommand".)
00127   unsigned sendTeardownCommand(MediaSubsession& subsession, responseHandler* responseHandler, Authenticator* authenticator = NULL);
00128       // Issues a RTSP "TEARDOWN" command on "subsession", then returns the "CSeq" sequence number that was used in the command.
00129       // (The "responseHandler" and "authenticator" parameters are as described for "sendDescribeCommand".)
00130 
00131   unsigned sendSetParameterCommand(MediaSession& session, responseHandler* responseHandler,
00132                                    char const* parameterName, char const* parameterValue,
00133                                    Authenticator* authenticator = NULL);
00134       // Issues an aggregate RTSP "SET_PARAMETER" command on "session", then returns the "CSeq" sequence number that was used in the command.
00135       // (The "responseHandler" and "authenticator" parameters are as described for "sendDescribeCommand".)
00136 
00137   unsigned sendGetParameterCommand(MediaSession& session, responseHandler* responseHandler, char const* parameterName,
00138                                    Authenticator* authenticator = NULL);
00139       // Issues an aggregate RTSP "GET_PARAMETER" command on "session", then returns the "CSeq" sequence number that was used in the command.
00140       // (The "responseHandler" and "authenticator" parameters are as described for "sendDescribeCommand".)
00141 
00142   Boolean changeResponseHandler(unsigned cseq, responseHandler* newResponseHandler);
00143       // Changes the response handler for the previously-performed command (whose operation returned "cseq").
00144       // (To turn off any response handling for the command, use a "newResponseHandler" value of NULL.  This might be done as part
00145       //  of an implementation of a 'timeout handler' on the command, for example.)
00146       // This function returns True iff "cseq" was for a valid previously-performed command (whose response is still unhandled).
00147 
00148   int socketNum() const { return fInputSocketNum; }
00149 
00150   static Boolean lookupByName(UsageEnvironment& env,
00151                               char const* sourceName,
00152                               RTSPClient*& resultClient);
00153 
00154   static Boolean parseRTSPURL(UsageEnvironment& env, char const* url,
00155                               char*& username, char*& password, NetAddress& address, portNumBits& portNum, char const** urlSuffix = NULL);
00156       // Parses "url" as "rtsp://[<username>[:<password>]@]<server-address-or-name>[:<port>][/<stream-name>]"
00157       // (Note that the returned "username" and "password" are either NULL, or heap-allocated strings that the caller must later delete[].)
00158 
00159   void setUserAgentString(char const* userAgentName);
00160       // sets an alternative string to be used in RTSP "User-Agent:" headers
00161 
00162   unsigned sessionTimeoutParameter() const { return fSessionTimeoutParameter; }
00163 
00164   char const* url() const { return fBaseURL; }
00165 
00166   static unsigned responseBufferSize;
00167 
00168 public: // Some compilers complain if this is "private:"
00169   // The state of a request-in-progress:
00170   class RequestRecord {
00171   public:
00172     RequestRecord(unsigned cseq, char const* commandName, responseHandler* handler,
00173                   MediaSession* session = NULL, MediaSubsession* subsession = NULL, u_int32_t booleanFlags = 0,
00174                   double start = 0.0f, double end = -1.0f, float scale = 1.0f, char const* contentStr = NULL);
00175     RequestRecord(unsigned cseq, responseHandler* handler,
00176                   char const* absStartTime, char const* absEndTime = NULL, float scale = 1.0f,
00177                   MediaSession* session = NULL, MediaSubsession* subsession = NULL);
00178         // alternative constructor for creating "PLAY" requests that include 'absolute' time values
00179     virtual ~RequestRecord();
00180 
00181     RequestRecord*& next() { return fNext; }
00182     unsigned& cseq() { return fCSeq; }
00183     char const* commandName() const { return fCommandName; }
00184     MediaSession* session() const { return fSession; }
00185     MediaSubsession* subsession() const { return fSubsession; }
00186     u_int32_t booleanFlags() const { return fBooleanFlags; }
00187     double start() const { return fStart; }
00188     double end() const { return fEnd; }
00189     char const* absStartTime() const { return fAbsStartTime; }
00190     char const* absEndTime() const { return fAbsEndTime; }
00191     float scale() const { return fScale; }
00192     char* contentStr() const { return fContentStr; }
00193     responseHandler*& handler() { return fHandler; }
00194 
00195   private:
00196     RequestRecord* fNext;
00197     unsigned fCSeq;
00198     char const* fCommandName;
00199     MediaSession* fSession;
00200     MediaSubsession* fSubsession;
00201     u_int32_t fBooleanFlags;
00202     double fStart, fEnd;
00203     char *fAbsStartTime, *fAbsEndTime; // used for optional 'absolute' (i.e., "time=") range specifications
00204     float fScale;
00205     char* fContentStr;
00206     responseHandler* fHandler;
00207   };
00208 
00209 protected:
00210   RTSPClient(UsageEnvironment& env, char const* rtspURL,
00211              int verbosityLevel, char const* applicationName, portNumBits tunnelOverHTTPPortNum);
00212       // called only by createNew();
00213   virtual ~RTSPClient();
00214 
00215   void reset();
00216   void setBaseURL(char const* url);
00217   virtual unsigned sendRequest(RequestRecord* request);
00218 
00219 private: // redefined virtual functions
00220   virtual Boolean isRTSPClient() const;
00221 
00222 private:
00223   class RequestQueue {
00224   public:
00225     RequestQueue();
00226     RequestQueue(RequestQueue& origQueue); // moves the queue contents to the new queue
00227     virtual ~RequestQueue();
00228 
00229     void enqueue(RequestRecord* request); // "request" must not be NULL
00230     RequestRecord* dequeue();
00231     void putAtHead(RequestRecord* request); // "request" must not be NULL
00232     RequestRecord* findByCSeq(unsigned cseq);
00233     Boolean isEmpty() const { return fHead == NULL; }
00234 
00235   private:
00236     RequestRecord* fHead;
00237     RequestRecord* fTail;
00238   };
00239 
00240   void resetTCPSockets();
00241   void resetResponseBuffer();
00242   int openConnection(); // -1: failure; 0: pending; 1: success
00243   int connectToServer(int socketNum, portNumBits remotePortNum); // used to implement "openConnection()"; result values are the same
00244   char* createAuthenticatorString(char const* cmd, char const* url);
00245   void handleRequestError(RequestRecord* request);
00246   Boolean parseResponseCode(char const* line, unsigned& responseCode, char const*& responseString);
00247   void handleIncomingRequest();
00248   static Boolean checkForHeader(char const* line, char const* headerName, unsigned headerNameLength, char const*& headerParams);
00249   Boolean parseTransportParams(char const* paramsStr,
00250                                char*& serverAddressStr, portNumBits& serverPortNum,
00251                                unsigned char& rtpChannelId, unsigned char& rtcpChannelId);
00252   Boolean parseScaleParam(char const* paramStr, float& scale);
00253   Boolean parseRTPInfoParams(char const*& paramStr, u_int16_t& seqNum, u_int32_t& timestamp);
00254   Boolean handleSETUPResponse(MediaSubsession& subsession, char const* sessionParamsStr, char const* transportParamsStr,
00255                               Boolean streamUsingTCP);
00256   Boolean handlePLAYResponse(MediaSession& session, MediaSubsession& subsession,
00257                              char const* scaleParamsStr, char const* rangeParamsStr, char const* rtpInfoParamsStr);
00258   Boolean handleTEARDOWNResponse(MediaSession& session, MediaSubsession& subsession);
00259   Boolean handleGET_PARAMETERResponse(char const* parameterName, char*& resultValueString);
00260   Boolean handleAuthenticationFailure(char const* wwwAuthenticateParamsStr);
00261   Boolean resendCommand(RequestRecord* request);
00262   char const* sessionURL(MediaSession const& session) const;
00263   static void handleAlternativeRequestByte(void*, u_int8_t requestByte);
00264   void handleAlternativeRequestByte1(u_int8_t requestByte);
00265   void constructSubsessionURL(MediaSubsession const& subsession,
00266                               char const*& prefix,
00267                               char const*& separator,
00268                               char const*& suffix);
00269 
00270   // Support for tunneling RTSP-over-HTTP:
00271   Boolean setupHTTPTunneling1(); // send the HTTP "GET"
00272   static void responseHandlerForHTTP_GET(RTSPClient* rtspClient, int responseCode, char* responseString);
00273   void responseHandlerForHTTP_GET1(int responseCode, char* responseString);
00274   Boolean setupHTTPTunneling2(); // send the HTTP "POST"
00275 
00276   // Support for asynchronous connections to the server:
00277   static void connectionHandler(void*, int /*mask*/);
00278   void connectionHandler1();
00279 
00280   // Support for handling data sent back by a server:
00281   static void incomingDataHandler(void*, int /*mask*/);
00282   void incomingDataHandler1();
00283   void handleResponseBytes(int newBytesRead);
00284 
00285 protected:
00286   int fVerbosityLevel;
00287   unsigned fCSeq; // sequence number, used in consecutive requests
00288   Authenticator fCurrentAuthenticator;
00289 
00290 private:
00291   portNumBits fTunnelOverHTTPPortNum;
00292   char* fUserAgentHeaderStr;
00293   unsigned fUserAgentHeaderStrLen;
00294   int fInputSocketNum, fOutputSocketNum;
00295   netAddressBits fServerAddress;
00296   char* fBaseURL;
00297   unsigned char fTCPStreamIdCount; // used for (optional) RTP/TCP
00298   char* fLastSessionId;
00299   unsigned fSessionTimeoutParameter; // optionally set in response "Session:" headers
00300   char* fResponseBuffer;
00301   unsigned fResponseBytesAlreadySeen, fResponseBufferBytesLeft;
00302   RequestQueue fRequestsAwaitingConnection, fRequestsAwaitingHTTPTunneling, fRequestsAwaitingResponse;
00303 
00304   // Support for tunneling RTSP-over-HTTP:
00305   char fSessionCookie[33];
00306   unsigned fSessionCookieCounter;
00307   Boolean fHTTPTunnelingConnectionIsPending;
00308 
00309 #ifdef RTSPCLIENT_SYNCHRONOUS_INTERFACE
00310   // Old "RTSPClient" interface, which performs synchronous (blocking) operations.
00311   // This will eventually go away, so new applications should not use it.
00312 public:
00313   static RTSPClient* createNew(UsageEnvironment& env,
00314                                int verbosityLevel = 0,
00315                                char const* applicationName = NULL,
00316                                portNumBits tunnelOverHTTPPortNum = 0);
00317   char* describeURL(char const* url, Authenticator* authenticator = NULL,
00318                     Boolean allowKasennaProtocol = False, int timeout = -1);
00319   char* describeWithPassword(char const* url,
00320                              char const* username, char const* password,
00321                              Boolean allowKasennaProtocol = False, 
00322                              int timeout = -1);
00323   char* sendOptionsCmd(char const* url,
00324                        char* username = NULL, char* password = NULL,
00325                        Authenticator* authenticator = NULL,
00326                        int timeout = -1);
00327   Boolean announceSDPDescription(char const* url,
00328                                  char const* sdpDescription,
00329                                  Authenticator* authenticator = NULL,
00330                                  int timeout = -1);
00331   Boolean announceWithPassword(char const* url, char const* sdpDescription,
00332                                char const* username, char const* password, int timeout = -1);
00333   Boolean setupMediaSubsession(MediaSubsession& subsession,
00334                                Boolean streamOutgoing = False,
00335                                Boolean streamUsingTCP = False,
00336                                Boolean forceMulticastOnUnspecified = False);
00337   Boolean playMediaSession(MediaSession& session,
00338                            double start = 0.0f, double end = -1.0f,
00339                            float scale = 1.0f);
00340   Boolean playMediaSubsession(MediaSubsession& subsession,
00341                               double start = 0.0f, double end = -1.0f,
00342                               float scale = 1.0f,
00343                               Boolean hackForDSS = False);
00344   Boolean pauseMediaSession(MediaSession& session);
00345   Boolean pauseMediaSubsession(MediaSubsession& subsession);
00346   Boolean recordMediaSubsession(MediaSubsession& subsession);
00347   Boolean setMediaSessionParameter(MediaSession& session,
00348                                    char const* parameterName,
00349                                    char const* parameterValue);
00350   Boolean getMediaSessionParameter(MediaSession& session,
00351                                    char const* parameterName,
00352                                    char*& parameterValue);
00353   Boolean teardownMediaSession(MediaSession& session);
00354   Boolean teardownMediaSubsession(MediaSubsession& subsession);
00355 
00356   static Boolean parseRTSPURLUsernamePassword(char const* url,
00357                                               char*& username, char*& password);
00358 private: // used to implement the old interface:
00359   static void responseHandlerForSyncInterface(RTSPClient* rtspClient,
00360                                               int responseCode, char* responseString);
00361   void responseHandlerForSyncInterface1(int responseCode, char* responseString);
00362   static void timeoutHandlerForSyncInterface(void* rtspClient);
00363   void timeoutHandlerForSyncInterface1();
00364   TaskToken fTimeoutTask;
00365   char fWatchVariableForSyncInterface;
00366   char* fResultString;
00367   int fResultCode;
00368 #endif
00369 };
00370 
00371 #endif

Generated on Mon Apr 29 13:28:01 2013 for live by  doxygen 1.5.2