Coverage Report

Created: 2018-09-25 14:53

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