Bug 837523 - Additional checks for unsupported app behavior r=ehugg
authorAdam Roach [:abr] <adam@nostrum.com>
Tue, 26 Feb 2013 08:26:29 -0600
changeset 123018 9cbb040ed6da24a209666df1a96ccb6c1d1a41bf
parent 123017 bf6ef4772884397681a98b82a99004afa7982e14
child 123019 7bdc94c723f30754739a793af634686d4cf1a80e
push id24372
push useremorley@mozilla.com
push dateWed, 27 Feb 2013 13:22:59 +0000
treeherdermozilla-central@0a91da5f5eab [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehugg
bugs837523
milestone22.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 837523 - Additional checks for unsupported app behavior r=ehugg
media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
media/webrtc/signaling/src/sipcc/core/gsm/fsmdef.c
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -234,17 +234,19 @@ PeerConnectionImpl::PeerConnectionImpl()
 : mRole(kRoleUnknown)
   , mCall(NULL)
   , mReadyState(kNew)
   , mIceState(kIceGathering)
   , mPCObserver(NULL)
   , mWindow(NULL)
   , mIdentity(NULL)
   , mSTSThread(NULL)
-  , mMedia(new PeerConnectionMedia(this)) {
+  , mMedia(new PeerConnectionMedia(this))
+  , mNumAudioStreams(0)
+  , mNumVideoStreams(0) {
 #ifdef MOZILLA_INTERNAL_API
   MOZ_ASSERT(NS_IsMainThread());
 #endif
 }
 
 PeerConnectionImpl::~PeerConnectionImpl()
 {
   // This aborts if not on main thread (in Debug builds)
@@ -954,31 +956,58 @@ PeerConnectionImpl::CloseStreams() {
   mCall->endCall();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 PeerConnectionImpl::AddStream(nsIDOMMediaStream* aMediaStream) {
   PC_AUTO_ENTER_API_CALL(true);
 
+  if (!aMediaStream) {
+    CSFLogError(logTag, "%s: Attempt to add null stream",__FUNCTION__);
+    return NS_ERROR_FAILURE;
+  }
+
+  DOMMediaStream* stream = static_cast<DOMMediaStream*>(aMediaStream);
+  uint32_t hints = stream->GetHintContents();
+
+  // XXX Remove this check once addStream has an error callback
+  // available and/or we have plumbing to handle multiple
+  // local audio streams.
+  if ((hints & DOMMediaStream::HINT_CONTENTS_AUDIO) &&
+      mNumAudioStreams > 0) {
+    CSFLogError(logTag, "%s: Only one local audio stream is supported for now",
+                __FUNCTION__);
+    return NS_ERROR_FAILURE;
+  }
+
+  // XXX Remove this check once addStream has an error callback
+  // available and/or we have plumbing to handle multiple
+  // local video streams.
+  if ((hints & DOMMediaStream::HINT_CONTENTS_VIDEO) &&
+      mNumVideoStreams > 0) {
+    CSFLogError(logTag, "%s: Only one local video stream is supported for now",
+                __FUNCTION__);
+    return NS_ERROR_FAILURE;
+  }
+
   uint32_t stream_id;
   nsresult res = mMedia->AddStream(aMediaStream, &stream_id);
   if (NS_FAILED(res))
     return res;
 
-  DOMMediaStream* stream = static_cast<DOMMediaStream*>(aMediaStream);
-  uint32_t hints = stream->GetHintContents();
-
   // TODO(ekr@rtfm.com): these integers should be the track IDs
   if (hints & DOMMediaStream::HINT_CONTENTS_AUDIO) {
     mCall->addStream(stream_id, 0, AUDIO);
+    mNumAudioStreams++;
   }
 
   if (hints & DOMMediaStream::HINT_CONTENTS_VIDEO) {
     mCall->addStream(stream_id, 1, VIDEO);
+    mNumVideoStreams++;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 PeerConnectionImpl::RemoveStream(nsIDOMMediaStream* aMediaStream) {
   PC_AUTO_ENTER_API_CALL(true);
@@ -989,20 +1018,24 @@ PeerConnectionImpl::RemoveStream(nsIDOMM
   if (NS_FAILED(res))
     return res;
 
   DOMMediaStream* stream = static_cast<DOMMediaStream*>(aMediaStream);
   uint32_t hints = stream->GetHintContents();
 
   if (hints & DOMMediaStream::HINT_CONTENTS_AUDIO) {
     mCall->removeStream(stream_id, 0, AUDIO);
+    MOZ_ASSERT(mNumAudioStreams > 0);
+    mNumAudioStreams--;
   }
 
   if (hints & DOMMediaStream::HINT_CONTENTS_VIDEO) {
     mCall->removeStream(stream_id, 1, VIDEO);
+    MOZ_ASSERT(mNumVideoStreams > 0);
+    mNumVideoStreams--;
   }
 
   return NS_OK;
 }
 
 /*
 NS_IMETHODIMP
 PeerConnectionImpl::SetRemoteFingerprint(const char* hash, const char* fingerprint)
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
@@ -301,16 +301,23 @@ private:
 
 #ifdef MOZILLA_INTERNAL_API
   // DataConnection that's used to get all the DataChannels
 	nsRefPtr<mozilla::DataChannelConnection> mDataConnection;
 #endif
 
   nsRefPtr<PeerConnectionMedia> mMedia;
 
+  // Temporary: used to prevent multiple audio streams or multiple video streams
+  // in a single PC. This is tied up in the IETF discussion around proper
+  // representation of multiple streams in SDP, and strongly related to
+  // Bug 840728.
+  int mNumAudioStreams;
+  int mNumVideoStreams;
+
 public:
   //these are temporary until the DataChannel Listen/Connect API is removed
   unsigned short listenPort;
   unsigned short connectPort;
   char *connectStr; // XXX ownership/free
 };
 
 // This is what is returned when you acquire on a handle
--- a/media/webrtc/signaling/src/sipcc/core/gsm/fsmdef.c
+++ b/media/webrtc/signaling/src/sipcc/core/gsm/fsmdef.c
@@ -3296,16 +3296,29 @@ fsmdef_ev_setremotedesc(sm_event_t *even
     config_get_value(CFGID_SDPMODE, &sdpmode, sizeof(sdpmode));
     if (!sdpmode) {
         ui_set_remote_description(evSetRemoteDescError, line, call_id,
             dcb->caller_id.call_instance_id, strlib_empty(),
             PC_SETREMOTEDESCERROR);
         return (SM_RC_END);
     }
 
+    // XXX We don't currently support renegotiation. If the remote SDP
+    // has already been set, return an error to the application. This is
+    // temporary until Bug 840728 is implemented.
+    if (dcb->sdp && dcb->sdp->dest_sdp) {
+        FSM_DEBUG_SM(DEB_F_PREFIX"Renegotiation not currently supported.\n",
+                     DEB_F_PREFIX_ARGS(FSM, __FUNCTION__));
+        ui_set_remote_description(evSetRemoteDescError, line, call_id,
+            dcb->caller_id.call_instance_id, strlib_empty(),
+            PC_SETREMOTEDESCERROR);
+        return (SM_RC_END);
+    }
+
+
     if (dcb == NULL) {
         FSM_DEBUG_SM(DEB_F_PREFIX"dcb is NULL.\n", DEB_F_PREFIX_ARGS(FSM, __FUNCTION__));
         return SM_RC_CLEANUP;
     }
 
     cc_initialize_msg_body_parts_info(&msg_body);
 
     /* !!! NOTE !!! The following code sets up the pointers inside