proxyServer/live555ProxyServer.cpp

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 // Copyright (c) 1996-2014, Live Networks, Inc.  All rights reserved
00017 // LIVE555 Proxy Server
00018 // main program
00019 
00020 #include "liveMedia.hh"
00021 #include "BasicUsageEnvironment.hh"
00022 
00023 char const* progName;
00024 UsageEnvironment* env;
00025 UserAuthenticationDatabase* authDB = NULL;
00026 UserAuthenticationDatabase* authDBForREGISTER = NULL;
00027 
00028 // Default values of command-line parameters:
00029 int verbosityLevel = 0;
00030 Boolean streamRTPOverTCP = False;
00031 portNumBits tunnelOverHTTPPortNum = 0;
00032 char* username = NULL;
00033 char* password = NULL;
00034 Boolean proxyREGISTERRequests = False;
00035 char* usernameForREGISTER = NULL;
00036 char* passwordForREGISTER = NULL;
00037 
00038 static RTSPServer* createRTSPServer(Port port) {
00039   if (proxyREGISTERRequests) {
00040     return RTSPServerWithREGISTERProxying::createNew(*env, port, authDB, authDBForREGISTER, 65, streamRTPOverTCP, verbosityLevel);
00041   } else {
00042     return RTSPServer::createNew(*env, port, authDB);
00043   }
00044 }
00045 
00046 void usage() {
00047   *env << "Usage: " << progName
00048        << " [-v|-V]"
00049        << " [-t|-T <http-port>]"
00050        << " [-u <username> <password>]"
00051        << " [-R] [-U <username-for-REGISTER> <password-for-REGISTER>]"
00052        << " <rtsp-url-1> ... <rtsp-url-n>\n";
00053   exit(1);
00054 }
00055 
00056 int main(int argc, char** argv) {
00057   // Increase the maximum size of video frames that we can 'proxy' without truncation.
00058   // (Such frames are unreasonably large; the back-end servers should really not be sending frames this large!)
00059   OutPacketBuffer::maxSize = 100000; // bytes
00060 
00061   // Begin by setting up our usage environment:
00062   TaskScheduler* scheduler = BasicTaskScheduler::createNew();
00063   env = BasicUsageEnvironment::createNew(*scheduler);
00064 
00065   *env << "LIVE555 Proxy Server\n"
00066        << "\t(LIVE555 Streaming Media library version "
00067        << LIVEMEDIA_LIBRARY_VERSION_STRING << ")\n\n";
00068 
00069   // Check command-line arguments: optional parameters, then one or more rtsp:// URLs (of streams to be proxied):
00070   progName = argv[0];
00071   if (argc < 2) usage();
00072   while (argc > 1) {
00073     // Process initial command-line options (beginning with "-"):
00074     char* const opt = argv[1];
00075     if (opt[0] != '-') break; // the remaining parameters are assumed to be "rtsp://" URLs
00076 
00077     switch (opt[1]) {
00078     case 'v': { // verbose output
00079       verbosityLevel = 1;
00080       break;
00081     }
00082 
00083     case 'V': { // more verbose output
00084       verbosityLevel = 2;
00085       break;
00086     }
00087 
00088     case 't': {
00089       // Stream RTP and RTCP over the TCP 'control' connection.
00090       // (This is for the 'back end' (i.e., proxied) stream only.)
00091       streamRTPOverTCP = True;
00092       break;
00093     }
00094 
00095     case 'T': {
00096       // stream RTP and RTCP over a HTTP connection
00097       if (argc > 3 && argv[2][0] != '-') {
00098         // The next argument is the HTTP server port number:                                                                       
00099         if (sscanf(argv[2], "%hu", &tunnelOverHTTPPortNum) == 1
00100             && tunnelOverHTTPPortNum > 0) {
00101           ++argv; --argc;
00102           break;
00103         }
00104       }
00105 
00106       // If we get here, the option was specified incorrectly:
00107       usage();
00108       break;
00109     }
00110 
00111     case 'u': { // specify a username and password (to be used if the 'back end' (i.e., proxied) stream requires authentication)
00112       if (argc < 4) usage(); // there's no argv[3] (for the "password")
00113       username = argv[2];
00114       password = argv[3];
00115       argv += 2; argc -= 2;
00116       break;
00117     }
00118 
00119     case 'U': { // specify a username and password to use to authenticate incoming "REGISTER" commands
00120       if (argc < 4) usage(); // there's no argv[3] (for the "password")
00121       usernameForREGISTER = argv[2];
00122       passwordForREGISTER = argv[3];
00123 
00124       if (authDBForREGISTER == NULL) authDBForREGISTER = new UserAuthenticationDatabase;
00125       authDBForREGISTER->addUserRecord(usernameForREGISTER, passwordForREGISTER);
00126       argv += 2; argc -= 2;
00127       break;
00128     }
00129 
00130     case 'R': { // Handle incoming "REGISTER" requests by proxying the specified stream:
00131       proxyREGISTERRequests = True;
00132       break;
00133     }
00134 
00135     default: {
00136       usage();
00137       break;
00138     }
00139     }
00140 
00141     ++argv; --argc;
00142   }
00143   if (argc < 2 && !proxyREGISTERRequests) usage(); // there must be at least one "rtsp://" URL at the end 
00144   // Make sure that the remaining arguments appear to be "rtsp://" URLs:
00145   int i;
00146   for (i = 1; i < argc; ++i) {
00147     if (strncmp(argv[i], "rtsp://", 7) != 0) usage();
00148   }
00149   // Do some additional checking for invalid command-line argument combinations:
00150   if (authDBForREGISTER != NULL && !proxyREGISTERRequests) {
00151     *env << "The '-U <username> <password>' option can be used only with -R\n";
00152     usage();
00153   }
00154   if (streamRTPOverTCP) {
00155     if (tunnelOverHTTPPortNum > 0) {
00156       *env << "The -t and -T options cannot both be used!\n";
00157       usage();
00158     } else {
00159       tunnelOverHTTPPortNum = (portNumBits)(~0); // hack to tell "ProxyServerMediaSession" to stream over TCP, but not using HTTP
00160     }
00161   }
00162 
00163 #ifdef ACCESS_CONTROL
00164   // To implement client access control to the RTSP server, do the following:
00165   authDB = new UserAuthenticationDatabase;
00166   authDB->addUserRecord("username1", "password1"); // replace these with real strings
00167       // Repeat this line with each <username>, <password> that you wish to allow access to the server.
00168 #endif
00169 
00170   // Create the RTSP server.  Try first with the default port number (554),
00171   // and then with the alternative port number (8554):
00172   RTSPServer* rtspServer;
00173   portNumBits rtspServerPortNum = 554;
00174   rtspServer = createRTSPServer(rtspServerPortNum);
00175   if (rtspServer == NULL) {
00176     rtspServerPortNum = 8554;
00177     rtspServer = createRTSPServer(rtspServerPortNum);
00178   }
00179   if (rtspServer == NULL) {
00180     *env << "Failed to create RTSP server: " << env->getResultMsg() << "\n";
00181     exit(1);
00182   }
00183 
00184   // Create a proxy for each "rtsp://" URL specified on the command line:
00185   for (i = 1; i < argc; ++i) {
00186     char const* proxiedStreamURL = argv[i];
00187     char streamName[30];
00188     if (argc == 2) {
00189       sprintf(streamName, "%s", "proxyStream"); // there's just one stream; give it this name
00190     } else {
00191       sprintf(streamName, "proxyStream-%d", i); // there's more than one stream; distinguish them by name
00192     }
00193     ServerMediaSession* sms
00194       = ProxyServerMediaSession::createNew(*env, rtspServer,
00195                                            proxiedStreamURL, streamName,
00196                                            username, password, tunnelOverHTTPPortNum, verbosityLevel);
00197     rtspServer->addServerMediaSession(sms);
00198 
00199     char* proxyStreamURL = rtspServer->rtspURL(sms);
00200     *env << "RTSP stream, proxying the stream \"" << proxiedStreamURL << "\"\n";
00201     *env << "\tPlay this stream using the URL: " << proxyStreamURL << "\n";
00202     delete[] proxyStreamURL;
00203   }
00204 
00205   if (proxyREGISTERRequests) {
00206     *env << "(We handle incoming \"REGISTER\" requests on port " << rtspServerPortNum << ")\n";
00207   }
00208 
00209   // Also, attempt to create a HTTP server for RTSP-over-HTTP tunneling.
00210   // Try first with the default HTTP port (80), and then with the alternative HTTP
00211   // port numbers (8000 and 8080).
00212 
00213   if (rtspServer->setUpTunnelingOverHTTP(80) || rtspServer->setUpTunnelingOverHTTP(8000) || rtspServer->setUpTunnelingOverHTTP(8080)) {
00214     *env << "\n(We use port " << rtspServer->httpServerPortNum() << " for optional RTSP-over-HTTP tunneling.)\n";
00215   } else {
00216     *env << "\n(RTSP-over-HTTP tunneling is not available.)\n";
00217   }
00218 
00219   // Now, enter the event loop:
00220   env->taskScheduler().doEventLoop(); // does not return
00221 
00222   return 0; // only to prevent compiler warning
00223 }

Generated on Tue Mar 25 14:35:36 2014 for live by  doxygen 1.5.2