Bug 806169: proxy all SendPackets to the STS thread r=ekr
authorRandell Jesup <rjesup@jesup.org>
Sun, 28 Oct 2012 23:48:36 -0400
changeset 111769 e069342dc6658bdd2d806a70a3b832e4868b927b
parent 111768 76a12989a99c165d42309696afc99a3d92a8c2aa
child 111770 3a7226d6429b88fc2fd5c09ef31394f38ef96dcf
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersekr
bugs806169
milestone19.0a1
Bug 806169: proxy all SendPackets to the STS thread r=ekr
netwerk/sctp/datachannel/DataChannel.cpp
netwerk/sctp/datachannel/DataChannel.h
--- a/netwerk/sctp/datachannel/DataChannel.cpp
+++ b/netwerk/sctp/datachannel/DataChannel.cpp
@@ -185,16 +185,22 @@ DataChannelConnection::Init(unsigned sho
       usrsctp_sysctl_set_sctp_debug_on(0 /* SCTP_DEBUG_ALL */);
       usrsctp_sysctl_set_sctp_blackhole(2);
       sctp_initialized = true;
 
       gDataChannelShutdown = new DataChannelShutdown();
       gDataChannelShutdown->Init();
     }
   }
+  // XXX FIX! make this a global we get once
+  // Find the STS thread
+
+  nsresult res;
+  mSTS = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &res);
+  MOZ_ASSERT(NS_SUCCEEDED(res));
 
   // Open sctp association across tunnel
   if ((mMasterSocket = usrsctp_socket(
          aUsingDtls ? AF_CONN : AF_INET,
          SOCK_STREAM, IPPROTO_SCTP, receive_cb, nullptr, 0, this)) == nullptr) {
     return false;
   }
 
@@ -389,32 +395,44 @@ DataChannelConnection::PacketReceived(Tr
                                       const unsigned char *data, size_t len)
 {
   //LOG(("%p: SCTP/DTLS received %ld bytes", this, len));
 
   // Pass the data to SCTP
   usrsctp_conninput(static_cast<void *>(this), data, len, 0);
 }
 
-// XXX Merge with SctpDtlsOutput?
 int
 DataChannelConnection::SendPacket(const unsigned char *data, size_t len)
 {
   //LOG(("%p: SCTP/DTLS sent %ld bytes", this, len));
   return mTransportFlow->SendPacket(data, len) < 0 ? 1 : 0;
 }
 
 /* static */
 int
 DataChannelConnection::SctpDtlsOutput(void *addr, void *buffer, size_t length,
                                       uint8_t tos, uint8_t set_df)
 {
   DataChannelConnection *peer = static_cast<DataChannelConnection *>(addr);
+  int res;
 
-  return peer->SendPacket(static_cast<unsigned char *>(buffer), length);
+  if (peer->IsSTSThread()) {
+    res = peer->SendPacket(static_cast<unsigned char *>(buffer), length);
+  } else {
+    res = -1;
+    // XXX It might be worthwhile to add an assertion against the thread
+    // somehow getting into the DataChannel/SCTP code again, as
+    // DISPATCH_SYNC is not fully blocking.  This may be tricky, as it
+    // needs to be a per-thread check, not a global.
+    peer->mSTS->Dispatch(WrapRunnableRet(
+      peer, &DataChannelConnection::SendPacket, static_cast<unsigned char *>(buffer), length, &res
+    ), NS_DISPATCH_SYNC);
+  }
+  return res;
 }
 #endif
 
 // listen for incoming associations
 // Blocks! - Don't call this from main thread!
 bool
 DataChannelConnection::Listen(unsigned short port)
 {
--- a/netwerk/sctp/datachannel/DataChannel.h
+++ b/netwerk/sctp/datachannel/DataChannel.h
@@ -211,31 +211,42 @@ private:
   void HandleRemoteErrorEvent(const struct sctp_remote_error *sre);
   void HandleShutdownEvent(const struct sctp_shutdown_event *sse);
   void HandleAdaptationIndication(const struct sctp_adaptation_event *sai);
   void HandleSendFailedEvent(const struct sctp_send_failed_event *ssfe);
   void HandleStreamResetEvent(const struct sctp_stream_reset_event *strrst);
   void HandleStreamChangeEvent(const struct sctp_stream_change_event *strchg);
   void HandleNotification(const union sctp_notification *notif, size_t n);
 
+#ifdef SCTP_DTLS_SUPPORTED
+  bool IsSTSThread() {
+    bool on = false;
+    if (mSTS) {
+      mSTS->IsOnCurrentThread(&on);
+    }
+    return on;
+  }
+#endif
+
   // NOTE: while these arrays will auto-expand, increases in the number of
   // channels available from the stack must be negotiated!
   nsAutoTArray<DataChannel*,16> mStreamsOut;
   nsAutoTArray<DataChannel*,16> mStreamsIn;
   nsDeque mPending; // Holds DataChannels
 
   // Streams pending reset
   nsAutoTArray<uint16_t,4> mStreamsResetting;
 
   struct socket *mMasterSocket;
   struct socket *mSocket;
   uint16_t mState;
 
 #ifdef SCTP_DTLS_SUPPORTED
   nsRefPtr<TransportFlow> mTransportFlow;
+  nsCOMPtr<nsIEventTarget> mSTS;
 #endif
   uint16_t mLocalPort;
   uint16_t mRemotePort;
 
   // Timer to control when we try to resend blocked messages
   nsCOMPtr<nsITimer> mDeferredTimer;
   uint32_t mDeferTimeout; // in ms
   bool mTimerRunning;