1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/sctp/datachannel/DataChannel.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,568 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=2 et sw=2 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.8 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef NETWERK_SCTP_DATACHANNEL_DATACHANNEL_H_ 1.11 +#define NETWERK_SCTP_DATACHANNEL_DATACHANNEL_H_ 1.12 + 1.13 +#ifdef MOZ_WEBRTC_SIGNALING 1.14 +#define SCTP_DTLS_SUPPORTED 1 1.15 +#endif 1.16 + 1.17 +#include <string> 1.18 +#include <errno.h> 1.19 +#include "nsISupports.h" 1.20 +#include "nsCOMPtr.h" 1.21 +#include "mozilla/WeakPtr.h" 1.22 +#include "nsString.h" 1.23 +#include "nsThreadUtils.h" 1.24 +#include "nsTArray.h" 1.25 +#include "nsDeque.h" 1.26 +#include "nsIInputStream.h" 1.27 +#include "nsITimer.h" 1.28 +#include "mozilla/Mutex.h" 1.29 +#include "DataChannelProtocol.h" 1.30 +#include "DataChannelListener.h" 1.31 +#ifdef SCTP_DTLS_SUPPORTED 1.32 +#include "mtransport/sigslot.h" 1.33 +#include "mtransport/transportflow.h" 1.34 +#include "mtransport/transportlayer.h" 1.35 +#include "mtransport/transportlayerdtls.h" 1.36 +#include "mtransport/transportlayerprsock.h" 1.37 +#endif 1.38 + 1.39 +#ifndef DATACHANNEL_LOG 1.40 +#define DATACHANNEL_LOG(args) 1.41 +#endif 1.42 + 1.43 +#ifndef EALREADY 1.44 +#define EALREADY WSAEALREADY 1.45 +#endif 1.46 + 1.47 +extern "C" { 1.48 + struct socket; 1.49 + struct sctp_rcvinfo; 1.50 +} 1.51 + 1.52 +namespace mozilla { 1.53 + 1.54 +class DTLSConnection; 1.55 +class DataChannelConnection; 1.56 +class DataChannel; 1.57 +class DataChannelOnMessageAvailable; 1.58 + 1.59 +// For queuing outgoing messages 1.60 +class BufferedMsg 1.61 +{ 1.62 +public: 1.63 + BufferedMsg(struct sctp_sendv_spa &spa,const char *data, 1.64 + uint32_t length); 1.65 + ~BufferedMsg(); 1.66 + 1.67 + struct sctp_sendv_spa *mSpa; 1.68 + const char *mData; 1.69 + uint32_t mLength; 1.70 +}; 1.71 + 1.72 +// for queuing incoming data messages before the Open or 1.73 +// external negotiation is indicated to us 1.74 +class QueuedDataMessage 1.75 +{ 1.76 +public: 1.77 + QueuedDataMessage(uint16_t stream, uint32_t ppid, 1.78 + const void *data, size_t length) 1.79 + : mStream(stream) 1.80 + , mPpid(ppid) 1.81 + , mLength(length) 1.82 + { 1.83 + mData = static_cast<char *>(moz_xmalloc(length)); // infallible 1.84 + memcpy(mData, data, length); 1.85 + } 1.86 + 1.87 + ~QueuedDataMessage() 1.88 + { 1.89 + moz_free(mData); 1.90 + } 1.91 + 1.92 + uint16_t mStream; 1.93 + uint32_t mPpid; 1.94 + size_t mLength; 1.95 + char *mData; 1.96 +}; 1.97 + 1.98 +// One per PeerConnection 1.99 +class DataChannelConnection: public nsITimerCallback 1.100 +#ifdef SCTP_DTLS_SUPPORTED 1.101 + , public sigslot::has_slots<> 1.102 +#endif 1.103 +{ 1.104 +public: 1.105 + NS_DECL_THREADSAFE_ISUPPORTS 1.106 + NS_DECL_NSITIMERCALLBACK 1.107 + 1.108 + class DataConnectionListener : public SupportsWeakPtr<DataConnectionListener> 1.109 + { 1.110 + public: 1.111 + MOZ_DECLARE_REFCOUNTED_TYPENAME(DataChannelConnection::DataConnectionListener) 1.112 + virtual ~DataConnectionListener() {} 1.113 + 1.114 + // Called when a the connection is open 1.115 + virtual void NotifyConnection() = 0; 1.116 + 1.117 + // Called when a the connection is lost/closed 1.118 + virtual void NotifyClosedConnection() = 0; 1.119 + 1.120 + // Called when a new DataChannel has been opened by the other side. 1.121 + virtual void NotifyDataChannel(already_AddRefed<DataChannel> channel) = 0; 1.122 + }; 1.123 + 1.124 + DataChannelConnection(DataConnectionListener *listener); 1.125 + virtual ~DataChannelConnection(); 1.126 + 1.127 + bool Init(unsigned short aPort, uint16_t aNumStreams, bool aUsingDtls); 1.128 + void Destroy(); // So we can spawn refs tied to runnables in shutdown 1.129 + // Finish Destroy on STS to avoid SCTP race condition with ABORT from far end 1.130 + void DestroyOnSTS(struct socket *aMasterSocket, 1.131 + struct socket *aSocket); 1.132 + 1.133 +#ifdef ALLOW_DIRECT_SCTP_LISTEN_CONNECT 1.134 + // These block; they require something to decide on listener/connector 1.135 + // (though you can do simultaneous Connect()). Do not call these from 1.136 + // the main thread! 1.137 + bool Listen(unsigned short port); 1.138 + bool Connect(const char *addr, unsigned short port); 1.139 +#endif 1.140 + 1.141 +#ifdef SCTP_DTLS_SUPPORTED 1.142 + // Connect using a TransportFlow (DTLS) channel 1.143 + void SetEvenOdd(); 1.144 + bool ConnectViaTransportFlow(TransportFlow *aFlow, uint16_t localport, uint16_t remoteport); 1.145 + void CompleteConnect(TransportFlow *flow, TransportLayer::State state); 1.146 + void SetSignals(); 1.147 +#endif 1.148 + 1.149 + typedef enum { 1.150 + RELIABLE=0, 1.151 + PARTIAL_RELIABLE_REXMIT = 1, 1.152 + PARTIAL_RELIABLE_TIMED = 2 1.153 + } Type; 1.154 + 1.155 + already_AddRefed<DataChannel> Open(const nsACString& label, 1.156 + const nsACString& protocol, 1.157 + Type type, bool inOrder, 1.158 + uint32_t prValue, 1.159 + DataChannelListener *aListener, 1.160 + nsISupports *aContext, 1.161 + bool aExternalNegotiated, 1.162 + uint16_t aStream) NS_WARN_UNUSED_RESULT; 1.163 + 1.164 + void Close(DataChannel *aChannel); 1.165 + // CloseInt() must be called with mLock held 1.166 + void CloseInt(DataChannel *aChannel); 1.167 + void CloseAll(); 1.168 + 1.169 + int32_t SendMsg(uint16_t stream, const nsACString &aMsg) 1.170 + { 1.171 + return SendMsgCommon(stream, aMsg, false); 1.172 + } 1.173 + int32_t SendBinaryMsg(uint16_t stream, const nsACString &aMsg) 1.174 + { 1.175 + return SendMsgCommon(stream, aMsg, true); 1.176 + } 1.177 + int32_t SendBlob(uint16_t stream, nsIInputStream *aBlob); 1.178 + 1.179 + // Called on data reception from the SCTP library 1.180 + // must(?) be public so my c->c++ trampoline can call it 1.181 + int ReceiveCallback(struct socket* sock, void *data, size_t datalen, 1.182 + struct sctp_rcvinfo rcv, int32_t flags); 1.183 + 1.184 + // Find out state 1.185 + enum { 1.186 + CONNECTING = 0U, 1.187 + OPEN = 1U, 1.188 + CLOSING = 2U, 1.189 + CLOSED = 3U 1.190 + }; 1.191 + uint16_t GetReadyState() { MutexAutoLock lock(mLock); return mState; } 1.192 + 1.193 + friend class DataChannel; 1.194 + Mutex mLock; 1.195 + 1.196 + void ReadBlob(already_AddRefed<DataChannelConnection> aThis, uint16_t aStream, nsIInputStream* aBlob); 1.197 + 1.198 + void GetStreamIds(std::vector<uint16_t>* aStreamList); 1.199 + 1.200 +protected: 1.201 + friend class DataChannelOnMessageAvailable; 1.202 + // Avoid cycles with PeerConnectionImpl 1.203 + // Use from main thread only as WeakPtr is not threadsafe 1.204 + WeakPtr<DataConnectionListener> mListener; 1.205 + 1.206 +private: 1.207 + friend class DataChannelConnectRunnable; 1.208 + 1.209 +#ifdef SCTP_DTLS_SUPPORTED 1.210 + static void DTLSConnectThread(void *data); 1.211 + int SendPacket(const unsigned char* data, size_t len, bool release); 1.212 + void SctpDtlsInput(TransportFlow *flow, const unsigned char *data, size_t len); 1.213 + static int SctpDtlsOutput(void *addr, void *buffer, size_t length, uint8_t tos, uint8_t set_df); 1.214 +#endif 1.215 + DataChannel* FindChannelByStream(uint16_t stream); 1.216 + uint16_t FindFreeStream(); 1.217 + bool RequestMoreStreams(int32_t aNeeded = 16); 1.218 + int32_t SendControlMessage(void *msg, uint32_t len, uint16_t stream); 1.219 + int32_t SendOpenRequestMessage(const nsACString& label, const nsACString& protocol, 1.220 + uint16_t stream, 1.221 + bool unordered, uint16_t prPolicy, uint32_t prValue); 1.222 + int32_t SendOpenAckMessage(uint16_t stream); 1.223 + int32_t SendMsgInternal(DataChannel *channel, const char *data, 1.224 + uint32_t length, uint32_t ppid); 1.225 + int32_t SendBinary(DataChannel *channel, const char *data, 1.226 + uint32_t len, uint32_t ppid_partial, uint32_t ppid_final); 1.227 + int32_t SendMsgCommon(uint16_t stream, const nsACString &aMsg, bool isBinary); 1.228 + 1.229 + void DeliverQueuedData(uint16_t stream); 1.230 + 1.231 + already_AddRefed<DataChannel> OpenFinish(already_AddRefed<DataChannel>&& aChannel); 1.232 + 1.233 + void StartDefer(); 1.234 + bool SendDeferredMessages(); 1.235 + void ProcessQueuedOpens(); 1.236 + void ClearResets(); 1.237 + void SendOutgoingStreamReset(); 1.238 + void ResetOutgoingStream(uint16_t stream); 1.239 + void HandleOpenRequestMessage(const struct rtcweb_datachannel_open_request *req, 1.240 + size_t length, 1.241 + uint16_t stream); 1.242 + void HandleOpenAckMessage(const struct rtcweb_datachannel_ack *ack, 1.243 + size_t length, uint16_t stream); 1.244 + void HandleUnknownMessage(uint32_t ppid, size_t length, uint16_t stream); 1.245 + void HandleDataMessage(uint32_t ppid, const void *buffer, size_t length, uint16_t stream); 1.246 + void HandleMessage(const void *buffer, size_t length, uint32_t ppid, uint16_t stream); 1.247 + void HandleAssociationChangeEvent(const struct sctp_assoc_change *sac); 1.248 + void HandlePeerAddressChangeEvent(const struct sctp_paddr_change *spc); 1.249 + void HandleRemoteErrorEvent(const struct sctp_remote_error *sre); 1.250 + void HandleShutdownEvent(const struct sctp_shutdown_event *sse); 1.251 + void HandleAdaptationIndication(const struct sctp_adaptation_event *sai); 1.252 + void HandleSendFailedEvent(const struct sctp_send_failed_event *ssfe); 1.253 + void HandleStreamResetEvent(const struct sctp_stream_reset_event *strrst); 1.254 + void HandleStreamChangeEvent(const struct sctp_stream_change_event *strchg); 1.255 + void HandleNotification(const union sctp_notification *notif, size_t n); 1.256 + 1.257 +#ifdef SCTP_DTLS_SUPPORTED 1.258 + bool IsSTSThread() { 1.259 + bool on = false; 1.260 + if (mSTS) { 1.261 + mSTS->IsOnCurrentThread(&on); 1.262 + } 1.263 + return on; 1.264 + } 1.265 +#endif 1.266 + 1.267 + // Exists solely for proxying release of the TransportFlow to the STS thread 1.268 + static void ReleaseTransportFlow(nsRefPtr<TransportFlow> aFlow) {} 1.269 + 1.270 + // Data: 1.271 + // NOTE: while this array will auto-expand, increases in the number of 1.272 + // channels available from the stack must be negotiated! 1.273 + bool mAllocateEven; 1.274 + nsAutoTArray<nsRefPtr<DataChannel>,16> mStreams; 1.275 + nsDeque mPending; // Holds already_AddRefed<DataChannel>s -- careful! 1.276 + // holds data that's come in before a channel is open 1.277 + nsTArray<nsAutoPtr<QueuedDataMessage> > mQueuedData; 1.278 + 1.279 + // Streams pending reset 1.280 + nsAutoTArray<uint16_t,4> mStreamsResetting; 1.281 + 1.282 + struct socket *mMasterSocket; // accessed from STS thread 1.283 + struct socket *mSocket; // cloned from mMasterSocket on successful Connect on STS thread 1.284 + uint16_t mState; // Protected with mLock 1.285 + 1.286 +#ifdef SCTP_DTLS_SUPPORTED 1.287 + nsRefPtr<TransportFlow> mTransportFlow; 1.288 + nsCOMPtr<nsIEventTarget> mSTS; 1.289 +#endif 1.290 + uint16_t mLocalPort; // Accessed from connect thread 1.291 + uint16_t mRemotePort; 1.292 + bool mUsingDtls; 1.293 + 1.294 + // Timer to control when we try to resend blocked messages 1.295 + nsCOMPtr<nsITimer> mDeferredTimer; 1.296 + uint32_t mDeferTimeout; // in ms 1.297 + bool mTimerRunning; 1.298 + nsCOMPtr<nsIThread> mInternalIOThread; 1.299 +}; 1.300 + 1.301 +#define ENSURE_DATACONNECTION \ 1.302 + do { if (!mConnection) { DATACHANNEL_LOG(("%s: %p no connection!",__FUNCTION__, this)); return; } } while (0) 1.303 + 1.304 +#define ENSURE_DATACONNECTION_RET(x) \ 1.305 + do { if (!mConnection) { DATACHANNEL_LOG(("%s: %p no connection!",__FUNCTION__, this)); return (x); } } while (0) 1.306 + 1.307 +class DataChannel { 1.308 +public: 1.309 + enum { 1.310 + CONNECTING = 0U, 1.311 + OPEN = 1U, 1.312 + CLOSING = 2U, 1.313 + CLOSED = 3U, 1.314 + WAITING_TO_OPEN = 4U 1.315 + }; 1.316 + 1.317 + DataChannel(DataChannelConnection *connection, 1.318 + uint16_t stream, 1.319 + uint16_t state, 1.320 + const nsACString& label, 1.321 + const nsACString& protocol, 1.322 + uint16_t policy, uint32_t value, 1.323 + uint32_t flags, 1.324 + DataChannelListener *aListener, 1.325 + nsISupports *aContext) 1.326 + : mListenerLock("netwerk::sctp::DataChannel") 1.327 + , mListener(aListener) 1.328 + , mContext(aContext) 1.329 + , mConnection(connection) 1.330 + , mLabel(label) 1.331 + , mProtocol(protocol) 1.332 + , mState(state) 1.333 + , mReady(false) 1.334 + , mStream(stream) 1.335 + , mPrPolicy(policy) 1.336 + , mPrValue(value) 1.337 + , mFlags(flags) 1.338 + , mIsRecvBinary(false) 1.339 + { 1.340 + NS_ASSERTION(mConnection,"NULL connection"); 1.341 + } 1.342 + 1.343 + ~DataChannel(); 1.344 + void Destroy(); // when we disconnect from the connection after stream RESET 1.345 + 1.346 + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DataChannel) 1.347 + 1.348 + // Close this DataChannel. Can be called multiple times. MUST be called 1.349 + // before destroying the DataChannel (state must be CLOSED or CLOSING). 1.350 + void Close(); 1.351 + 1.352 + // Set the listener (especially for channels created from the other side) 1.353 + void SetListener(DataChannelListener *aListener, nsISupports *aContext); 1.354 + 1.355 + // Send a string 1.356 + bool SendMsg(const nsACString &aMsg) 1.357 + { 1.358 + ENSURE_DATACONNECTION_RET(false); 1.359 + 1.360 + if (mStream != INVALID_STREAM) 1.361 + return (mConnection->SendMsg(mStream, aMsg) > 0); 1.362 + else 1.363 + return false; 1.364 + } 1.365 + 1.366 + // Send a binary message (TypedArray) 1.367 + bool SendBinaryMsg(const nsACString &aMsg) 1.368 + { 1.369 + ENSURE_DATACONNECTION_RET(false); 1.370 + 1.371 + if (mStream != INVALID_STREAM) 1.372 + return (mConnection->SendBinaryMsg(mStream, aMsg) > 0); 1.373 + else 1.374 + return false; 1.375 + } 1.376 + 1.377 + // Send a binary blob 1.378 + bool SendBinaryStream(nsIInputStream *aBlob, uint32_t msgLen) 1.379 + { 1.380 + ENSURE_DATACONNECTION_RET(false); 1.381 + 1.382 + if (mStream != INVALID_STREAM) 1.383 + return (mConnection->SendBlob(mStream, aBlob) > 0); 1.384 + else 1.385 + return false; 1.386 + } 1.387 + 1.388 + uint16_t GetType() { return mPrPolicy; } 1.389 + 1.390 + bool GetOrdered() { return !(mFlags & DATA_CHANNEL_FLAGS_OUT_OF_ORDER_ALLOWED); } 1.391 + 1.392 + // Amount of data buffered to send 1.393 + uint32_t GetBufferedAmount(); 1.394 + 1.395 + // Find out state 1.396 + uint16_t GetReadyState() 1.397 + { 1.398 + if (mConnection) { 1.399 + MutexAutoLock lock(mConnection->mLock); 1.400 + if (mState == WAITING_TO_OPEN) 1.401 + return CONNECTING; 1.402 + return mState; 1.403 + } 1.404 + return CLOSED; 1.405 + } 1.406 + 1.407 + void GetLabel(nsAString& aLabel) { CopyUTF8toUTF16(mLabel, aLabel); } 1.408 + void GetProtocol(nsAString& aProtocol) { CopyUTF8toUTF16(mProtocol, aProtocol); } 1.409 + uint16_t GetStream() { return mStream; } 1.410 + 1.411 + void AppReady(); 1.412 + 1.413 + void SendOrQueue(DataChannelOnMessageAvailable *aMessage); 1.414 + 1.415 +protected: 1.416 + Mutex mListenerLock; // protects mListener and mContext 1.417 + DataChannelListener *mListener; 1.418 + nsCOMPtr<nsISupports> mContext; 1.419 + 1.420 +private: 1.421 + friend class DataChannelOnMessageAvailable; 1.422 + friend class DataChannelConnection; 1.423 + 1.424 + nsresult AddDataToBinaryMsg(const char *data, uint32_t size); 1.425 + 1.426 + nsRefPtr<DataChannelConnection> mConnection; 1.427 + nsCString mLabel; 1.428 + nsCString mProtocol; 1.429 + uint16_t mState; 1.430 + bool mReady; 1.431 + uint16_t mStream; 1.432 + uint16_t mPrPolicy; 1.433 + uint32_t mPrValue; 1.434 + uint32_t mFlags; 1.435 + uint32_t mId; 1.436 + bool mIsRecvBinary; 1.437 + nsCString mRecvBuffer; 1.438 + nsTArray<nsAutoPtr<BufferedMsg> > mBufferedData; 1.439 + nsTArray<nsCOMPtr<nsIRunnable> > mQueuedMessages; 1.440 +}; 1.441 + 1.442 +// used to dispatch notifications of incoming data to the main thread 1.443 +// Patterned on CallOnMessageAvailable in WebSockets 1.444 +// Also used to proxy other items to MainThread 1.445 +class DataChannelOnMessageAvailable : public nsRunnable 1.446 +{ 1.447 +public: 1.448 + enum { 1.449 + ON_CONNECTION, 1.450 + ON_DISCONNECTED, 1.451 + ON_CHANNEL_CREATED, 1.452 + ON_CHANNEL_OPEN, 1.453 + ON_CHANNEL_CLOSED, 1.454 + ON_DATA, 1.455 + START_DEFER, 1.456 + }; /* types */ 1.457 + 1.458 + DataChannelOnMessageAvailable(int32_t aType, 1.459 + DataChannelConnection *aConnection, 1.460 + DataChannel *aChannel, 1.461 + nsCString &aData, // XXX this causes inefficiency 1.462 + int32_t aLen) 1.463 + : mType(aType), 1.464 + mChannel(aChannel), 1.465 + mConnection(aConnection), 1.466 + mData(aData), 1.467 + mLen(aLen) {} 1.468 + 1.469 + DataChannelOnMessageAvailable(int32_t aType, 1.470 + DataChannel *aChannel) 1.471 + : mType(aType), 1.472 + mChannel(aChannel) {} 1.473 + // XXX is it safe to leave mData/mLen uninitialized? This should only be 1.474 + // used for notifications that don't use them, but I'd like more 1.475 + // bulletproof compile-time checking. 1.476 + 1.477 + DataChannelOnMessageAvailable(int32_t aType, 1.478 + DataChannelConnection *aConnection, 1.479 + DataChannel *aChannel) 1.480 + : mType(aType), 1.481 + mChannel(aChannel), 1.482 + mConnection(aConnection) {} 1.483 + 1.484 + // for ON_CONNECTION/ON_DISCONNECTED 1.485 + DataChannelOnMessageAvailable(int32_t aType, 1.486 + DataChannelConnection *aConnection, 1.487 + bool aResult = true) 1.488 + : mType(aType), 1.489 + mConnection(aConnection), 1.490 + mResult(aResult) {} 1.491 + 1.492 + NS_IMETHOD Run() 1.493 + { 1.494 + MOZ_ASSERT(NS_IsMainThread()); 1.495 + switch (mType) { 1.496 + case ON_DATA: 1.497 + case ON_CHANNEL_OPEN: 1.498 + case ON_CHANNEL_CLOSED: 1.499 + { 1.500 + MutexAutoLock lock(mChannel->mListenerLock); 1.501 + if (!mChannel->mListener) { 1.502 + DATACHANNEL_LOG(("DataChannelOnMessageAvailable (%d) with null Listener!",mType)); 1.503 + return NS_OK; 1.504 + } 1.505 + 1.506 + switch (mType) { 1.507 + case ON_DATA: 1.508 + if (mLen < 0) { 1.509 + mChannel->mListener->OnMessageAvailable(mChannel->mContext, mData); 1.510 + } else { 1.511 + mChannel->mListener->OnBinaryMessageAvailable(mChannel->mContext, mData); 1.512 + } 1.513 + break; 1.514 + case ON_CHANNEL_OPEN: 1.515 + mChannel->mListener->OnChannelConnected(mChannel->mContext); 1.516 + break; 1.517 + case ON_CHANNEL_CLOSED: 1.518 + mChannel->mListener->OnChannelClosed(mChannel->mContext); 1.519 + break; 1.520 + } 1.521 + break; 1.522 + } 1.523 + case ON_DISCONNECTED: 1.524 + // If we've disconnected, make sure we close all the streams - from mainthread! 1.525 + mConnection->CloseAll(); 1.526 + // fall through 1.527 + case ON_CHANNEL_CREATED: 1.528 + case ON_CONNECTION: 1.529 + // WeakPtr - only used/modified/nulled from MainThread so we can use a WeakPtr here 1.530 + if (!mConnection->mListener) { 1.531 + DATACHANNEL_LOG(("DataChannelOnMessageAvailable (%d) with null Listener",mType)); 1.532 + return NS_OK; 1.533 + } 1.534 + switch (mType) { 1.535 + case ON_CHANNEL_CREATED: 1.536 + // important to give it an already_AddRefed pointer! 1.537 + mConnection->mListener->NotifyDataChannel(mChannel.forget()); 1.538 + break; 1.539 + case ON_CONNECTION: 1.540 + if (mResult) { 1.541 + mConnection->mListener->NotifyConnection(); 1.542 + } 1.543 + // FIX - on mResult false (failure) we should do something. Needs spec work here 1.544 + break; 1.545 + case ON_DISCONNECTED: 1.546 + mConnection->mListener->NotifyClosedConnection(); 1.547 + break; 1.548 + } 1.549 + break; 1.550 + case START_DEFER: 1.551 + mConnection->StartDefer(); 1.552 + break; 1.553 + } 1.554 + return NS_OK; 1.555 + } 1.556 + 1.557 +private: 1.558 + ~DataChannelOnMessageAvailable() {} 1.559 + 1.560 + int32_t mType; 1.561 + // XXX should use union 1.562 + nsRefPtr<DataChannel> mChannel; 1.563 + nsRefPtr<DataChannelConnection> mConnection; 1.564 + nsCString mData; 1.565 + int32_t mLen; 1.566 + bool mResult; 1.567 +}; 1.568 + 1.569 +} 1.570 + 1.571 +#endif // NETWERK_SCTP_DATACHANNEL_DATACHANNEL_H_