Add SetMaxMessageSize and GetMaxMessageSize methods. r?jesup draft
authorLennart Grahl <lennart.grahl@gmail.com>
Thu, 20 Jul 2017 23:07:21 +0200
changeset 612595 bc31498b62339fc061261b3d284063286429051d
parent 612594 082a983aa2b0cfbdfe6f061daea7537c5fbadae9
child 638452 bdb3945c18485d7fc353b61e1daea802913e3a4d
push id69545
push userbmo:lennart.grahl@gmail.com
push dateThu, 20 Jul 2017 21:12:46 +0000
reviewersjesup
milestone56.0a1
Add SetMaxMessageSize and GetMaxMessageSize methods. r?jesup * Add SetMaxMessageSize method for late-applying those signalling parameters when a data channel has been created before the remote SDP was available. * Limit remote maximum message size and add a GetMaxMessageSize method for a future implementation of RTCSctpTransport.maxMessageSize. MozReview-Commit-ID: JofnMeGfJEq
media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
netwerk/sctp/datachannel/DataChannel.cpp
netwerk/sctp/datachannel/DataChannel.h
netwerk/sctp/datachannel/DataChannelProtocol.h
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -1090,19 +1090,17 @@ PeerConnectionImpl::EnsureDataConnection
                                          uint16_t aNumstreams,
                                          uint32_t aMaxMessageSize,
                                          bool aMMSSet)
 {
   PC_AUTO_ENTER_API_CALL(false);
 
   if (mDataConnection) {
     CSFLogDebug(logTag,"%s DataConnection already connected",__FUNCTION__);
-    // Ignore the request to connect when already connected.  This entire
-    // implementation is temporary.  Ignore aNumstreams as it's merely advisory
-    // and we increase the number of streams dynamically as needed.
+    mDataConnection->SetMaxMessageSize(aMMSSet, aMaxMessageSize);
     return NS_OK;
   }
 
   nsCOMPtr<nsIEventTarget> target = mWindow
       ? mWindow->EventTargetFor(TaskCategory::Other)
       : nullptr;
   mDataConnection = new DataChannelConnection(this, target);
   if (!mDataConnection->Init(aLocalPort, aNumstreams, aMMSSet, aMaxMessageSize)) {
--- a/netwerk/sctp/datachannel/DataChannel.cpp
+++ b/netwerk/sctp/datachannel/DataChannel.cpp
@@ -346,51 +346,24 @@ DataChannelConnection::Init(unsigned sho
                             SCTP_SHUTDOWN_EVENT,
                             SCTP_ADAPTATION_INDICATION,
                             SCTP_PARTIAL_DELIVERY_EVENT,
                             SCTP_SEND_FAILED_EVENT,
                             SCTP_STREAM_RESET_EVENT,
                             SCTP_STREAM_CHANGE_EVENT};
   {
     ASSERT_WEBRTC(NS_IsMainThread());
+    // MutexAutoLock lock(mLock); Not needed since we're on mainthread always
+
     mSendInterleaved = false;
     mPpidFragmentation = false;
-    mMaxMessageSizeSet = aMaxMessageSizeSet;
-    mMaxMessageSize = aMaxMessageSize;
-
-    nsresult rv;
-    nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1", &rv);
-    if (!NS_WARN_IF(NS_FAILED(rv))) {
-      nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs);
-
-      if (branch) {
-        if (!NS_FAILED(branch->GetBoolPref(
-            "media.peerconnection.sctp.force_ppid_fragmentation", &mPpidFragmentation))) {
-          // Ensure that forced on/off PPID fragmentation does not get overridden when Firefox has
-          // been detected.
-          mMaxMessageSizeSet = true;
-        }
-
-        int32_t temp;
-        if (!NS_FAILED(branch->GetIntPref(
-            "media.peerconnection.sctp.force_maximum_message_size", &temp))) {
-           if (temp >= 0) {
-             mMaxMessageSize = (uint64_t)temp;
-           }
-        }
-      }
-    }
-
-    LOG(("Use PPID-based fragmentation/reassembly: %s", mPpidFragmentation ? "yes" : "no"));
-    LOG(("Maximum message size (outgoing data): %" PRIu64 " (set=%s)",
-         mMaxMessageSize, mMaxMessageSizeSet ? "yes" : "no"));
-
-    // MutexAutoLock lock(mLock); Not needed since we're on mainthread always
+    SetMaxMessageSize(aMaxMessageSizeSet, aMaxMessageSize);
+
     if (!sctp_initialized) {
-      LOG(("sctp_init(DTLS)"));
+      LOG(("sctp_init"));
 #ifdef MOZ_PEERCONNECTION
       usrsctp_init(0,
                    DataChannelConnection::SctpDtlsOutput,
                    debug_printf
                   );
 #else
       MOZ_CRASH("Trying to use SCTP/DTLS without mtransport");
 #endif
@@ -537,16 +510,72 @@ DataChannelConnection::Init(unsigned sho
   return true;
 
 error_cleanup:
   usrsctp_close(mMasterSocket);
   mMasterSocket = nullptr;
   return false;
 }
 
+void
+DataChannelConnection::SetMaxMessageSize(bool aMaxMessageSizeSet, uint64_t aMaxMessageSize)
+{
+  MutexAutoLock lock(mLock); // TODO: Needed?
+
+  mMaxMessageSizeSet = aMaxMessageSizeSet;
+  mMaxMessageSize = aMaxMessageSize;
+
+  bool ppidFragmentationEnforced = false;
+  nsresult rv;
+  nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1", &rv);
+  if (!NS_WARN_IF(NS_FAILED(rv))) {
+    nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs);
+
+    if (branch) {
+      if (!NS_FAILED(branch->GetBoolPref(
+          "media.peerconnection.sctp.force_ppid_fragmentation", &mPpidFragmentation))) {
+        // Ensure that forced on/off PPID fragmentation does not get overridden when Firefox has
+        // been detected.
+        mMaxMessageSizeSet = true;
+        ppidFragmentationEnforced = true;
+      }
+
+      int32_t temp;
+      if (!NS_FAILED(branch->GetIntPref(
+          "media.peerconnection.sctp.force_maximum_message_size", &temp))) {
+        if (temp >= 0) {
+          mMaxMessageSize = (uint64_t)temp;
+        }
+      }
+    }
+  }
+
+  // Fix remote MMS. This code exists, so future implementations of RTCSctpTransport.maxMessageSize
+  // can simply provide that value from GetMaxMessageSize.
+
+  // TODO: Bug 1382779, once resolved, can be increased to min(Uint8ArrayMaxSize, UINT32_MAX)
+  // TODO: Bug 1381146, once resolved, can be increased to whatever we support then (hopefully
+  //       SIZE_MAX)
+  if (mMaxMessageSize == 0 || mMaxMessageSize > WEBRTC_DATACHANNEL_MAX_MESSAGE_SIZE_REMOTE) {
+    mMaxMessageSize = WEBRTC_DATACHANNEL_MAX_MESSAGE_SIZE_REMOTE;
+  }
+
+  LOG(("Use PPID-based fragmentation/reassembly: %s (enforced=%s)",
+       mPpidFragmentation ? "yes" : "no", ppidFragmentationEnforced ? "yes" : "no"));
+  LOG(("Maximum message size (outgoing data): %" PRIu64 " (set=%s, enforced=%s)",
+       mMaxMessageSize, mMaxMessageSizeSet ? "yes" : "no",
+       aMaxMessageSize != mMaxMessageSize ? "yes" : "no"));
+}
+
+uint64_t
+DataChannelConnection::GetMaxMessageSize()
+{
+  return mMaxMessageSize;
+}
+
 #ifdef MOZ_PEERCONNECTION
 void
 DataChannelConnection::SetEvenOdd()
 {
   ASSERT_WEBRTC(IsSTSThread());
 
   TransportLayerDtls *dtls = static_cast<TransportLayerDtls *>(
       mTransportFlow->GetLayer(TransportLayerDtls::ID()));
@@ -1708,17 +1737,17 @@ DataChannelConnection::HandleAssociation
     break;
   }
   LOG(("Association change: streams (in/out) = (%u/%u)",
        sac->sac_inbound_streams, sac->sac_outbound_streams));
 
   if (NS_WARN_IF(!sac)) {
     return;
   }
-  
+
   n = sac->sac_length - sizeof(*sac);
   if ((sac->sac_state == SCTP_COMM_UP) || (sac->sac_state == SCTP_RESTART)) {
     if (n > 0) {
       for (i = 0; i < n; ++i) {
         switch (sac->sac_info[i]) {
         case SCTP_ASSOC_SUPPORTS_PR:
           LOG(("Supports: PR"));
           break;
--- a/netwerk/sctp/datachannel/DataChannel.h
+++ b/netwerk/sctp/datachannel/DataChannel.h
@@ -140,21 +140,25 @@ public:
     virtual void NotifyDataChannel(already_AddRefed<DataChannel> channel) = 0;
   };
 
   explicit DataChannelConnection(DataConnectionListener *listener,
                                  nsIEventTarget *aTarget);
 
   bool Init(unsigned short aPort, uint16_t aNumStreams, bool aMaxMessageSizeSet,
             uint64_t aMaxMessageSize);
+
   void Destroy(); // So we can spawn refs tied to runnables in shutdown
   // Finish Destroy on STS to avoid SCTP race condition with ABORT from far end
   void DestroyOnSTS(struct socket *aMasterSocket,
                     struct socket *aSocket);
 
+  void SetMaxMessageSize(bool aMaxMessageSizeSet, uint64_t aMaxMessageSize);
+  uint64_t GetMaxMessageSize();
+
 #ifdef ALLOW_DIRECT_SCTP_LISTEN_CONNECT
   // These block; they require something to decide on listener/connector
   // (though you can do simultaneous Connect()).  Do not call these from
   // the main thread!
   bool Listen(unsigned short port);
   bool Connect(const char *addr, unsigned short port);
 #endif
 
--- a/netwerk/sctp/datachannel/DataChannelProtocol.h
+++ b/netwerk/sctp/datachannel/DataChannelProtocol.h
@@ -18,16 +18,20 @@
 
 #define WEBRTC_DATACHANNEL_STREAMS_DEFAULT                 256
 // Do not change this value!
 #define WEBRTC_DATACHANNEL_STREAMS_OLDER_FIREFOX           256
 #define WEBRTC_DATACHANNEL_PORT_DEFAULT                    5000
 // TODO: Bug 1381146, change once we resolve the nsCString limitation
 #define WEBRTC_DATACHANNEL_MAX_MESSAGE_SIZE_LOCAL          1073741823
 #define WEBRTC_DATACHANNEL_MAX_MESSAGE_SIZE_REMOTE_DEFAULT 65535
+// TODO: Bug 1382779, once resolved, can be increased to min(Uint8ArrayMaxSize, UINT32_MAX)
+// TODO: Bug 1381146, once resolved, can be increased to whatever we support then (hopefully
+//       SIZE_MAX) or be removed
+#define WEBRTC_DATACHANNEL_MAX_MESSAGE_SIZE_REMOTE         2147483637
 
 #define DATA_CHANNEL_PPID_CONTROL           50
 #define DATA_CHANNEL_PPID_BINARY_PARTIAL    52
 #define DATA_CHANNEL_PPID_BINARY            53
 #define DATA_CHANNEL_PPID_DOMSTRING_PARTIAL 54
 #define DATA_CHANNEL_PPID_DOMSTRING         51
 
 #define DATA_CHANNEL_MAX_BINARY_FRAGMENT 0x4000
@@ -44,17 +48,17 @@
 #define DATA_CHANNEL_BUFFER_MESSAGE_FLAGS_COMPLETE  0x04
 
 #define INVALID_STREAM (0xFFFF)
 // max is 0xFFFF: Streams 0 to 0xFFFE = 0xFFFF streams
 #define MAX_NUM_STREAMS (2048)
 
 struct rtcweb_datachannel_open_request {
   uint8_t  msg_type; // DATA_CHANNEL_OPEN
-  uint8_t  channel_type;  
+  uint8_t  channel_type;
   int16_t  priority;
   uint32_t reliability_param;
   uint16_t label_length;
   uint16_t protocol_length;
   char     label[1]; // (and protocol) keep VC++ happy...
 } SCTP_PACKED;
 
 struct rtcweb_datachannel_ack {