LCOV - code coverage report
Current view: top level - netwerk/sctp/datachannel - DataChannel.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 105 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 30 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
       5             :  * You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef NETWERK_SCTP_DATACHANNEL_DATACHANNEL_H_
       8             : #define NETWERK_SCTP_DATACHANNEL_DATACHANNEL_H_
       9             : 
      10             : #ifdef MOZ_WEBRTC_SIGNALING
      11             : #define SCTP_DTLS_SUPPORTED 1
      12             : #endif
      13             : 
      14             : #include <string>
      15             : #include <errno.h>
      16             : #include "nsISupports.h"
      17             : #include "nsCOMPtr.h"
      18             : #include "mozilla/WeakPtr.h"
      19             : #include "nsString.h"
      20             : #include "nsThreadUtils.h"
      21             : #include "nsTArray.h"
      22             : #include "nsDeque.h"
      23             : #include "nsIInputStream.h"
      24             : #include "mozilla/Mutex.h"
      25             : #include "DataChannelProtocol.h"
      26             : #include "DataChannelListener.h"
      27             : #include "mozilla/net/NeckoTargetHolder.h"
      28             : #ifdef SCTP_DTLS_SUPPORTED
      29             : #include "mtransport/sigslot.h"
      30             : #include "mtransport/transportflow.h"
      31             : #include "mtransport/transportlayer.h"
      32             : #include "mtransport/transportlayerdtls.h"
      33             : #include "mtransport/transportlayerprsock.h"
      34             : #endif
      35             : 
      36             : #ifndef DATACHANNEL_LOG
      37             : #define DATACHANNEL_LOG(args)
      38             : #endif
      39             : 
      40             : #ifndef EALREADY
      41             : #define EALREADY  WSAEALREADY
      42             : #endif
      43             : 
      44             : extern "C" {
      45             :   struct socket;
      46             :   struct sctp_rcvinfo;
      47             : }
      48             : 
      49             : namespace mozilla {
      50             : 
      51             : class DataChannelConnection;
      52             : class DataChannel;
      53             : class DataChannelOnMessageAvailable;
      54             : 
      55             : // For queuing outgoing messages
      56             : class BufferedMsg
      57             : {
      58             : public:
      59             :   BufferedMsg(struct sctp_sendv_spa &spa,const char *data,
      60             :               size_t length);
      61             :   ~BufferedMsg();
      62             : 
      63             :   struct sctp_sendv_spa *mSpa;
      64             :   const char *mData;
      65             :   size_t mLength;
      66             : };
      67             : 
      68             : // for queuing incoming data messages before the Open or
      69             : // external negotiation is indicated to us
      70             : class QueuedDataMessage
      71             : {
      72             : public:
      73           0 :   QueuedDataMessage(uint16_t stream, uint32_t ppid,
      74             :              const void *data, size_t length)
      75           0 :     : mStream(stream)
      76             :     , mPpid(ppid)
      77           0 :     , mLength(length)
      78             :   {
      79           0 :     mData = static_cast<char *>(moz_xmalloc(length)); // infallible
      80           0 :     memcpy(mData, data, length);
      81           0 :   }
      82             : 
      83           0 :   ~QueuedDataMessage()
      84           0 :   {
      85           0 :     free(mData);
      86           0 :   }
      87             : 
      88             :   uint16_t mStream;
      89             :   uint32_t mPpid;
      90             :   size_t   mLength;
      91             :   char     *mData;
      92             : };
      93             : 
      94             : // One per PeerConnection
      95             : class DataChannelConnection final
      96             :   : public net::NeckoTargetHolder
      97             : #ifdef SCTP_DTLS_SUPPORTED
      98             :   , public sigslot::has_slots<>
      99             : #endif
     100             : {
     101             :   virtual ~DataChannelConnection();
     102             : 
     103             : public:
     104           0 :   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DataChannelConnection)
     105             : 
     106           0 :   class DataConnectionListener : public SupportsWeakPtr<DataConnectionListener>
     107             :   {
     108             :   public:
     109           0 :     MOZ_DECLARE_WEAKREFERENCE_TYPENAME(DataChannelConnection::DataConnectionListener)
     110           0 :     virtual ~DataConnectionListener() {}
     111             : 
     112             :     // Called when a new DataChannel has been opened by the other side.
     113             :     virtual void NotifyDataChannel(already_AddRefed<DataChannel> channel) = 0;
     114             :   };
     115             : 
     116             :   explicit DataChannelConnection(DataConnectionListener *listener,
     117             :                                  nsIEventTarget *aTarget);
     118             : 
     119             :   bool Init(unsigned short aPort, uint16_t aNumStreams, bool aUsingDtls);
     120             :   void Destroy(); // So we can spawn refs tied to runnables in shutdown
     121             :   // Finish Destroy on STS to avoid SCTP race condition with ABORT from far end
     122             :   void DestroyOnSTS(struct socket *aMasterSocket,
     123             :                     struct socket *aSocket);
     124             : 
     125             : #ifdef ALLOW_DIRECT_SCTP_LISTEN_CONNECT
     126             :   // These block; they require something to decide on listener/connector
     127             :   // (though you can do simultaneous Connect()).  Do not call these from
     128             :   // the main thread!
     129             :   bool Listen(unsigned short port);
     130             :   bool Connect(const char *addr, unsigned short port);
     131             : #endif
     132             : 
     133             : #ifdef SCTP_DTLS_SUPPORTED
     134             :   // Connect using a TransportFlow (DTLS) channel
     135             :   void SetEvenOdd();
     136             :   bool ConnectViaTransportFlow(TransportFlow *aFlow, uint16_t localport, uint16_t remoteport);
     137             :   void CompleteConnect(TransportFlow *flow, TransportLayer::State state);
     138             :   void SetSignals();
     139             : #endif
     140             : 
     141             :   typedef enum {
     142             :     RELIABLE=0,
     143             :     PARTIAL_RELIABLE_REXMIT = 1,
     144             :     PARTIAL_RELIABLE_TIMED = 2
     145             :   } Type;
     146             : 
     147             :   MOZ_MUST_USE
     148             :   already_AddRefed<DataChannel> Open(const nsACString& label,
     149             :                                      const nsACString& protocol,
     150             :                                      Type type, bool inOrder,
     151             :                                      uint32_t prValue,
     152             :                                      DataChannelListener *aListener,
     153             :                                      nsISupports *aContext,
     154             :                                      bool aExternalNegotiated,
     155             :                                      uint16_t aStream);
     156             : 
     157             :   void Close(DataChannel *aChannel);
     158             :   // CloseInt() must be called with mLock held
     159             :   void CloseInt(DataChannel *aChannel);
     160             :   void CloseAll();
     161             : 
     162           0 :   int32_t SendMsg(uint16_t stream, const nsACString &aMsg)
     163             :     {
     164           0 :       return SendMsgCommon(stream, aMsg, false);
     165             :     }
     166           0 :   int32_t SendBinaryMsg(uint16_t stream, const nsACString &aMsg)
     167             :     {
     168           0 :       return SendMsgCommon(stream, aMsg, true);
     169             :     }
     170             :   int32_t SendBlob(uint16_t stream, nsIInputStream *aBlob);
     171             : 
     172             :   // Called on data reception from the SCTP library
     173             :   // must(?) be public so my c->c++ trampoline can call it
     174             :   int ReceiveCallback(struct socket* sock, void *data, size_t datalen,
     175             :                       struct sctp_rcvinfo rcv, int32_t flags);
     176             : 
     177             :   // Find out state
     178             :   enum {
     179             :     CONNECTING = 0U,
     180             :     OPEN = 1U,
     181             :     CLOSING = 2U,
     182             :     CLOSED = 3U
     183             :   };
     184             :   uint16_t GetReadyState() { MutexAutoLock lock(mLock); return mState; }
     185             : 
     186             :   friend class DataChannel;
     187             :   Mutex  mLock;
     188             : 
     189             :   void ReadBlob(already_AddRefed<DataChannelConnection> aThis, uint16_t aStream, nsIInputStream* aBlob);
     190             : 
     191             :   void GetStreamIds(std::vector<uint16_t>* aStreamList);
     192             : 
     193             :   bool SendDeferredMessages();
     194             : 
     195             : protected:
     196             :   friend class DataChannelOnMessageAvailable;
     197             :   // Avoid cycles with PeerConnectionImpl
     198             :   // Use from main thread only as WeakPtr is not threadsafe
     199             :   WeakPtr<DataConnectionListener> mListener;
     200             : 
     201             : private:
     202             :   friend class DataChannelConnectRunnable;
     203             : 
     204             : #ifdef SCTP_DTLS_SUPPORTED
     205             :   static void DTLSConnectThread(void *data);
     206             :   int SendPacket(unsigned char data[], size_t len, bool release);
     207             :   void SctpDtlsInput(TransportFlow *flow, const unsigned char *data, size_t len);
     208             :   static int SctpDtlsOutput(void *addr, void *buffer, size_t length, uint8_t tos, uint8_t set_df);
     209             : #endif
     210             :   DataChannel* FindChannelByStream(uint16_t stream);
     211             :   uint16_t FindFreeStream();
     212             :   bool RequestMoreStreams(int32_t aNeeded = 16);
     213             :   int32_t SendControlMessage(void *msg, uint32_t len, uint16_t stream);
     214             :   int32_t SendOpenRequestMessage(const nsACString& label, const nsACString& protocol,
     215             :                                  uint16_t stream,
     216             :                                  bool unordered, uint16_t prPolicy, uint32_t prValue);
     217             :   int32_t SendOpenAckMessage(uint16_t stream);
     218             :   int32_t SendMsgInternal(DataChannel *channel, const char *data,
     219             :                           size_t length, uint32_t ppid);
     220             :   int32_t SendBinary(DataChannel *channel, const char *data,
     221             :                      size_t len, uint32_t ppid_partial, uint32_t ppid_final);
     222             :   int32_t SendMsgCommon(uint16_t stream, const nsACString &aMsg, bool isBinary);
     223             : 
     224             :   void DeliverQueuedData(uint16_t stream);
     225             : 
     226             :   already_AddRefed<DataChannel> OpenFinish(already_AddRefed<DataChannel>&& aChannel);
     227             : 
     228             :   void ProcessQueuedOpens();
     229             :   void ClearResets();
     230             :   void SendOutgoingStreamReset();
     231             :   void ResetOutgoingStream(uint16_t stream);
     232             :   void HandleOpenRequestMessage(const struct rtcweb_datachannel_open_request *req,
     233             :                                 size_t length,
     234             :                                 uint16_t stream);
     235             :   void HandleOpenAckMessage(const struct rtcweb_datachannel_ack *ack,
     236             :                             size_t length, uint16_t stream);
     237             :   void HandleUnknownMessage(uint32_t ppid, size_t length, uint16_t stream);
     238             :   void HandleDataMessage(uint32_t ppid, const void *buffer, size_t length, uint16_t stream);
     239             :   void HandleMessage(const void *buffer, size_t length, uint32_t ppid, uint16_t stream);
     240             :   void HandleAssociationChangeEvent(const struct sctp_assoc_change *sac);
     241             :   void HandlePeerAddressChangeEvent(const struct sctp_paddr_change *spc);
     242             :   void HandleRemoteErrorEvent(const struct sctp_remote_error *sre);
     243             :   void HandleShutdownEvent(const struct sctp_shutdown_event *sse);
     244             :   void HandleAdaptationIndication(const struct sctp_adaptation_event *sai);
     245             :   void HandleSendFailedEvent(const struct sctp_send_failed_event *ssfe);
     246             :   void HandleStreamResetEvent(const struct sctp_stream_reset_event *strrst);
     247             :   void HandleStreamChangeEvent(const struct sctp_stream_change_event *strchg);
     248             :   void HandleNotification(const union sctp_notification *notif, size_t n);
     249             : 
     250             : #ifdef SCTP_DTLS_SUPPORTED
     251           0 :   bool IsSTSThread() {
     252           0 :     bool on = false;
     253           0 :     if (mSTS) {
     254           0 :       mSTS->IsOnCurrentThread(&on);
     255             :     }
     256           0 :     return on;
     257             :   }
     258             : #endif
     259             : 
     260             :   // Exists solely for proxying release of the TransportFlow to the STS thread
     261             :   static void ReleaseTransportFlow(const RefPtr<TransportFlow>& aFlow) {}
     262             : 
     263             :   // Data:
     264             :   // NOTE: while this array will auto-expand, increases in the number of
     265             :   // channels available from the stack must be negotiated!
     266             :   bool mAllocateEven;
     267             :   AutoTArray<RefPtr<DataChannel>,16> mStreams;
     268             :   nsDeque mPending; // Holds addref'ed DataChannel's -- careful!
     269             :   // holds data that's come in before a channel is open
     270             :   nsTArray<nsAutoPtr<QueuedDataMessage>> mQueuedData;
     271             : 
     272             :   // Streams pending reset
     273             :   AutoTArray<uint16_t,4> mStreamsResetting;
     274             : 
     275             :   struct socket *mMasterSocket; // accessed from STS thread
     276             :   struct socket *mSocket; // cloned from mMasterSocket on successful Connect on STS thread
     277             :   uint16_t mState; // Protected with mLock
     278             : 
     279             : #ifdef SCTP_DTLS_SUPPORTED
     280             :   RefPtr<TransportFlow> mTransportFlow;
     281             :   nsCOMPtr<nsIEventTarget> mSTS;
     282             : #endif
     283             :   uint16_t mLocalPort; // Accessed from connect thread
     284             :   uint16_t mRemotePort;
     285             :   bool mUsingDtls;
     286             : 
     287             :   nsCOMPtr<nsIThread> mInternalIOThread;
     288             : };
     289             : 
     290             : #define ENSURE_DATACONNECTION \
     291             :   do { MOZ_ASSERT(mConnection); if (!mConnection) { return; } } while (0)
     292             : 
     293             : #define ENSURE_DATACONNECTION_RET(x) \
     294             :   do { MOZ_ASSERT(mConnection); if (!mConnection) { return (x); } } while (0)
     295             : 
     296             : class DataChannel {
     297             : public:
     298             :   enum {
     299             :     CONNECTING = 0U,
     300             :     OPEN = 1U,
     301             :     CLOSING = 2U,
     302             :     CLOSED = 3U,
     303             :     WAITING_TO_OPEN = 4U
     304             :   };
     305             : 
     306           0 :   DataChannel(DataChannelConnection *connection,
     307             :               uint16_t stream,
     308             :               uint16_t state,
     309             :               const nsACString& label,
     310             :               const nsACString& protocol,
     311             :               uint16_t policy, uint32_t value,
     312             :               uint32_t flags,
     313             :               DataChannelListener *aListener,
     314             :               nsISupports *aContext)
     315           0 :     : mListenerLock("netwerk::sctp::DataChannel")
     316             :     , mListener(aListener)
     317             :     , mContext(aContext)
     318             :     , mConnection(connection)
     319             :     , mLabel(label)
     320             :     , mProtocol(protocol)
     321             :     , mState(state)
     322             :     , mReady(false)
     323             :     , mStream(stream)
     324             :     , mPrPolicy(policy)
     325             :     , mPrValue(value)
     326             :     , mFlags(flags)
     327             :     , mIsRecvBinary(false)
     328             :     , mBufferedThreshold(0) // default from spec
     329           0 :     , mMainThreadEventTarget(connection->GetNeckoTarget())
     330             :     {
     331           0 :       NS_ASSERTION(mConnection,"NULL connection");
     332           0 :     }
     333             : 
     334             : private:
     335             :   ~DataChannel();
     336             : 
     337             : public:
     338           0 :   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DataChannel)
     339             : 
     340             :   // when we disconnect from the connection after stream RESET
     341             :   void StreamClosedLocked();
     342             : 
     343             :   // Complete dropping of the link between DataChannel and the connection.
     344             :   // After this, except for a few methods below listed to be safe, you can't
     345             :   // call into DataChannel.
     346             :   void ReleaseConnection();
     347             : 
     348             :   // Close this DataChannel.  Can be called multiple times.  MUST be called
     349             :   // before destroying the DataChannel (state must be CLOSED or CLOSING).
     350             :   void Close();
     351             : 
     352             :   // Set the listener (especially for channels created from the other side)
     353             :   void SetListener(DataChannelListener *aListener, nsISupports *aContext);
     354             : 
     355             :   // Send a string
     356           0 :   bool SendMsg(const nsACString &aMsg)
     357             :     {
     358           0 :       ENSURE_DATACONNECTION_RET(false);
     359             : 
     360           0 :       if (mStream != INVALID_STREAM)
     361           0 :         return (mConnection->SendMsg(mStream, aMsg) >= 0);
     362             :       else
     363           0 :         return false;
     364             :     }
     365             : 
     366             :   // Send a binary message (TypedArray)
     367           0 :   bool SendBinaryMsg(const nsACString &aMsg)
     368             :     {
     369           0 :       ENSURE_DATACONNECTION_RET(false);
     370             : 
     371           0 :       if (mStream != INVALID_STREAM)
     372           0 :         return (mConnection->SendBinaryMsg(mStream, aMsg) >= 0);
     373             :       else
     374           0 :         return false;
     375             :     }
     376             : 
     377             :   // Send a binary blob
     378           0 :   bool SendBinaryStream(nsIInputStream *aBlob, uint32_t msgLen)
     379             :     {
     380           0 :       ENSURE_DATACONNECTION_RET(false);
     381             : 
     382           0 :       if (mStream != INVALID_STREAM)
     383           0 :         return (mConnection->SendBlob(mStream, aBlob) == 0);
     384             :       else
     385           0 :         return false;
     386             :     }
     387             : 
     388           0 :   uint16_t GetType() { return mPrPolicy; }
     389             : 
     390           0 :   bool GetOrdered() { return !(mFlags & DATA_CHANNEL_FLAGS_OUT_OF_ORDER_ALLOWED); }
     391             : 
     392             :   // Amount of data buffered to send
     393           0 :   uint32_t GetBufferedAmount()
     394             :   {
     395           0 :     if (!mConnection) {
     396           0 :       return 0;
     397             :     }
     398             : 
     399           0 :     MutexAutoLock lock(mConnection->mLock);
     400           0 :     return GetBufferedAmountLocked();
     401             :   }
     402             : 
     403             : 
     404             :   // Trigger amount for generating BufferedAmountLow events
     405             :   uint32_t GetBufferedAmountLowThreshold();
     406             :   void SetBufferedAmountLowThreshold(uint32_t aThreshold);
     407             : 
     408             :   // Find out state
     409           0 :   uint16_t GetReadyState()
     410             :     {
     411           0 :       if (mConnection) {
     412           0 :         MutexAutoLock lock(mConnection->mLock);
     413           0 :         if (mState == WAITING_TO_OPEN)
     414           0 :           return CONNECTING;
     415           0 :         return mState;
     416             :       }
     417           0 :       return CLOSED;
     418             :     }
     419             : 
     420           0 :   void GetLabel(nsAString& aLabel) { CopyUTF8toUTF16(mLabel, aLabel); }
     421           0 :   void GetProtocol(nsAString& aProtocol) { CopyUTF8toUTF16(mProtocol, aProtocol); }
     422           0 :   uint16_t GetStream() { return mStream; }
     423             : 
     424             :   void AppReady();
     425             : 
     426             :   void SendOrQueue(DataChannelOnMessageAvailable *aMessage);
     427             : 
     428             : protected:
     429             :   Mutex mListenerLock; // protects mListener and mContext
     430             :   DataChannelListener *mListener;
     431             :   nsCOMPtr<nsISupports> mContext;
     432             : 
     433             : private:
     434             :   friend class DataChannelOnMessageAvailable;
     435             :   friend class DataChannelConnection;
     436             : 
     437             :   nsresult AddDataToBinaryMsg(const char *data, uint32_t size);
     438             :   uint32_t GetBufferedAmountLocked() const;
     439             : 
     440             :   RefPtr<DataChannelConnection> mConnection;
     441             :   nsCString mLabel;
     442             :   nsCString mProtocol;
     443             :   uint16_t mState;
     444             :   bool     mReady;
     445             :   uint16_t mStream;
     446             :   uint16_t mPrPolicy;
     447             :   uint32_t mPrValue;
     448             :   uint32_t mFlags;
     449             :   uint32_t mId;
     450             :   bool mIsRecvBinary;
     451             :   size_t mBufferedThreshold;
     452             :   nsCString mRecvBuffer;
     453             :   nsTArray<nsAutoPtr<BufferedMsg>> mBufferedData; // GUARDED_BY(mConnection->mLock)
     454             :   nsTArray<nsCOMPtr<nsIRunnable>> mQueuedMessages;
     455             :   nsCOMPtr<nsIEventTarget> mMainThreadEventTarget;
     456             : };
     457             : 
     458             : // used to dispatch notifications of incoming data to the main thread
     459             : // Patterned on CallOnMessageAvailable in WebSockets
     460             : // Also used to proxy other items to MainThread
     461             : class DataChannelOnMessageAvailable : public Runnable
     462             : {
     463             : public:
     464             :   enum {
     465             :     ON_CONNECTION,
     466             :     ON_DISCONNECTED,
     467             :     ON_CHANNEL_CREATED,
     468             :     ON_CHANNEL_OPEN,
     469             :     ON_CHANNEL_CLOSED,
     470             :     ON_DATA,
     471             :     BUFFER_LOW_THRESHOLD,
     472             :     NO_LONGER_BUFFERED,
     473             :   };  /* types */
     474             : 
     475           0 :   DataChannelOnMessageAvailable(
     476             :     int32_t aType,
     477             :     DataChannelConnection* aConnection,
     478             :     DataChannel* aChannel,
     479             :     nsCString& aData, // XXX this causes inefficiency
     480             :     int32_t aLen)
     481           0 :     : Runnable("DataChannelOnMessageAvailable")
     482             :     , mType(aType)
     483             :     , mChannel(aChannel)
     484             :     , mConnection(aConnection)
     485             :     , mData(aData)
     486           0 :     , mLen(aLen)
     487             :   {
     488           0 :   }
     489             : 
     490             :   DataChannelOnMessageAvailable(int32_t aType, DataChannel* aChannel)
     491             :     : Runnable("DataChannelOnMessageAvailable")
     492             :     , mType(aType)
     493             :     , mChannel(aChannel)
     494             :   {
     495             :   }
     496             :   // XXX is it safe to leave mData/mLen uninitialized?  This should only be
     497             :   // used for notifications that don't use them, but I'd like more
     498             :   // bulletproof compile-time checking.
     499             : 
     500           0 :   DataChannelOnMessageAvailable(int32_t aType,
     501             :                                 DataChannelConnection* aConnection,
     502             :                                 DataChannel* aChannel)
     503           0 :     : Runnable("DataChannelOnMessageAvailable")
     504             :     , mType(aType)
     505             :     , mChannel(aChannel)
     506           0 :     , mConnection(aConnection)
     507             :   {
     508           0 :   }
     509             : 
     510             :   // for ON_CONNECTION/ON_DISCONNECTED
     511           0 :   DataChannelOnMessageAvailable(int32_t aType,
     512             :                                 DataChannelConnection* aConnection)
     513           0 :     : Runnable("DataChannelOnMessageAvailable")
     514             :     , mType(aType)
     515           0 :     , mConnection(aConnection)
     516             :   {
     517           0 :   }
     518             : 
     519           0 :   NS_IMETHOD Run() override
     520             :   {
     521           0 :     MOZ_ASSERT(NS_IsMainThread());
     522             : 
     523             :     // Note: calling the listeners can indirectly cause the listeners to be
     524             :     // made available for GC (by removing event listeners), especially for
     525             :     // OnChannelClosed().  We hold a ref to the Channel and the listener
     526             :     // while calling this.
     527           0 :     switch (mType) {
     528             :       case ON_DATA:
     529             :       case ON_CHANNEL_OPEN:
     530             :       case ON_CHANNEL_CLOSED:
     531             :       case BUFFER_LOW_THRESHOLD:
     532             :       case NO_LONGER_BUFFERED:
     533             :         {
     534           0 :           MutexAutoLock lock(mChannel->mListenerLock);
     535           0 :           if (!mChannel->mListener) {
     536           0 :             DATACHANNEL_LOG(("DataChannelOnMessageAvailable (%d) with null Listener!",mType));
     537           0 :             return NS_OK;
     538             :           }
     539             : 
     540           0 :           switch (mType) {
     541             :             case ON_DATA:
     542           0 :               if (mLen < 0) {
     543           0 :                 mChannel->mListener->OnMessageAvailable(mChannel->mContext, mData);
     544             :               } else {
     545           0 :                 mChannel->mListener->OnBinaryMessageAvailable(mChannel->mContext, mData);
     546             :               }
     547           0 :               break;
     548             :             case ON_CHANNEL_OPEN:
     549           0 :               mChannel->mListener->OnChannelConnected(mChannel->mContext);
     550           0 :               break;
     551             :             case ON_CHANNEL_CLOSED:
     552           0 :               mChannel->mListener->OnChannelClosed(mChannel->mContext);
     553           0 :               break;
     554             :             case BUFFER_LOW_THRESHOLD:
     555           0 :               mChannel->mListener->OnBufferLow(mChannel->mContext);
     556           0 :               break;
     557             :             case NO_LONGER_BUFFERED:
     558           0 :               mChannel->mListener->NotBuffered(mChannel->mContext);
     559           0 :               break;
     560             :           }
     561           0 :           break;
     562             :         }
     563             :       case ON_DISCONNECTED:
     564             :         // If we've disconnected, make sure we close all the streams - from mainthread!
     565           0 :         mConnection->CloseAll();
     566             :         MOZ_FALLTHROUGH;
     567             :       case ON_CHANNEL_CREATED:
     568             :       case ON_CONNECTION:
     569             :         // WeakPtr - only used/modified/nulled from MainThread so we can use a WeakPtr here
     570           0 :         if (!mConnection->mListener) {
     571           0 :           DATACHANNEL_LOG(("DataChannelOnMessageAvailable (%d) with null Listener",mType));
     572           0 :           return NS_OK;
     573             :         }
     574           0 :         switch (mType) {
     575             :           case ON_CHANNEL_CREATED:
     576             :             // important to give it an already_AddRefed pointer!
     577           0 :             mConnection->mListener->NotifyDataChannel(mChannel.forget());
     578           0 :             break;
     579             :           default:
     580           0 :             break;
     581             :         }
     582           0 :         break;
     583             :     }
     584           0 :     return NS_OK;
     585             :   }
     586             : 
     587             : private:
     588           0 :   ~DataChannelOnMessageAvailable() {}
     589             : 
     590             :   int32_t                           mType;
     591             :   // XXX should use union
     592             :   RefPtr<DataChannel>             mChannel;
     593             :   RefPtr<DataChannelConnection>   mConnection;
     594             :   nsCString                         mData;
     595             :   int32_t                           mLen;
     596             : };
     597             : 
     598             : }
     599             : 
     600             : #endif  // NETWERK_SCTP_DATACHANNEL_DATACHANNEL_H_

Generated by: LCOV version 1.13