RTSPServer.hh 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. /**********
  2. This library is free software; you can redistribute it and/or modify it under
  3. the terms of the GNU Lesser General Public License as published by the
  4. Free Software Foundation; either version 3 of the License, or (at your
  5. option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
  6. This library is distributed in the hope that it will be useful, but WITHOUT
  7. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
  9. more details.
  10. You should have received a copy of the GNU Lesser General Public License
  11. along with this library; if not, write to the Free Software Foundation, Inc.,
  12. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  13. **********/
  14. // "liveMedia"
  15. // Copyright (c) 1996-2019 Live Networks, Inc. All rights reserved.
  16. // A RTSP server
  17. // C++ header
  18. #ifndef _RTSP_SERVER_HH
  19. #define _RTSP_SERVER_HH
  20. #ifndef _GENERIC_MEDIA_SERVER_HH
  21. #include "GenericMediaServer.hh"
  22. #endif
  23. #ifndef _DIGEST_AUTHENTICATION_HH
  24. #include "DigestAuthentication.hh"
  25. #endif
  26. class RTSPServer: public GenericMediaServer {
  27. public:
  28. static RTSPServer* createNew(UsageEnvironment& env, Port ourPort = 554,
  29. UserAuthenticationDatabase* authDatabase = NULL,
  30. unsigned reclamationSeconds = 65);
  31. // If ourPort.num() == 0, we'll choose the port number
  32. // Note: The caller is responsible for reclaiming "authDatabase"
  33. // If "reclamationSeconds" > 0, then the "RTSPClientSession" state for
  34. // each client will get reclaimed (and the corresponding RTP stream(s)
  35. // torn down) if no RTSP commands - or RTCP "RR" packets - from the
  36. // client are received in at least "reclamationSeconds" seconds.
  37. static Boolean lookupByName(UsageEnvironment& env, char const* name,
  38. RTSPServer*& resultServer);
  39. typedef void (responseHandlerForREGISTER)(RTSPServer* rtspServer, unsigned requestId, int resultCode, char* resultString);
  40. unsigned registerStream(ServerMediaSession* serverMediaSession,
  41. char const* remoteClientNameOrAddress, portNumBits remoteClientPortNum,
  42. responseHandlerForREGISTER* responseHandler,
  43. char const* username = NULL, char const* password = NULL,
  44. Boolean receiveOurStreamViaTCP = False,
  45. char const* proxyURLSuffix = NULL);
  46. // 'Register' the stream represented by "serverMediaSession" with the given remote client (specifed by name and port number).
  47. // This is done using our custom "REGISTER" RTSP command.
  48. // The function returns a unique number that can be used to identify the request; this number is also passed to "responseHandler".
  49. // When a response is received from the remote client (or the "REGISTER" request fails), the specified response handler
  50. // (if non-NULL) is called. (Note that the "resultString" passed to the handler was dynamically allocated,
  51. // and should be delete[]d by the handler after use.)
  52. // If "receiveOurStreamViaTCP" is True, then we're requesting that the remote client access our stream using RTP/RTCP-over-TCP.
  53. // (Otherwise, the remote client may choose regular RTP/RTCP-over-UDP streaming.)
  54. // "proxyURLSuffix" (optional) is used only when the remote client is also a proxy server.
  55. // It tells the proxy server the suffix that it should use in its "rtsp://" URL (when front-end clients access the stream)
  56. typedef void (responseHandlerForDEREGISTER)(RTSPServer* rtspServer, unsigned requestId, int resultCode, char* resultString);
  57. unsigned deregisterStream(ServerMediaSession* serverMediaSession,
  58. char const* remoteClientNameOrAddress, portNumBits remoteClientPortNum,
  59. responseHandlerForDEREGISTER* responseHandler,
  60. char const* username = NULL, char const* password = NULL,
  61. char const* proxyURLSuffix = NULL);
  62. // Used to turn off a previous "registerStream()" - using our custom "DEREGISTER" RTSP command.
  63. char* rtspURL(ServerMediaSession const* serverMediaSession, int clientSocket = -1) const;
  64. // returns a "rtsp://" URL that could be used to access the
  65. // specified session (which must already have been added to
  66. // us using "addServerMediaSession()".
  67. // This string is dynamically allocated; caller should delete[]
  68. // (If "clientSocket" is non-negative, then it is used (by calling "getsockname()") to determine
  69. // the IP address to be used in the URL.)
  70. char* rtspURLPrefix(int clientSocket = -1) const;
  71. // like "rtspURL()", except that it returns just the common prefix used by
  72. // each session's "rtsp://" URL.
  73. // This string is dynamically allocated; caller should delete[]
  74. UserAuthenticationDatabase* setAuthenticationDatabase(UserAuthenticationDatabase* newDB);
  75. // Changes the server's authentication database to "newDB", returning a pointer to the old database (if there was one).
  76. // "newDB" may be NULL (you can use this to disable authentication at runtime, if desired).
  77. void disableStreamingRTPOverTCP() {
  78. fAllowStreamingRTPOverTCP = False;
  79. }
  80. Boolean setUpTunnelingOverHTTP(Port httpPort);
  81. // (Attempts to) enable RTSP-over-HTTP tunneling on the specified port.
  82. // 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).
  83. // Note: RTSP-over-HTTP tunneling is described in
  84. // http://mirror.informatimago.com/next/developer.apple.com/quicktime/icefloe/dispatch028.html
  85. // and http://images.apple.com/br/quicktime/pdf/QTSS_Modules.pdf
  86. portNumBits httpServerPortNum() const; // in host byte order. (Returns 0 if not present.)
  87. protected:
  88. RTSPServer(UsageEnvironment& env,
  89. int ourSocket, Port ourPort,
  90. UserAuthenticationDatabase* authDatabase,
  91. unsigned reclamationSeconds);
  92. // called only by createNew();
  93. virtual ~RTSPServer();
  94. virtual char const* allowedCommandNames(); // used to implement "RTSPClientConnection::handleCmd_OPTIONS()"
  95. virtual Boolean weImplementREGISTER(char const* cmd/*"REGISTER" or "DEREGISTER"*/,
  96. char const* proxyURLSuffix, char*& responseStr);
  97. // used to implement "RTSPClientConnection::handleCmd_REGISTER()"
  98. // Note: "responseStr" is dynamically allocated (or NULL), and should be delete[]d after the call
  99. virtual void implementCmd_REGISTER(char const* cmd/*"REGISTER" or "DEREGISTER"*/,
  100. char const* url, char const* urlSuffix, int socketToRemoteServer,
  101. Boolean deliverViaTCP, char const* proxyURLSuffix);
  102. // used to implement "RTSPClientConnection::handleCmd_REGISTER()"
  103. virtual UserAuthenticationDatabase* getAuthenticationDatabaseForCommand(char const* cmdName);
  104. virtual Boolean specialClientAccessCheck(int clientSocket, struct sockaddr_in& clientAddr,
  105. char const* urlSuffix);
  106. // a hook that allows subclassed servers to do server-specific access checking
  107. // on each client (e.g., based on client IP address), without using digest authentication.
  108. virtual Boolean specialClientUserAccessCheck(int clientSocket, struct sockaddr_in& clientAddr,
  109. char const* urlSuffix, char const *username);
  110. // another hook that allows subclassed servers to do server-specific access checking
  111. // - this time after normal digest authentication has already taken place (and would otherwise allow access).
  112. // (This test can only be used to further restrict access, not to grant additional access.)
  113. private: // redefined virtual functions
  114. virtual Boolean isRTSPServer() const;
  115. public: // should be protected, but some old compilers complain otherwise
  116. // The state of a TCP connection used by a RTSP client:
  117. class RTSPClientSession; // forward
  118. class RTSPClientConnection: public GenericMediaServer::ClientConnection {
  119. public:
  120. // A data structure that's used to implement the "REGISTER" command:
  121. class ParamsForREGISTER {
  122. public:
  123. ParamsForREGISTER(char const* cmd/*"REGISTER" or "DEREGISTER"*/,
  124. RTSPClientConnection* ourConnection, char const* url, char const* urlSuffix,
  125. Boolean reuseConnection, Boolean deliverViaTCP, char const* proxyURLSuffix);
  126. virtual ~ParamsForREGISTER();
  127. private:
  128. friend class RTSPClientConnection;
  129. char const* fCmd;
  130. RTSPClientConnection* fOurConnection;
  131. char* fURL;
  132. char* fURLSuffix;
  133. Boolean fReuseConnection, fDeliverViaTCP;
  134. char* fProxyURLSuffix;
  135. };
  136. protected: // redefined virtual functions:
  137. virtual void handleRequestBytes(int newBytesRead);
  138. protected:
  139. RTSPClientConnection(RTSPServer& ourServer, int clientSocket, struct sockaddr_in clientAddr);
  140. virtual ~RTSPClientConnection();
  141. friend class RTSPServer;
  142. friend class RTSPClientSession;
  143. // Make the handler functions for each command virtual, to allow subclasses to reimplement them, if necessary:
  144. virtual void handleCmd_OPTIONS();
  145. // You probably won't need to subclass/reimplement this function; reimplement "RTSPServer::allowedCommandNames()" instead.
  146. virtual void handleCmd_GET_PARAMETER(char const* fullRequestStr); // when operating on the entire server
  147. virtual void handleCmd_SET_PARAMETER(char const* fullRequestStr); // when operating on the entire server
  148. virtual void handleCmd_DESCRIBE(char const* urlPreSuffix, char const* urlSuffix, char const* fullRequestStr);
  149. virtual void handleCmd_REGISTER(char const* cmd/*"REGISTER" or "DEREGISTER"*/,
  150. char const* url, char const* urlSuffix, char const* fullRequestStr,
  151. Boolean reuseConnection, Boolean deliverViaTCP, char const* proxyURLSuffix);
  152. // You probably won't need to subclass/reimplement this function;
  153. // reimplement "RTSPServer::weImplementREGISTER()" and "RTSPServer::implementCmd_REGISTER()" instead.
  154. virtual void handleCmd_bad();
  155. virtual void handleCmd_notSupported();
  156. virtual void handleCmd_notFound();
  157. virtual void handleCmd_sessionNotFound();
  158. virtual void handleCmd_unsupportedTransport();
  159. // Support for optional RTSP-over-HTTP tunneling:
  160. virtual Boolean parseHTTPRequestString(char* resultCmdName, unsigned resultCmdNameMaxSize,
  161. char* urlSuffix, unsigned urlSuffixMaxSize,
  162. char* sessionCookie, unsigned sessionCookieMaxSize,
  163. char* acceptStr, unsigned acceptStrMaxSize);
  164. virtual void handleHTTPCmd_notSupported();
  165. virtual void handleHTTPCmd_notFound();
  166. virtual void handleHTTPCmd_OPTIONS();
  167. virtual void handleHTTPCmd_TunnelingGET(char const* sessionCookie);
  168. virtual Boolean handleHTTPCmd_TunnelingPOST(char const* sessionCookie, unsigned char const* extraData, unsigned extraDataSize);
  169. virtual void handleHTTPCmd_StreamingGET(char const* urlSuffix, char const* fullRequestStr);
  170. protected:
  171. void resetRequestBuffer();
  172. void closeSocketsRTSP();
  173. static void handleAlternativeRequestByte(void*, u_int8_t requestByte);
  174. void handleAlternativeRequestByte1(u_int8_t requestByte);
  175. Boolean authenticationOK(char const* cmdName, char const* urlSuffix, char const* fullRequestStr);
  176. void changeClientInputSocket(int newSocketNum, unsigned char const* extraData, unsigned extraDataSize);
  177. // used to implement RTSP-over-HTTP tunneling
  178. static void continueHandlingREGISTER(ParamsForREGISTER* params);
  179. virtual void continueHandlingREGISTER1(ParamsForREGISTER* params);
  180. // Shortcuts for setting up a RTSP response (prior to sending it):
  181. void setRTSPResponse(char const* responseStr);
  182. void setRTSPResponse(char const* responseStr, u_int32_t sessionId);
  183. void setRTSPResponse(char const* responseStr, char const* contentStr);
  184. void setRTSPResponse(char const* responseStr, u_int32_t sessionId, char const* contentStr);
  185. RTSPServer& fOurRTSPServer; // same as ::fOurServer
  186. int& fClientInputSocket; // aliased to ::fOurSocket
  187. int fClientOutputSocket;
  188. Boolean fIsActive;
  189. unsigned char* fLastCRLF;
  190. unsigned fRecursionCount;
  191. char const* fCurrentCSeq;
  192. Authenticator fCurrentAuthenticator; // used if access control is needed
  193. char* fOurSessionCookie; // used for optional RTSP-over-HTTP tunneling
  194. unsigned fBase64RemainderCount; // used for optional RTSP-over-HTTP tunneling (possible values: 0,1,2,3)
  195. };
  196. // The state of an individual client session (using one or more sequential TCP connections) handled by a RTSP server:
  197. class RTSPClientSession: public GenericMediaServer::ClientSession {
  198. protected:
  199. RTSPClientSession(RTSPServer& ourServer, u_int32_t sessionId);
  200. virtual ~RTSPClientSession();
  201. friend class RTSPServer;
  202. friend class RTSPClientConnection;
  203. // Make the handler functions for each command virtual, to allow subclasses to redefine them:
  204. virtual void handleCmd_SETUP(RTSPClientConnection* ourClientConnection,
  205. char const* urlPreSuffix, char const* urlSuffix, char const* fullRequestStr);
  206. virtual void handleCmd_withinSession(RTSPClientConnection* ourClientConnection,
  207. char const* cmdName,
  208. char const* urlPreSuffix, char const* urlSuffix,
  209. char const* fullRequestStr);
  210. virtual void handleCmd_TEARDOWN(RTSPClientConnection* ourClientConnection,
  211. ServerMediaSubsession* subsession);
  212. virtual void handleCmd_PLAY(RTSPClientConnection* ourClientConnection,
  213. ServerMediaSubsession* subsession, char const* fullRequestStr);
  214. virtual void handleCmd_PAUSE(RTSPClientConnection* ourClientConnection,
  215. ServerMediaSubsession* subsession);
  216. virtual void handleCmd_GET_PARAMETER(RTSPClientConnection* ourClientConnection,
  217. ServerMediaSubsession* subsession, char const* fullRequestStr);
  218. virtual void handleCmd_SET_PARAMETER(RTSPClientConnection* ourClientConnection,
  219. ServerMediaSubsession* subsession, char const* fullRequestStr);
  220. protected:
  221. void deleteStreamByTrack(unsigned trackNum);
  222. void reclaimStreamStates();
  223. Boolean isMulticast() const { return fIsMulticast; }
  224. // Shortcuts for setting up a RTSP response (prior to sending it):
  225. void setRTSPResponse(RTSPClientConnection* ourClientConnection, char const* responseStr) { ourClientConnection->setRTSPResponse(responseStr); }
  226. void setRTSPResponse(RTSPClientConnection* ourClientConnection, char const* responseStr, u_int32_t sessionId) { ourClientConnection->setRTSPResponse(responseStr, sessionId); }
  227. void setRTSPResponse(RTSPClientConnection* ourClientConnection, char const* responseStr, char const* contentStr) { ourClientConnection->setRTSPResponse(responseStr, contentStr); }
  228. void setRTSPResponse(RTSPClientConnection* ourClientConnection, char const* responseStr, u_int32_t sessionId, char const* contentStr) { ourClientConnection->setRTSPResponse(responseStr, sessionId, contentStr); }
  229. protected:
  230. RTSPServer& fOurRTSPServer; // same as ::fOurServer
  231. Boolean fIsMulticast, fStreamAfterSETUP;
  232. unsigned char fTCPStreamIdCount; // used for (optional) RTP/TCP
  233. Boolean usesTCPTransport() const { return fTCPStreamIdCount > 0; }
  234. unsigned fNumStreamStates;
  235. struct streamState {
  236. ServerMediaSubsession* subsession;
  237. int tcpSocketNum;
  238. void* streamToken;
  239. } * fStreamStates;
  240. };
  241. protected: // redefined virtual functions
  242. // If you subclass "RTSPClientConnection", then you must also redefine this virtual function in order
  243. // to create new objects of your subclass:
  244. virtual ClientConnection* createNewClientConnection(int clientSocket, struct sockaddr_in clientAddr);
  245. protected:
  246. // If you subclass "RTSPClientSession", then you must also redefine this virtual function in order
  247. // to create new objects of your subclass:
  248. virtual ClientSession* createNewClientSession(u_int32_t sessionId);
  249. private:
  250. static void incomingConnectionHandlerHTTP(void*, int /*mask*/);
  251. void incomingConnectionHandlerHTTP();
  252. void noteTCPStreamingOnSocket(int socketNum, RTSPClientSession* clientSession, unsigned trackNum);
  253. void unnoteTCPStreamingOnSocket(int socketNum, RTSPClientSession* clientSession, unsigned trackNum);
  254. void stopTCPStreamingOnSocket(int socketNum);
  255. private:
  256. friend class RTSPClientConnection;
  257. friend class RTSPClientSession;
  258. friend class RegisterRequestRecord;
  259. friend class DeregisterRequestRecord;
  260. int fHTTPServerSocket; // for optional RTSP-over-HTTP tunneling
  261. Port fHTTPServerPort; // ditto
  262. HashTable* fClientConnectionsForHTTPTunneling; // maps client-supplied 'session cookie' strings to "RTSPClientConnection"s
  263. // (used only for optional RTSP-over-HTTP tunneling)
  264. HashTable* fTCPStreamingDatabase;
  265. // maps TCP socket numbers to ids of sessions that are streaming over it (RTP/RTCP-over-TCP)
  266. HashTable* fPendingRegisterOrDeregisterRequests;
  267. unsigned fRegisterOrDeregisterRequestCounter;
  268. UserAuthenticationDatabase* fAuthDB;
  269. Boolean fAllowStreamingRTPOverTCP; // by default, True
  270. };
  271. ////////// A subclass of "RTSPServer" that implements the "REGISTER" command to set up proxying on the specified URL //////////
  272. class RTSPServerWithREGISTERProxying: public RTSPServer {
  273. public:
  274. static RTSPServerWithREGISTERProxying* createNew(UsageEnvironment& env, Port ourPort = 554,
  275. UserAuthenticationDatabase* authDatabase = NULL,
  276. UserAuthenticationDatabase* authDatabaseForREGISTER = NULL,
  277. unsigned reclamationSeconds = 65,
  278. Boolean streamRTPOverTCP = False,
  279. int verbosityLevelForProxying = 0,
  280. char const* backEndUsername = NULL,
  281. char const* backEndPassword = NULL);
  282. protected:
  283. RTSPServerWithREGISTERProxying(UsageEnvironment& env, int ourSocket, Port ourPort,
  284. UserAuthenticationDatabase* authDatabase, UserAuthenticationDatabase* authDatabaseForREGISTER,
  285. unsigned reclamationSeconds,
  286. Boolean streamRTPOverTCP, int verbosityLevelForProxying,
  287. char const* backEndUsername, char const* backEndPassword);
  288. // called only by createNew();
  289. virtual ~RTSPServerWithREGISTERProxying();
  290. protected: // redefined virtual functions
  291. virtual char const* allowedCommandNames();
  292. virtual Boolean weImplementREGISTER(char const* cmd/*"REGISTER" or "DEREGISTER"*/,
  293. char const* proxyURLSuffix, char*& responseStr);
  294. virtual void implementCmd_REGISTER(char const* cmd/*"REGISTER" or "DEREGISTER"*/,
  295. char const* url, char const* urlSuffix, int socketToRemoteServer,
  296. Boolean deliverViaTCP, char const* proxyURLSuffix);
  297. virtual UserAuthenticationDatabase* getAuthenticationDatabaseForCommand(char const* cmdName);
  298. private:
  299. Boolean fStreamRTPOverTCP;
  300. int fVerbosityLevelForProxying;
  301. unsigned fRegisteredProxyCounter;
  302. char* fAllowedCommandNames;
  303. UserAuthenticationDatabase* fAuthDBForREGISTER;
  304. char* fBackEndUsername;
  305. char* fBackEndPassword;
  306. };
  307. // A special version of "parseTransportHeader()", used just for parsing the "Transport:" header
  308. // in an incoming "REGISTER" command:
  309. void parseTransportHeaderForREGISTER(char const* buf, // in
  310. Boolean &reuseConnection, // out
  311. Boolean& deliverViaTCP, // out
  312. char*& proxyURLSuffix); // out
  313. #endif