Sophie

Sophie

distrib > Mageia > 5 > x86_64 > by-pkgid > 4402953a691cd9397ded7dc09c2c19cf > files > 3

live-2014.08.26-3.mga5.src.rpm

--- live-2013.06.14/liveMedia/include/RTSPClient.hh	2013-06-14 06:24:48.000000000 -0400
+++ live-2013.01.04/liveMedia/include/RTSPClient.hh	2013-01-04 00:07:48.000000000 -0500
@@ -308,6 +305,67 @@ private:
   char fSessionCookie[33];
   unsigned fSessionCookieCounter;
   Boolean fHTTPTunnelingConnectionIsPending;
+
+#ifdef RTSPCLIENT_SYNCHRONOUS_INTERFACE
+  // Old "RTSPClient" interface, which performs synchronous (blocking) operations.
+  // This will eventually go away, so new applications should not use it.
+public:
+  static RTSPClient* createNew(UsageEnvironment& env,
+                               int verbosityLevel = 0,
+                               char const* applicationName = NULL,
+                               portNumBits tunnelOverHTTPPortNum = 0);
+  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*& parameterValue);
+  Boolean teardownMediaSession(MediaSession& session);
+  Boolean teardownMediaSubsession(MediaSubsession& subsession);
+
+  static Boolean parseRTSPURLUsernamePassword(char const* url,
+					      char*& username, char*& password);
+private: // used to implement the old interface:
+  static void responseHandlerForSyncInterface(RTSPClient* rtspClient,
+					      int responseCode, char* responseString);
+  void responseHandlerForSyncInterface1(int responseCode, char* responseString);
+  static void timeoutHandlerForSyncInterface(void* rtspClient);
+  void timeoutHandlerForSyncInterface1();
+  TaskToken fTimeoutTask;
+  char fWatchVariableForSyncInterface;
+  char* fResultString;
+  int fResultCode;
+#endif
 };
 
 
--- live-2013.06.14/liveMedia/RTSPClient.cpp	2013-06-14 06:24:48.000000000 -0400
+++ live-2013.01.04/liveMedia/RTSPClient.cpp	2013-01-04 00:07:48.000000000 -0500
@@ -1765,6 +1754,330 @@ RTSPClient::RequestRecord* RTSPClient::R
   }
   return NULL;
 }
+
+
+#ifdef RTSPCLIENT_SYNCHRONOUS_INTERFACE
+// Implementation of the old (synchronous) "RTSPClient" interface, using the new (asynchronous) interface:
+RTSPClient* RTSPClient::createNew(UsageEnvironment& env,
+				  int verbosityLevel,
+				  char const* applicationName,
+				  portNumBits tunnelOverHTTPPortNum) {
+  return new RTSPClient(env, NULL,
+		verbosityLevel, applicationName, tunnelOverHTTPPortNum, -1);
+}
+
+char* RTSPClient::describeURL(char const* url, Authenticator* authenticator,
+			      Boolean allowKasennaProtocol, int timeout) {
+  // Sorry 'Kasenna', but the party's over.  You've had 6 years to make your servers compliant with the standard RTSP protocol.
+  // We're not going to support your non-standard hacked version of the protocol any more.  Starting now, the "allowKasennaProtocol"
+  // parameter is a noop (and eventually, when the synchronous interface goes away completely, then so will this parameter).
+
+  // First, check whether "url" contains a username:password to be used.  If so, handle this using "describeWithPassword()" instead:
+  char* username; char* password;
+  if (authenticator == NULL
+      && parseRTSPURLUsernamePassword(url, username, password)) {
+    char* result = describeWithPassword(url, username, password, allowKasennaProtocol, timeout);
+    delete[] username; delete[] password; // they were dynamically allocated
+    return result;
+  }
+
+  setBaseURL(url);
+  fWatchVariableForSyncInterface = 0;
+  fTimeoutTask = NULL;  // by default, unless:
+  if (timeout > 0) {
+    // Schedule a task to be called when the specified timeout interval expires.
+    // Note that we do this *before* attempting to send the RTSP command, in case this attempt fails immediately, calling the
+    // command response handler - because we want the response handler to unschedule any pending timeout handler.
+    fTimeoutTask = envir().taskScheduler().scheduleDelayedTask(timeout*1000000, timeoutHandlerForSyncInterface, this);
+  }
+  (void)sendDescribeCommand(responseHandlerForSyncInterface, authenticator);
+
+  // Now block (but handling events) until we get a response (or a timeout):
+  envir().taskScheduler().doEventLoop(&fWatchVariableForSyncInterface);
+  if (fResultCode == 0) return fResultString; // success
+  delete[] fResultString;
+  return NULL;
+}
+
+char* RTSPClient::describeWithPassword(char const* url,
+				       char const* username, char const* password,
+				       Boolean allowKasennaProtocol, int timeout) {
+  Authenticator authenticator(username, password);
+  return describeURL(url, &authenticator, allowKasennaProtocol, timeout);
+}
+
+char* RTSPClient::sendOptionsCmd(char const* url,
+				 char* username, char* password,
+				 Authenticator* authenticator,
+				 int timeout) {
+  char* result = NULL;
+  Boolean haveAllocatedAuthenticator = False;
+  if (authenticator == NULL) {
+    // First, check whether "url" contains a username:password to be used
+    // (and no username,password pair was supplied separately):
+    if (username == NULL && password == NULL
+	&& parseRTSPURLUsernamePassword(url, username, password)) {
+      Authenticator newAuthenticator(username,password);
+      result = sendOptionsCmd(url, username, password, &newAuthenticator, timeout);
+      delete[] username; delete[] password; // they were dynamically allocated
+      return result;
+    } else if (username != NULL && password != NULL) {
+      // Use the separately supplied username and password:
+      authenticator = new Authenticator(username,password);
+      haveAllocatedAuthenticator = True;
+      
+      result = sendOptionsCmd(url, username, password, authenticator, timeout);
+      if (result != NULL) { // We are already authorized
+	delete authenticator;
+	return result;
+      }
+
+      // The "realm" field should have been filled in:
+      if (authenticator->realm() == NULL) {
+	// We haven't been given enough information to try again, so fail:
+	delete authenticator;
+	return NULL;
+      }
+    }
+  }
+
+  setBaseURL(url);
+  fWatchVariableForSyncInterface = 0;
+  fTimeoutTask = NULL;  // by default, unless:
+  if (timeout > 0) {
+    // Schedule a task to be called when the specified timeout interval expires.
+    // Note that we do this *before* attempting to send the RTSP command, in case this attempt fails immediately, calling the
+    // command response handler - because we want the response handler to unschedule any pending timeout handler.
+    fTimeoutTask = envir().taskScheduler().scheduleDelayedTask(timeout*1000000, timeoutHandlerForSyncInterface, this);
+  }
+  (void)sendOptionsCommand(responseHandlerForSyncInterface, authenticator);
+  if (haveAllocatedAuthenticator) delete authenticator;
+
+  // Now block (but handling events) until we get a response (or a timeout):
+  envir().taskScheduler().doEventLoop(&fWatchVariableForSyncInterface);
+  if (fResultCode == 0) return fResultString; // success
+  delete[] fResultString;
+  return NULL;
+}
+
+Boolean RTSPClient::announceSDPDescription(char const* url,
+					   char const* sdpDescription,
+					   Authenticator* authenticator,
+					   int timeout) {
+  setBaseURL(url);
+  fWatchVariableForSyncInterface = 0;
+  fTimeoutTask = NULL;  // by default, unless:
+  if (timeout > 0) {
+    // Schedule a task to be called when the specified timeout interval expires.
+    // Note that we do this *before* attempting to send the RTSP command, in case this attempt fails immediately, calling the
+    // command response handler - because we want the response handler to unschedule any pending timeout handler.
+    fTimeoutTask = envir().taskScheduler().scheduleDelayedTask(timeout*1000000, timeoutHandlerForSyncInterface, this);
+  }
+  (void)sendAnnounceCommand(sdpDescription, responseHandlerForSyncInterface, authenticator);
+
+  // Now block (but handling events) until we get a response (or a timeout):
+  envir().taskScheduler().doEventLoop(&fWatchVariableForSyncInterface);
+  delete[] fResultString;
+  return fResultCode == 0;
+}
+
+Boolean RTSPClient
+::announceWithPassword(char const* url, char const* sdpDescription,
+		       char const* username, char const* password, int timeout) {
+  Authenticator authenticator(username,password);
+  return announceSDPDescription(url, sdpDescription, &authenticator, timeout);
+}
+
+Boolean RTSPClient::setupMediaSubsession(MediaSubsession& subsession,
+					 Boolean streamOutgoing,
+					 Boolean streamUsingTCP,
+					 Boolean forceMulticastOnUnspecified) {
+  fWatchVariableForSyncInterface = 0;
+  fTimeoutTask = NULL;
+  (void)sendSetupCommand(subsession, responseHandlerForSyncInterface, streamOutgoing, streamUsingTCP, forceMulticastOnUnspecified);
+
+  // Now block (but handling events) until we get a response (or a timeout):
+  envir().taskScheduler().doEventLoop(&fWatchVariableForSyncInterface);
+  delete[] fResultString;
+  return fResultCode == 0;
+}
+
+Boolean RTSPClient::playMediaSession(MediaSession& session,
+				     double start, double end, float scale) {
+  fWatchVariableForSyncInterface = 0;
+  fTimeoutTask = NULL;
+  (void)sendPlayCommand(session, responseHandlerForSyncInterface, start, end, scale);
+
+  // Now block (but handling events) until we get a response (or a timeout):
+  envir().taskScheduler().doEventLoop(&fWatchVariableForSyncInterface);
+  delete[] fResultString;
+  return fResultCode == 0;
+}
+
+Boolean RTSPClient::playMediaSubsession(MediaSubsession& subsession,
+					double start, double end, float scale,
+					Boolean /*hackForDSS*/) {
+  // NOTE: The "hackForDSS" flag is no longer supported.  (However, we will consider resupporting it
+  // if we get reports that it is still needed.)
+  fWatchVariableForSyncInterface = 0;
+  fTimeoutTask = NULL;
+  (void)sendPlayCommand(subsession, responseHandlerForSyncInterface, start, end, scale);
+
+  // Now block (but handling events) until we get a response (or a timeout):
+  envir().taskScheduler().doEventLoop(&fWatchVariableForSyncInterface);
+  delete[] fResultString;
+  return fResultCode == 0;
+}
+
+Boolean RTSPClient::pauseMediaSession(MediaSession& session) {
+  fWatchVariableForSyncInterface = 0;
+  fTimeoutTask = NULL;
+  (void)sendPauseCommand(session, responseHandlerForSyncInterface);
+
+  // Now block (but handling events) until we get a response (or a timeout):
+  envir().taskScheduler().doEventLoop(&fWatchVariableForSyncInterface);
+  delete[] fResultString;
+  return fResultCode == 0;
+}
+
+Boolean RTSPClient::pauseMediaSubsession(MediaSubsession& subsession) {
+  fWatchVariableForSyncInterface = 0;
+  fTimeoutTask = NULL;
+  (void)sendPauseCommand(subsession, responseHandlerForSyncInterface);
+
+  // Now block (but handling events) until we get a response (or a timeout):
+  envir().taskScheduler().doEventLoop(&fWatchVariableForSyncInterface);
+  delete[] fResultString;
+  return fResultCode == 0;
+}
+
+Boolean RTSPClient::recordMediaSubsession(MediaSubsession& subsession) {
+  fWatchVariableForSyncInterface = 0;
+  fTimeoutTask = NULL;
+  (void)sendRecordCommand(subsession, responseHandlerForSyncInterface);
+
+  // Now block (but handling events) until we get a response (or a timeout):
+  envir().taskScheduler().doEventLoop(&fWatchVariableForSyncInterface);
+  delete[] fResultString;
+  return fResultCode == 0;
+}
+
+Boolean RTSPClient::setMediaSessionParameter(MediaSession& session,
+					     char const* parameterName,
+					     char const* parameterValue) {
+  fWatchVariableForSyncInterface = 0;
+  fTimeoutTask = NULL;
+  (void)sendSetParameterCommand(session, responseHandlerForSyncInterface, parameterName, parameterValue);
+
+  // Now block (but handling events) until we get a response (or a timeout):
+  envir().taskScheduler().doEventLoop(&fWatchVariableForSyncInterface);
+  delete[] fResultString;
+  return fResultCode == 0;
+}
+
+Boolean RTSPClient::getMediaSessionParameter(MediaSession& session,
+					     char const* parameterName,
+					     char*& parameterValue) {
+  fWatchVariableForSyncInterface = 0;
+  fTimeoutTask = NULL;
+  (void)sendGetParameterCommand(session, responseHandlerForSyncInterface, parameterName);
+
+  // Now block (but handling events) until we get a response (or a timeout):
+  envir().taskScheduler().doEventLoop(&fWatchVariableForSyncInterface);
+  parameterValue = fResultString;
+  return fResultCode == 0;
+}
+
+Boolean RTSPClient::teardownMediaSession(MediaSession& session) {
+  fWatchVariableForSyncInterface = 0;
+  fTimeoutTask = NULL;
+  (void)sendTeardownCommand(session, NULL);
+  return True; // we don't wait for a response to the "TEARDOWN"
+}
+
+Boolean RTSPClient::teardownMediaSubsession(MediaSubsession& subsession) {
+  fWatchVariableForSyncInterface = 0;
+  fTimeoutTask = NULL;
+  (void)sendTeardownCommand(subsession, NULL);
+  return True; // we don't wait for a response to the "TEARDOWN"
+}
+
+Boolean RTSPClient::parseRTSPURLUsernamePassword(char const* url,
+						 char*& username,
+						 char*& password) {
+  username = password = NULL; // by default
+  do {
+    // Parse the URL as "rtsp://<username>[:<password>]@<whatever>"
+    char const* prefix = "rtsp://";
+    unsigned const prefixLength = 7;
+    if (_strncasecmp(url, prefix, prefixLength) != 0) break;
+
+    // Look for the ':' and '@':
+    unsigned usernameIndex = prefixLength;
+    unsigned colonIndex = 0, atIndex = 0;
+    for (unsigned i = usernameIndex; url[i] != '\0' && url[i] != '/'; ++i) {
+      if (url[i] == ':' && colonIndex == 0) {
+	colonIndex = i;
+      } else if (url[i] == '@') {
+	atIndex = i;
+	break; // we're done
+      }
+    }
+    if (atIndex == 0) break; // no '@' found
+
+    char* urlCopy = strDup(url);
+    urlCopy[atIndex] = '\0';
+    if (colonIndex > 0) {
+      urlCopy[colonIndex] = '\0';
+      password = strDup(&urlCopy[colonIndex+1]);
+    } else {
+      password = strDup("");
+    }
+    username = strDup(&urlCopy[usernameIndex]);
+    delete[] urlCopy;
+
+    return True;
+  } while (0);
+
+  return False;
+}
+
+void RTSPClient::responseHandlerForSyncInterface(RTSPClient* rtspClient, int responseCode, char* responseString) {
+  if (rtspClient != NULL) rtspClient->responseHandlerForSyncInterface1(responseCode, responseString);
+}
+
+void RTSPClient::responseHandlerForSyncInterface1(int responseCode, char* responseString) {
+  // If we have a 'timeout task' pending, then unschedule it:
+  if (fTimeoutTask != NULL) envir().taskScheduler().unscheduleDelayedTask(fTimeoutTask);
+
+  // Set result values:
+  fResultCode = responseCode;
+  fResultString = responseString;
+
+  // Signal a break from the event loop (thereby returning from the blocking command):
+  fWatchVariableForSyncInterface = ~0;
+}
+
+void RTSPClient::timeoutHandlerForSyncInterface(void* rtspClient) {
+  if (rtspClient != NULL) ((RTSPClient*)rtspClient)->timeoutHandlerForSyncInterface1();
+}
+
+void RTSPClient::timeoutHandlerForSyncInterface1() {
+  // A RTSP command has timed out, so we should have a queued request record.  Disable it by setting its response handler to NULL.
+  // (Because this is a synchronous interface, there should be exactly one pending response handler - for "fCSeq".)
+  // all of them.)
+  changeResponseHandler(fCSeq, NULL);
+  fTimeoutTask = NULL;
+
+  // Fill in 'negative' return values:
+  fResultCode = ~0;
+  fResultString = NULL;
+
+  // Signal a break from the event loop (thereby returning from the blocking command):
+  fWatchVariableForSyncInterface = ~0;
+}
+
+#endif
 
 
 ////////// HandlerServerForREGISTERCommand implementation /////////