liveMedia/include/RTSPServer.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-2012 Live Networks, Inc.  All rights reserved.
00018 // A RTSP server
00019 // C++ header
00020 
00021 #ifndef _RTSP_SERVER_HH
00022 #define _RTSP_SERVER_HH
00023 
00024 #ifndef _SERVER_MEDIA_SESSION_HH
00025 #include "ServerMediaSession.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 // A data structure used for optional user/password authentication:
00035 
00036 class UserAuthenticationDatabase {
00037 public:
00038   UserAuthenticationDatabase(char const* realm = NULL,
00039                              Boolean passwordsAreMD5 = False);
00040     // If "passwordsAreMD5" is True, then each password stored into, or removed from,
00041     // the database is actually the value computed
00042     // by md5(<username>:<realm>:<actual-password>)
00043   virtual ~UserAuthenticationDatabase();
00044 
00045   virtual void addUserRecord(char const* username, char const* password);
00046   virtual void removeUserRecord(char const* username);
00047 
00048   virtual char const* lookupPassword(char const* username);
00049       // returns NULL if the user name was not present
00050 
00051   char const* realm() { return fRealm; }
00052   Boolean passwordsAreMD5() { return fPasswordsAreMD5; }
00053 
00054 protected:
00055   HashTable* fTable;
00056   char* fRealm;
00057   Boolean fPasswordsAreMD5;
00058 };
00059 
00060 #define RTSP_BUFFER_SIZE 10000 // for incoming requests, and outgoing responses
00061 
00062 class RTSPServer: public Medium {
00063 public:
00064   static RTSPServer* createNew(UsageEnvironment& env, Port ourPort = 554,
00065                                UserAuthenticationDatabase* authDatabase = NULL,
00066                                unsigned reclamationTestSeconds = 65);
00067       // If ourPort.num() == 0, we'll choose the port number
00068       // Note: The caller is responsible for reclaiming "authDatabase"
00069       // If "reclamationTestSeconds" > 0, then the "RTSPClientSession" state for
00070       //     each client will get reclaimed (and the corresponding RTP stream(s)
00071       //     torn down) if no RTSP commands - or RTCP "RR" packets - from the
00072       //     client are received in at least "reclamationTestSeconds" seconds.
00073 
00074   static Boolean lookupByName(UsageEnvironment& env, char const* name,
00075                               RTSPServer*& resultServer);
00076 
00077   void addServerMediaSession(ServerMediaSession* serverMediaSession);
00078   virtual ServerMediaSession* lookupServerMediaSession(char const* streamName);
00079   void removeServerMediaSession(ServerMediaSession* serverMediaSession);
00080   void removeServerMediaSession(char const* streamName);
00081 
00082   char* rtspURL(ServerMediaSession const* serverMediaSession, int clientSocket = -1) const;
00083       // returns a "rtsp://" URL that could be used to access the
00084       // specified session (which must already have been added to
00085       // us using "addServerMediaSession()".
00086       // This string is dynamically allocated; caller should delete[]
00087       // (If "clientSocket" is non-negative, then it is used (by calling "getsockname()") to determine
00088       //  the IP address to be used in the URL.)
00089   char* rtspURLPrefix(int clientSocket = -1) const;
00090       // like "rtspURL()", except that it returns just the common prefix used by
00091       // each session's "rtsp://" URL.
00092       // This string is dynamically allocated; caller should delete[]
00093 
00094   UserAuthenticationDatabase* setAuthenticationDatabase(UserAuthenticationDatabase* newDB);
00095       // Changes the server's authentication database to "newDB", returning a pointer to the old database (if there was one).
00096       // "newDB" may be NULL (you can use this to disable authentication at runtime, if desired).
00097 
00098   Boolean setUpTunnelingOverHTTP(Port httpPort);
00099       // (Attempts to) enable RTSP-over-HTTP tunneling on the specified port.
00100       // Returns True iff the specified port can be used in this way (i.e., it's not already being used for a separate HTTP server).
00101       // Note: RTSP-over-HTTP tunneling is described in http://developer.apple.com/quicktime/icefloe/dispatch028.html
00102   portNumBits httpServerPortNum() const; // in host byte order.  (Returns 0 if not present.)
00103 
00104 protected:
00105   RTSPServer(UsageEnvironment& env,
00106              int ourSocket, Port ourPort,
00107              UserAuthenticationDatabase* authDatabase,
00108              unsigned reclamationTestSeconds);
00109       // called only by createNew();
00110   virtual ~RTSPServer();
00111 
00112   static int setUpOurSocket(UsageEnvironment& env, Port& ourPort);
00113   virtual Boolean specialClientAccessCheck(int clientSocket, struct sockaddr_in& clientAddr,
00114                                            char const* urlSuffix);
00115       // a hook that allows subclassed servers to do server-specific access checking
00116       // on each client (e.g., based on client IP address), without using
00117       // digest authentication.
00118 
00119 private: // redefined virtual functions
00120   virtual Boolean isRTSPServer() const;
00121 
00122 public: // should be protected, but some old compilers complain otherwise
00123   // The state of each individual session handled by a RTSP server:
00124   class RTSPClientSession {
00125   public:
00126     RTSPClientSession(RTSPServer& ourServer, unsigned sessionId,
00127                       int clientSocket, struct sockaddr_in clientAddr);
00128     virtual ~RTSPClientSession();
00129   protected:
00130     // Make the handler functions for each command virtual, to allow subclasses to redefine them:
00131     virtual void handleCmd_bad(char const* cseq);
00132     virtual void handleCmd_notSupported(char const* cseq);
00133     virtual void handleCmd_notFound(char const* cseq);
00134     virtual void handleCmd_unsupportedTransport(char const* cseq);
00135     virtual void handleCmd_OPTIONS(char const* cseq);
00136     virtual void handleCmd_DESCRIBE(char const* cseq,
00137                                     char const* urlPreSuffix, char const* urlSuffix,
00138                                     char const* fullRequestStr);
00139     virtual void handleCmd_SETUP(char const* cseq,
00140                                  char const* urlPreSuffix, char const* urlSuffix,
00141                                  char const* fullRequestStr);
00142     virtual void handleCmd_withinSession(char const* cmdName,
00143                                          char const* urlPreSuffix, char const* urlSuffix,
00144                                          char const* cseq, char const* fullRequestStr);
00145     virtual void handleCmd_TEARDOWN(ServerMediaSubsession* subsession,
00146                                     char const* cseq);
00147     virtual void handleCmd_PLAY(ServerMediaSubsession* subsession,
00148                                 char const* cseq, char const* fullRequestStr);
00149     virtual void handleCmd_PAUSE(ServerMediaSubsession* subsession,
00150                                  char const* cseq);
00151     virtual void handleCmd_GET_PARAMETER(ServerMediaSubsession* subsession,
00152                                          char const* cseq, char const* fullRequestStr);
00153     virtual void handleCmd_SET_PARAMETER(ServerMediaSubsession* subsession,
00154                                          char const* cseq, char const* fullRequestStr);
00155     // Support for optional RTSP-over-HTTP tunneling:
00156     virtual Boolean parseHTTPRequestString(char* resultCmdName, unsigned resultCmdNameMaxSize,
00157                                            char* urlSuffix, unsigned urlSuffixMaxSize,
00158                                            char* sessionCookie, unsigned sessionCookieMaxSize,
00159                                            char* acceptStr, unsigned acceptStrMaxSize);
00160     virtual void handleHTTPCmd_notSupported();
00161     virtual void handleHTTPCmd_notFound();
00162     virtual void handleHTTPCmd_TunnelingGET(char const* sessionCookie);
00163     virtual Boolean handleHTTPCmd_TunnelingPOST(char const* sessionCookie, unsigned char const* extraData, unsigned extraDataSize);
00164     virtual void handleHTTPCmd_StreamingGET(char const* urlSuffix, char const* fullRequestStr);
00165   protected:
00166     UsageEnvironment& envir() { return fOurServer.envir(); }
00167     void closeSockets();
00168     void reclaimStreamStates();
00169     void resetRequestBuffer();
00170     Boolean authenticationOK(char const* cmdName, char const* cseq,
00171                              char const* urlSuffix,
00172                              char const* fullRequestStr);
00173     Boolean isMulticast() const { return fIsMulticast; }
00174     static void incomingRequestHandler(void*, int /*mask*/);
00175     void incomingRequestHandler1();
00176     static void handleAlternativeRequestByte(void*, u_int8_t requestByte);
00177     void handleAlternativeRequestByte1(u_int8_t requestByte);
00178     void handleRequestBytes(int newBytesRead);
00179     void noteLiveness();
00180     static void noteClientLiveness(RTSPClientSession* clientSession);
00181     static void livenessTimeoutTask(RTSPClientSession* clientSession);
00182     void changeClientInputSocket(int newSocketNum, unsigned char const* extraData, unsigned extraDataSize);
00183   protected:
00184     RTSPServer& fOurServer;
00185     unsigned fOurSessionId;
00186     ServerMediaSession* fOurServerMediaSession;
00187     int fClientInputSocket, fClientOutputSocket;
00188     struct sockaddr_in fClientAddr;
00189     char* fSessionCookie; // used for optional RTSP-over-HTTP tunneling
00190     TaskToken fLivenessCheckTask;
00191     unsigned char fRequestBuffer[RTSP_BUFFER_SIZE];
00192     unsigned fRequestBytesAlreadySeen, fRequestBufferBytesLeft;
00193     unsigned char* fLastCRLF;
00194     unsigned fBase64RemainderCount; // used for optional RTSP-over-HTTP tunneling (possible values: 0,1,2,3)
00195     unsigned char fResponseBuffer[RTSP_BUFFER_SIZE];
00196     Boolean fIsMulticast, fSessionIsActive, fStreamAfterSETUP;
00197     Authenticator fCurrentAuthenticator; // used if access control is needed
00198     unsigned char fTCPStreamIdCount; // used for (optional) RTP/TCP
00199     unsigned fNumStreamStates;
00200     struct streamState {
00201       ServerMediaSubsession* subsession;
00202       void* streamToken;
00203     } * fStreamStates;
00204     unsigned fRecursionCount;
00205   };
00206 
00207 protected:
00208   // If you subclass "RTSPClientSession", then you should also redefine this virtual function in order
00209   // to create new objects of your subclass:
00210   virtual RTSPClientSession*
00211   createNewClientSession(unsigned sessionId, int clientSocket, struct sockaddr_in clientAddr);
00212 
00213   // An iterator over our "ServerMediaSession" objects:
00214   class ServerMediaSessionIterator {
00215   public:
00216     ServerMediaSessionIterator(RTSPServer& server);
00217     virtual ~ServerMediaSessionIterator();
00218     ServerMediaSession* next();
00219   private:
00220     HashTable::Iterator* fOurIterator;
00221     ServerMediaSession* fNextPtr;
00222   };
00223 
00224 private:
00225   static void incomingConnectionHandlerRTSP(void*, int /*mask*/);
00226   void incomingConnectionHandlerRTSP1();
00227 
00228   static void incomingConnectionHandlerHTTP(void*, int /*mask*/);
00229   void incomingConnectionHandlerHTTP1();
00230 
00231   void incomingConnectionHandler(int serverSocket);
00232 
00233 private:
00234   friend class RTSPClientSession;
00235   friend class ServerMediaSessionIterator;
00236   int fRTSPServerSocket;
00237   Port fRTSPServerPort;
00238   int fHTTPServerSocket; // for optional RTSP-over-HTTP tunneling
00239   Port fHTTPServerPort; // ditto
00240   HashTable* fClientSessionsForHTTPTunneling; // ditto (maps 'session cookie' strings to "RTSPClientSession"s)
00241   UserAuthenticationDatabase* fAuthDB;
00242   unsigned fReclamationTestSeconds;
00243   HashTable* fServerMediaSessions;
00244 };
00245 
00246 #endif

Generated on Thu May 17 07:11:46 2012 for live by  doxygen 1.5.2