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/. */
7 #ifndef NETWERK_SCTP_DATACHANNEL_DATACHANNEL_H_
8 #define NETWERK_SCTP_DATACHANNEL_DATACHANNEL_H_
14 #include "nsISupports.h"
16 #include "mozilla/UniquePtr.h"
17 #include "mozilla/WeakPtr.h"
19 #include "nsThreadUtils.h"
22 #include "mozilla/dom/Blob.h"
23 #include "mozilla/Mutex.h"
24 #include "DataChannelProtocol.h"
25 #include "DataChannelListener.h"
26 #include "mozilla/net/NeckoTargetHolder.h"
28 #include "transport/sigslot.h"
29 #include "transport/transportlayer.h" // For TransportLayer::State
32 # define EALREADY WSAEALREADY
42 class DataChannelConnection
;
44 class DataChannelOnMessageAvailable
;
46 class MediaTransportHandler
;
48 struct RTCStatsCollection
;
51 enum class DataChannelState
{ Connecting
, Open
, Closing
, Closed
};
52 enum class DataChannelConnectionState
{ Connecting
, Open
, Closed
};
53 enum class DataChannelReliabilityPolicy
{
55 LimitedRetransmissions
,
59 // For sending outgoing messages.
60 // This class only holds a reference to the data and the info structure but does
64 OutgoingMsg(struct sctp_sendv_spa
& info
, Span
<const uint8_t> data
);
66 void Advance(size_t offset
);
67 struct sctp_sendv_spa
& GetInfo() const { return *mInfo
; };
68 size_t GetLength() const { return mData
.Length(); };
69 Span
<const uint8_t> GetRemainingData() const { return mData
.From(mPos
); }
72 const Span
<const uint8_t> mData
;
73 struct sctp_sendv_spa
* const mInfo
;
77 // For queuing outgoing messages
78 // This class copies data of an outgoing message.
79 class BufferedOutgoingMsg
: public OutgoingMsg
{
81 static UniquePtr
<BufferedOutgoingMsg
> CopyFrom(const OutgoingMsg
& msg
);
84 BufferedOutgoingMsg(nsTArray
<uint8_t>&& data
,
85 UniquePtr
<struct sctp_sendv_spa
>&& info
);
86 const nsTArray
<uint8_t> mDataStorage
;
87 const UniquePtr
<struct sctp_sendv_spa
> mInfoStorage
;
90 // for queuing incoming data messages before the Open or
91 // external negotiation is indicated to us
92 class QueuedDataMessage
{
94 QueuedDataMessage(uint16_t stream
, uint32_t ppid
, int flags
,
95 const uint8_t* data
, uint32_t length
)
96 : mStream(stream
), mPpid(ppid
), mFlags(flags
), mData(data
, length
) {}
98 const uint16_t mStream
;
101 const nsTArray
<uint8_t> mData
;
104 // One per PeerConnection
105 class DataChannelConnection final
: public net::NeckoTargetHolder
,
106 public sigslot::has_slots
<> {
107 friend class DataChannel
;
108 friend class DataChannelOnMessageAvailable
;
109 friend class DataChannelConnectRunnable
;
111 virtual ~DataChannelConnection();
114 enum class PendingType
{
115 None
, // No outgoing messages are pending.
116 Dcep
, // Outgoing DCEP messages are pending.
117 Data
, // Outgoing data channel messages are pending.
120 class DataConnectionListener
: public SupportsWeakPtr
{
122 virtual ~DataConnectionListener() = default;
124 // Called when a new DataChannel has been opened by the other side.
125 virtual void NotifyDataChannel(already_AddRefed
<DataChannel
> channel
) = 0;
127 // Called when a DataChannel transitions to state open
128 virtual void NotifyDataChannelOpen(DataChannel
* aChannel
) = 0;
130 // Called when a DataChannel (that was open at some point in the past)
131 // transitions to state closed
132 virtual void NotifyDataChannelClosed(DataChannel
* aChannel
) = 0;
134 // Called when SCTP connects
135 virtual void NotifySctpConnected() = 0;
137 // Called when SCTP closes
138 virtual void NotifySctpClosed() = 0;
141 // Create a new DataChannel Connection
142 // Must be called on Main thread
143 static Maybe
<RefPtr
<DataChannelConnection
>> Create(
144 DataConnectionListener
* aListener
, nsISerialEventTarget
* aTarget
,
145 MediaTransportHandler
* aHandler
, const uint16_t aLocalPort
,
146 const uint16_t aNumStreams
, const Maybe
<uint64_t>& aMaxMessageSize
);
148 DataChannelConnection(const DataChannelConnection
&) = delete;
149 DataChannelConnection(DataChannelConnection
&&) = delete;
150 DataChannelConnection
& operator=(const DataChannelConnection
&) = delete;
151 DataChannelConnection
& operator=(DataChannelConnection
&&) = delete;
153 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DataChannelConnection
)
155 void Destroy(); // So we can spawn refs tied to runnables in shutdown
156 // Finish Destroy on STS to avoid SCTP race condition with ABORT from far end
157 void DestroyOnSTS(struct socket
* aMasterSocket
, struct socket
* aSocket
);
158 void DestroyOnSTSFinal();
160 void SetMaxMessageSize(bool aMaxMessageSizeSet
, uint64_t aMaxMessageSize
);
161 uint64_t GetMaxMessageSize();
163 void AppendStatsToReport(const UniquePtr
<dom::RTCStatsCollection
>& aReport
,
164 const DOMHighResTimeStamp aTimestamp
) const;
166 bool ConnectToTransport(const std::string
& aTransportId
, const bool aClient
,
167 const uint16_t aLocalPort
,
168 const uint16_t aRemotePort
);
169 void TransportStateChange(const std::string
& aTransportId
,
170 TransportLayer::State aState
);
171 void CompleteConnect();
172 void SetSignals(const std::string
& aTransportId
);
174 [[nodiscard
]] already_AddRefed
<DataChannel
> Open(
175 const nsACString
& label
, const nsACString
& protocol
,
176 DataChannelReliabilityPolicy prPolicy
, bool inOrder
, uint32_t prValue
,
177 DataChannelListener
* aListener
, nsISupports
* aContext
,
178 bool aExternalNegotiated
, uint16_t aStream
);
181 void Close(DataChannel
* aChannel
);
182 void CloseLocked(DataChannel
* aChannel
) MOZ_REQUIRES(mLock
);
185 // Returns a POSIX error code.
186 int SendMsg(uint16_t stream
, const nsACString
& aMsg
) {
187 return SendDataMsgCommon(stream
, aMsg
, false);
190 // Returns a POSIX error code.
191 int SendBinaryMsg(uint16_t stream
, const nsACString
& aMsg
) {
192 return SendDataMsgCommon(stream
, aMsg
, true);
195 // Returns a POSIX error code.
196 int SendBlob(uint16_t stream
, nsIInputStream
* aBlob
);
198 // Called on data reception from the SCTP library
199 // must(?) be public so my c->c++ trampoline can call it
200 // May be called with (STS thread) or without the lock
201 int ReceiveCallback(struct socket
* sock
, void* data
, size_t datalen
,
202 struct sctp_rcvinfo rcv
, int flags
);
204 void ReadBlob(already_AddRefed
<DataChannelConnection
> aThis
, uint16_t aStream
,
205 nsIInputStream
* aBlob
);
207 bool SendDeferredMessages() MOZ_REQUIRES(mLock
);
209 int SctpDtlsOutput(void* addr
, void* buffer
, size_t length
, uint8_t tos
,
212 bool InShutdown() const {
213 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
223 using ChannelArray
= AutoTArray
<RefPtr
<DataChannel
>, 16>;
225 Channels() : mMutex("DataChannelConnection::Channels::mMutex") {}
226 Channels(const Channels
&) = delete;
227 Channels(Channels
&&) = delete;
228 Channels
& operator=(const Channels
&) = delete;
229 Channels
& operator=(Channels
&&) = delete;
231 void Insert(const RefPtr
<DataChannel
>& aChannel
);
232 bool Remove(const RefPtr
<DataChannel
>& aChannel
);
233 RefPtr
<DataChannel
> Get(uint16_t aId
) const;
234 ChannelArray
GetAll() const {
235 MutexAutoLock
lock(mMutex
);
236 return mChannels
.Clone();
238 RefPtr
<DataChannel
> GetNextChannel(uint16_t aCurrentId
) const;
241 struct IdComparator
{
242 bool Equals(const RefPtr
<DataChannel
>& aChannel
, uint16_t aId
) const;
243 bool LessThan(const RefPtr
<DataChannel
>& aChannel
, uint16_t aId
) const;
244 bool Equals(const RefPtr
<DataChannel
>& a1
,
245 const RefPtr
<DataChannel
>& a2
) const;
246 bool LessThan(const RefPtr
<DataChannel
>& a1
,
247 const RefPtr
<DataChannel
>& a2
) const;
249 mutable Mutex mMutex
;
250 ChannelArray mChannels
MOZ_GUARDED_BY(mMutex
);
253 DataChannelConnection(DataConnectionListener
* aListener
,
254 nsISerialEventTarget
* aTarget
,
255 MediaTransportHandler
* aHandler
);
257 bool Init(const uint16_t aLocalPort
, const uint16_t aNumStreams
,
258 const Maybe
<uint64_t>& aMaxMessageSize
);
260 DataChannelConnectionState
GetState() const MOZ_REQUIRES(mLock
) {
261 mLock
.AssertCurrentThreadOwns();
266 void SetState(DataChannelConnectionState aState
) MOZ_REQUIRES(mLock
);
267 static int OnThresholdEvent(struct socket
* sock
, uint32_t sb_free
,
270 static void DTLSConnectThread(void* data
);
271 void SendPacket(std::unique_ptr
<MediaPacket
>&& packet
);
272 void SctpDtlsInput(const std::string
& aTransportId
,
273 const MediaPacket
& packet
);
274 DataChannel
* FindChannelByStream(uint16_t stream
) MOZ_REQUIRES(mLock
);
275 uint16_t FindFreeStream() const MOZ_REQUIRES(mLock
);
276 bool RequestMoreStreams(int32_t aNeeded
= 16) MOZ_REQUIRES(mLock
);
277 uint32_t UpdateCurrentStreamIndex() MOZ_REQUIRES(mLock
);
278 uint32_t GetCurrentStreamIndex() MOZ_REQUIRES(mLock
);
279 int SendControlMessage(const uint8_t* data
, uint32_t len
, uint16_t stream
)
281 int SendOpenAckMessage(uint16_t stream
) MOZ_REQUIRES(mLock
);
282 int SendOpenRequestMessage(const nsACString
& label
,
283 const nsACString
& protocol
, uint16_t stream
,
285 DataChannelReliabilityPolicy prPolicy
,
286 uint32_t prValue
) MOZ_REQUIRES(mLock
);
287 bool SendBufferedMessages(nsTArray
<UniquePtr
<BufferedOutgoingMsg
>>& buffer
,
288 size_t* aWritten
) MOZ_REQUIRES(mLock
);
289 int SendMsgInternal(OutgoingMsg
& msg
, size_t* aWritten
) MOZ_REQUIRES(mLock
);
290 int SendMsgInternalOrBuffer(nsTArray
<UniquePtr
<BufferedOutgoingMsg
>>& buffer
,
291 OutgoingMsg
& msg
, bool& buffered
,
292 size_t* aWritten
) MOZ_REQUIRES(mLock
);
293 int SendDataMsgInternalOrBuffer(DataChannel
& channel
, const uint8_t* data
,
294 size_t len
, uint32_t ppid
)
296 int SendDataMsg(DataChannel
& channel
, const uint8_t* data
, size_t len
,
297 uint32_t ppidPartial
, uint32_t ppidFinal
) MOZ_REQUIRES(mLock
);
298 int SendDataMsgCommon(uint16_t stream
, const nsACString
& aMsg
, bool isBinary
);
300 void DeliverQueuedData(uint16_t stream
) MOZ_REQUIRES(mLock
);
302 already_AddRefed
<DataChannel
> OpenFinish(
303 already_AddRefed
<DataChannel
>&& aChannel
) MOZ_REQUIRES(mLock
);
305 void ProcessQueuedOpens() MOZ_REQUIRES(mLock
);
306 void ClearResets() MOZ_REQUIRES(mLock
);
307 void SendOutgoingStreamReset() MOZ_REQUIRES(mLock
);
308 void ResetOutgoingStream(DataChannel
& aChannel
) MOZ_REQUIRES(mLock
);
309 void HandleOpenRequestMessage(
310 const struct rtcweb_datachannel_open_request
* req
, uint32_t length
,
311 uint16_t stream
) MOZ_REQUIRES(mLock
);
312 void HandleOpenAckMessage(const struct rtcweb_datachannel_ack
* ack
,
313 uint32_t length
, uint16_t stream
);
314 void HandleUnknownMessage(uint32_t ppid
, uint32_t length
, uint16_t stream
)
316 uint8_t BufferMessage(nsACString
& recvBuffer
, const void* data
,
317 uint32_t length
, uint32_t ppid
, int flags
);
318 void HandleDataMessage(const void* data
, size_t length
, uint32_t ppid
,
319 uint16_t stream
, int flags
) MOZ_REQUIRES(mLock
);
320 void HandleDCEPMessage(const void* buffer
, size_t length
, uint32_t ppid
,
321 uint16_t stream
, int flags
) MOZ_REQUIRES(mLock
);
322 void HandleMessage(const void* buffer
, size_t length
, uint32_t ppid
,
323 uint16_t stream
, int flags
) MOZ_REQUIRES(mLock
);
324 void HandleAssociationChangeEvent(const struct sctp_assoc_change
* sac
)
326 void HandlePeerAddressChangeEvent(const struct sctp_paddr_change
* spc
)
328 void HandleRemoteErrorEvent(const struct sctp_remote_error
* sre
)
330 void HandleShutdownEvent(const struct sctp_shutdown_event
* sse
)
332 void HandleAdaptationIndication(const struct sctp_adaptation_event
* sai
)
334 void HandlePartialDeliveryEvent(const struct sctp_pdapi_event
* spde
)
336 void HandleSendFailedEvent(const struct sctp_send_failed_event
* ssfe
)
338 void HandleStreamResetEvent(const struct sctp_stream_reset_event
* strrst
)
340 void HandleStreamChangeEvent(const struct sctp_stream_change_event
* strchg
)
342 void HandleNotification(const union sctp_notification
* notif
, size_t n
)
345 bool IsSTSThread() const {
348 mSTS
->IsOnCurrentThread(&on
);
354 // Avoid cycles with PeerConnectionImpl
355 // Use from main thread only as WeakPtr is not threadsafe
356 WeakPtr
<DataConnectionListener
> mListener
;
357 bool mSendInterleaved
MOZ_GUARDED_BY(mLock
) = false;
359 bool mMaxMessageSizeSet
= false;
360 // mMaxMessageSize is only set on MainThread, but read off-main-thread
361 uint64_t mMaxMessageSize
MOZ_GUARDED_BY(mLock
) = 0;
363 Maybe
<bool> mAllocateEven
;
365 // NOTE: while this container will auto-expand, increases in the number of
366 // channels available from the stack must be negotiated!
367 // Accessed from both main and sts, API is threadsafe
370 uint32_t mCurrentStream
= 0;
372 std::set
<RefPtr
<DataChannel
>> mPending
MOZ_GUARDED_BY(mLock
);
373 size_t mNegotiatedIdLimit
MOZ_GUARDED_BY(mLock
) = 0;
374 PendingType mPendingType
MOZ_GUARDED_BY(mLock
) = PendingType::None
;
375 // holds data that's come in before a channel is open
376 nsTArray
<UniquePtr
<QueuedDataMessage
>> mQueuedData
MOZ_GUARDED_BY(mLock
);
377 // holds outgoing control messages
378 nsTArray
<UniquePtr
<BufferedOutgoingMsg
>> mBufferedControl
379 MOZ_GUARDED_BY(mLock
);
381 // Streams pending reset. Accessed from main and STS.
382 AutoTArray
<uint16_t, 4> mStreamsResetting
MOZ_GUARDED_BY(mLock
);
383 // accessed from STS thread
384 struct socket
* mMasterSocket
= nullptr;
385 // cloned from mMasterSocket on successful Connect on STS thread
386 struct socket
* mSocket
= nullptr;
387 DataChannelConnectionState mState
MOZ_GUARDED_BY(mLock
) =
388 DataChannelConnectionState::Closed
;
390 std::string mTransportId
;
391 bool mConnectedToTransportHandler
= false;
392 RefPtr
<MediaTransportHandler
> mTransportHandler
;
393 nsCOMPtr
<nsIEventTarget
> mSTS
;
394 uint16_t mLocalPort
= 0; // Accessed from connect thread
395 uint16_t mRemotePort
= 0;
397 nsCOMPtr
<nsIThread
> mInternalIOThread
= nullptr;
398 nsCString mRecvBuffer
;
400 // Workaround to prevent a message from being received on main before the
401 // sender sees the decrease in bufferedAmount.
402 bool mDeferSend
= false;
403 std::vector
<std::unique_ptr
<MediaPacket
>> mDeferredSend
;
405 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
412 friend class DataChannelOnMessageAvailable
;
413 friend class DataChannelConnection
;
416 struct TrafficCounters
{
417 uint32_t mMessagesSent
= 0;
418 uint64_t mBytesSent
= 0;
419 uint32_t mMessagesReceived
= 0;
420 uint64_t mBytesReceived
= 0;
423 DataChannel(DataChannelConnection
* connection
, uint16_t stream
,
424 DataChannelState state
, const nsACString
& label
,
425 const nsACString
& protocol
, DataChannelReliabilityPolicy policy
,
426 uint32_t value
, bool ordered
, bool negotiated
,
427 DataChannelListener
* aListener
, nsISupports
* aContext
);
428 DataChannel(const DataChannel
&) = delete;
429 DataChannel(DataChannel
&&) = delete;
430 DataChannel
& operator=(const DataChannel
&) = delete;
431 DataChannel
& operator=(DataChannel
&&) = delete;
437 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DataChannel
)
439 // when we disconnect from the connection after stream RESET
440 void StreamClosedLocked();
442 // Complete dropping of the link between DataChannel and the connection.
443 // After this, except for a few methods below listed to be safe, you can't
444 // call into DataChannel.
445 void ReleaseConnection();
447 // Close this DataChannel. Can be called multiple times. MUST be called
448 // before destroying the DataChannel (state must be CLOSED or CLOSING).
451 // Set the listener (especially for channels created from the other side)
452 void SetListener(DataChannelListener
* aListener
, nsISupports
* aContext
);
454 // Helper for send methods that converts POSIX error codes to an ErrorResult.
455 static void SendErrnoToErrorResult(int error
, size_t aMessageSize
,
459 void SendMsg(const nsACString
& aMsg
, ErrorResult
& aRv
);
461 // Send a binary message (TypedArray)
462 void SendBinaryMsg(const nsACString
& aMsg
, ErrorResult
& aRv
);
464 // Send a binary blob
465 void SendBinaryBlob(dom::Blob
& aBlob
, ErrorResult
& aRv
);
467 DataChannelReliabilityPolicy
GetType() const { return mPrPolicy
; }
469 dom::Nullable
<uint16_t> GetMaxPacketLifeTime() const;
471 dom::Nullable
<uint16_t> GetMaxRetransmits() const;
473 bool GetNegotiated() const { return mNegotiated
; }
475 bool GetOrdered() const { return mOrdered
; }
477 void IncrementBufferedAmount(uint32_t aSize
, ErrorResult
& aRv
);
478 void DecrementBufferedAmount(uint32_t aSize
);
480 // Amount of data buffered to send
481 uint32_t GetBufferedAmount() const {
482 MOZ_ASSERT(NS_IsMainThread());
483 return mBufferedAmount
;
486 // Trigger amount for generating BufferedAmountLow events
487 uint32_t GetBufferedAmountLowThreshold() const;
488 void SetBufferedAmountLowThreshold(uint32_t aThreshold
);
491 // TODO(bug 843625): Optionally pass an error here.
492 void AnnounceClosed();
495 DataChannelState
GetReadyState() const {
496 MOZ_ASSERT(NS_IsMainThread());
501 void SetReadyState(DataChannelState aState
);
503 void GetLabel(nsAString
& aLabel
) { CopyUTF8toUTF16(mLabel
, aLabel
); }
504 void GetProtocol(nsAString
& aProtocol
) {
505 CopyUTF8toUTF16(mProtocol
, aProtocol
);
507 uint16_t GetStream() const { return mStream
; }
509 void SendOrQueue(DataChannelOnMessageAvailable
* aMessage
)
510 MOZ_REQUIRES(mConnection
->mLock
);
512 TrafficCounters
GetTrafficCounters() const;
514 bool HasSentStreamReset() const { return mHasSentStreamReset
; }
515 void SetHasSentStreamReset() { mHasSentStreamReset
= true; }
518 nsresult
AddDataToBinaryMsg(const char* data
, uint32_t size
);
519 bool EnsureValidStream(ErrorResult
& aRv
);
520 void WithTrafficCounters(const std::function
<void(TrafficCounters
&)>&);
522 // These are both mainthread only
523 DataChannelListener
* mListener
;
524 nsCOMPtr
<nsISupports
> mContext
;
526 RefPtr
<DataChannelConnection
> mConnection
;
528 bool mEverOpened
= false;
529 const nsCString mLabel
;
530 const nsCString mProtocol
;
531 // This is mainthread only
532 DataChannelState mReadyState
;
534 const DataChannelReliabilityPolicy mPrPolicy
;
535 const uint32_t mPrValue
;
536 // Accessed on main and STS
537 const bool mNegotiated
;
539 // The data channel has completed the open procedure and the client has been
540 // notified about it.
541 bool mHasFinishedOpen
= false;
542 // The channel has been opened, but the peer has not yet acked - ensures that
543 // the messages are sent ordered until this is cleared.
544 bool mWaitingForAck
= false;
545 // A too large message was attempted to be sent - closing data channel.
546 bool mClosingTooLarge
= false;
547 bool mHasSentStreamReset
= false;
549 size_t mBufferedThreshold
;
550 // Read/written on main only. Decremented via message-passing, because the
551 // spec requires us to queue a task for this.
552 size_t mBufferedAmount
;
553 nsCString mRecvBuffer
;
554 nsTArray
<UniquePtr
<BufferedOutgoingMsg
>> mBufferedData
555 MOZ_GUARDED_BY(mConnection
->mLock
);
556 nsCOMPtr
<nsISerialEventTarget
> mMainThreadEventTarget
;
557 mutable Mutex mStatsLock
;
558 TrafficCounters mTrafficCounters
MOZ_GUARDED_BY(mStatsLock
);
561 // used to dispatch notifications of incoming data to the main thread
562 // Patterned on CallOnMessageAvailable in WebSockets
563 // Also used to proxy other items to MainThread
564 class DataChannelOnMessageAvailable
: public Runnable
{
566 enum class EventType
{
574 DataChannelOnMessageAvailable(
575 EventType aType
, DataChannelConnection
* aConnection
,
576 DataChannel
* aChannel
,
577 nsCString
& aData
) // XXX this causes inefficiency
578 : Runnable("DataChannelOnMessageAvailable"),
581 mConnection(aConnection
),
584 DataChannelOnMessageAvailable(EventType aType
, DataChannel
* aChannel
)
585 : Runnable("DataChannelOnMessageAvailable"),
587 mChannel(aChannel
) {}
588 // XXX is it safe to leave mData uninitialized? This should only be
589 // used for notifications that don't use them, but I'd like more
590 // bulletproof compile-time checking.
592 DataChannelOnMessageAvailable(EventType aType
,
593 DataChannelConnection
* aConnection
,
594 DataChannel
* aChannel
)
595 : Runnable("DataChannelOnMessageAvailable"),
598 mConnection(aConnection
) {}
600 // for ON_CONNECTION/ON_DISCONNECTED
601 DataChannelOnMessageAvailable(EventType aType
,
602 DataChannelConnection
* aConnection
)
603 : Runnable("DataChannelOnMessageAvailable"),
605 mConnection(aConnection
) {}
606 DataChannelOnMessageAvailable(const DataChannelOnMessageAvailable
&) = delete;
607 DataChannelOnMessageAvailable(DataChannelOnMessageAvailable
&&) = delete;
608 DataChannelOnMessageAvailable
& operator=(
609 const DataChannelOnMessageAvailable
&) = delete;
610 DataChannelOnMessageAvailable
& operator=(DataChannelOnMessageAvailable
&&) =
613 NS_IMETHOD
Run() override
;
616 ~DataChannelOnMessageAvailable() = default;
619 // XXX should use union
620 RefPtr
<DataChannel
> mChannel
;
621 RefPtr
<DataChannelConnection
> mConnection
;
625 } // namespace mozilla
627 #endif // NETWERK_SCTP_DATACHANNEL_DATACHANNEL_H_