DataChannel.h 18 KB

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