@@ -838,12 +838,14 @@ DataChannelConnection::SendControlMessage(void *msg, uint32_t len, uint16_t stre
838838
839839int32_t
840840DataChannelConnection::SendOpenRequestMessage (const nsACString& label,
841+ const nsACString& protocol,
841842 uint16_t stream, bool unordered,
842843 uint16_t prPolicy, uint32_t prValue)
843844{
844- int len = label.Length (); // not including nul
845+ int label_len = label.Length (); // not including nul
846+ int proto_len = protocol.Length (); // not including nul
845847 struct rtcweb_datachannel_open_request *req =
846- (struct rtcweb_datachannel_open_request *) moz_xmalloc (sizeof (*req)+len );
848+ (struct rtcweb_datachannel_open_request *) moz_xmalloc (sizeof (*req)+label_len+proto_len+ 1 );
847849 // careful - ok because request includes 1 char label
848850
849851 memset (req, 0 , sizeof (struct rtcweb_datachannel_open_request ));
@@ -869,9 +871,13 @@ DataChannelConnection::SendOpenRequestMessage(const nsACString& label,
869871 }
870872 req->reliability_params = htons ((uint16_t )prValue); /* XXX Why 16-bit */
871873 req->priority = htons (0 ); /* XXX: add support */
874+ req->label_length = label_len;
875+ req->protocol_length = proto_len;
872876 strcpy (&req->label [0 ], PromiseFlatCString (label).get ());
877+ strcpy (&req->label [req->label_length +1 ], PromiseFlatCString (protocol).get ());
873878
874- int32_t result = SendControlMessage (req, sizeof (*req)+len, stream);
879+ // sizeof(*req) already includes +1 byte for label, need nul for both strings
880+ int32_t result = SendControlMessage (req, sizeof (*req)+label_len+proto_len+1 , stream);
875881
876882 moz_free (req);
877883 return result;
@@ -907,7 +913,8 @@ DataChannelConnection::SendDeferredMessages()
907913
908914 // Only one of these should be set....
909915 if (channel->mFlags & DATA_CHANNEL_FLAGS_SEND_REQ ) {
910- if (SendOpenRequestMessage (channel->mLabel , channel->mStream ,
916+ if (SendOpenRequestMessage (channel->mLabel , channel->mProtocol ,
917+ channel->mStream ,
911918 channel->mFlags & DATA_CHANNEL_FLAG_OUT_OF_ORDER_ALLOWED ,
912919 channel->mPrPolicy , channel->mPrValue )) {
913920 channel->mFlags &= ~DATA_CHANNEL_FLAGS_SEND_REQ ;
@@ -996,15 +1003,10 @@ DataChannelConnection::HandleOpenRequestMessage(const struct rtcweb_datachannel_
9961003 uint16_t prPolicy;
9971004 uint32_t flags;
9981005 nsCString label (nsDependentCString (req->label ));
1006+ nsCString protocol (nsDependentCString (&req->label [req->label_length +1 ]));
9991007
10001008 mLock .AssertCurrentThreadOwns ();
10011009
1002- if ((channel = FindChannelByStream (stream))) {
1003- LOG ((" ERROR: HandleOpenRequestMessage: channel for stream %u is in state %d instead of CLOSED." ,
1004- stream, channel->mState ));
1005- /* XXX: some error handling */
1006- return ;
1007- }
10081010 switch (req->channel_type ) {
10091011 case DATA_CHANNEL_RELIABLE :
10101012 prPolicy = SCTP_PR_SCTP_NONE ;
@@ -1021,19 +1023,41 @@ DataChannelConnection::HandleOpenRequestMessage(const struct rtcweb_datachannel_
10211023 }
10221024 prValue = ntohs (req->reliability_params );
10231025 flags = ntohs (req->flags ) & DATA_CHANNEL_FLAG_OUT_OF_ORDER_ALLOWED ;
1026+
1027+ if ((channel = FindChannelByStream (stream))) {
1028+ if (!(channel->mFlags & DATA_CHANNEL_FLAGS_EXTERNAL_NEGOTIATED )) {
1029+ LOG ((" ERROR: HandleOpenRequestMessage: channel for stream %u is in state %d instead of CLOSED." ,
1030+ stream, channel->mState ));
1031+ /* XXX: some error handling */
1032+ } else {
1033+ LOG ((" Open for externally negotiated channel %u" , stream));
1034+ // XXX should also check protocol, maybe label
1035+ if (prPolicy != channel->mPrPolicy ||
1036+ prValue != channel->mPrValue ||
1037+ flags != (channel->mFlags & DATA_CHANNEL_FLAG_OUT_OF_ORDER_ALLOWED ))
1038+ {
1039+ LOG ((" WARNING: external negotiation mismatch with OpenRequest:"
1040+ " channel %u, policy %u/%u, value %u/%u, flags %x/%x" ,
1041+ stream, prPolicy, channel->mPrPolicy ,
1042+ prValue, channel->mPrValue , flags, channel->mFlags ));
1043+ }
1044+ }
1045+ return ;
1046+ }
10241047 channel = new DataChannel (this ,
10251048 stream,
10261049 DataChannel::CONNECTING ,
10271050 label,
1051+ protocol,
10281052 prPolicy, prValue,
10291053 flags,
10301054 nullptr , nullptr );
10311055 mStreams [stream] = channel;
10321056
10331057 channel->mState = DataChannel::WAITING_TO_OPEN ;
10341058
1035- LOG ((" %s: sending ON_CHANNEL_CREATED for %s: %u" , __FUNCTION__,
1036- channel->mLabel .get (), stream));
1059+ LOG ((" %s: sending ON_CHANNEL_CREATED for %s/%s : %u" , __FUNCTION__,
1060+ channel->mLabel .get (), channel-> mProtocol . get (), stream));
10371061 NS_DispatchToMainThread (new DataChannelOnMessageAvailable(
10381062 DataChannelOnMessageAvailable::ON_CHANNEL_CREATED ,
10391063 this , channel));
@@ -1691,15 +1715,20 @@ DataChannelConnection::ReceiveCallback(struct socket* sock, void *data, size_t d
16911715}
16921716
16931717already_AddRefed<DataChannel>
1694- DataChannelConnection::Open (const nsACString& label, Type type, bool inOrder,
1718+ DataChannelConnection::Open (const nsACString& label, const nsACString& protocol,
1719+ Type type, bool inOrder,
16951720 uint32_t prValue, DataChannelListener *aListener,
1696- nsISupports *aContext)
1721+ nsISupports *aContext, bool aExternalNegotiated,
1722+ uint16_t aStream)
16971723{
1724+ // aStream == INVALID_STREAM to have the protocol allocate
16981725 uint16_t prPolicy = SCTP_PR_SCTP_NONE ;
16991726 uint32_t flags;
17001727
1701- LOG ((" DC Open: label %s, type %u, inorder %d, prValue %u, listener %p, context %p" ,
1702- PromiseFlatCString (label).get (), type, inOrder, prValue, aListener, aContext));
1728+ LOG ((" DC Open: label %s/%s, type %u, inorder %d, prValue %u, listener %p, context %p, external: %s, stream %u" ,
1729+ PromiseFlatCString (label).get (), PromiseFlatCString (protocol).get (),
1730+ type, inOrder, prValue, aListener, aContext,
1731+ aExternalNegotiated ? " true" : " false" , aStream));
17031732 switch (type) {
17041733 case DATA_CHANNEL_RELIABLE :
17051734 prPolicy = SCTP_PR_SCTP_NONE ;
@@ -1715,13 +1744,24 @@ DataChannelConnection::Open(const nsACString& label, Type type, bool inOrder,
17151744 return nullptr ;
17161745 }
17171746
1747+ if (aStream != INVALID_STREAM && mStreams [aStream]) {
1748+ LOG ((" ERROR: external negotiation of already-open channel %u" , aStream));
1749+ // XXX How do we indicate this up to the application? Probably the
1750+ // caller's job, but we may need to return an error code.
1751+ return nullptr ;
1752+ }
1753+
17181754 flags = !inOrder ? DATA_CHANNEL_FLAG_OUT_OF_ORDER_ALLOWED : 0 ;
17191755 nsRefPtr<DataChannel> channel (new DataChannel (this ,
1720- INVALID_STREAM ,
1756+ aStream ,
17211757 DataChannel::CONNECTING ,
1722- label, type, prValue,
1758+ label, protocol,
1759+ type, prValue,
17231760 flags,
17241761 aListener, aContext));
1762+ if (aExternalNegotiated) {
1763+ channel->mFlags |= DATA_CHANNEL_FLAGS_EXTERNAL_NEGOTIATED ;
1764+ }
17251765
17261766 MutexAutoLock lock (mLock ); // OpenFinish assumes this
17271767 return OpenFinish (channel.forget ());
@@ -1731,38 +1771,42 @@ DataChannelConnection::Open(const nsACString& label, Type type, bool inOrder,
17311771already_AddRefed<DataChannel>
17321772DataChannelConnection::OpenFinish (already_AddRefed<DataChannel> aChannel)
17331773{
1734- uint16_t stream = FindFreeStream (); // may be INVALID_STREAM!
17351774 nsRefPtr<DataChannel> channel (aChannel);
1775+ uint16_t stream = channel->mStream ;
17361776
1737- mLock .AssertCurrentThreadOwns ();
1777+ if (stream == INVALID_STREAM ) {
1778+ stream = FindFreeStream (); // may be INVALID_STREAM!
17381779
1739- LOG (( " Finishing open: channel %p, stream = %u " , channel. get (), stream) );
1780+ mLock . AssertCurrentThreadOwns ( );
17401781
1741- if (stream == INVALID_STREAM ) {
1742- if (!RequestMoreStreams ()) {
1743- channel->mState = CLOSED ;
1744- if (channel->mFlags & DATA_CHANNEL_FLAGS_FINISH_OPEN ) {
1745- // We already returned the channel to the app.
1746- NS_ERROR (" Failed to request more streams" );
1747- NS_DispatchToMainThread (new DataChannelOnMessageAvailable(
1748- DataChannelOnMessageAvailable::ON_CHANNEL_CLOSED , this ,
1749- channel));
1750- return channel.forget ();
1782+ LOG ((" Finishing open: channel %p, stream = %u" , channel.get (), stream));
1783+
1784+ if (stream == INVALID_STREAM ) {
1785+ if (!RequestMoreStreams ()) {
1786+ channel->mState = CLOSED ;
1787+ if (channel->mFlags & DATA_CHANNEL_FLAGS_FINISH_OPEN ) {
1788+ // We already returned the channel to the app.
1789+ NS_ERROR (" Failed to request more streams" );
1790+ NS_DispatchToMainThread (new DataChannelOnMessageAvailable(
1791+ DataChannelOnMessageAvailable::ON_CHANNEL_CLOSED , this ,
1792+ channel));
1793+ return channel.forget ();
1794+ }
1795+ // we'll be destroying the channel, but it never really got set up
1796+ // Alternative would be to RUN_ON_THREAD(channel.forget(),::Destroy,...) and
1797+ // Dispatch it to ourselves
1798+ return nullptr ;
17511799 }
1752- // we'll be destroying the channel, but it never really got set up
1753- // Alternative would be to RUN_ON_THREAD(channel.forget(),::Destroy,...) and
1754- // Dispatch it to ourselves
1755- return nullptr ;
1800+ LOG ((" Queuing channel %p to finish open" , channel.get ()));
1801+ // Also serves to mark we told the app
1802+ channel->mFlags |= DATA_CHANNEL_FLAGS_FINISH_OPEN ;
1803+ channel->AddRef (); // we need a ref for the nsDeQue and one to return
1804+ mPending .Push (channel);
1805+ return channel.forget ();
17561806 }
1757- LOG ((" Queuing channel %p to finish open" , channel.get ()));
1758- // Also serves to mark we told the app
1759- channel->mFlags |= DATA_CHANNEL_FLAGS_FINISH_OPEN ;
1760- channel->AddRef (); // we need a ref for the nsDeQue and one to return
1761- mPending .Push (channel);
1762- return channel.forget ();
1807+ channel->mStream = stream;
17631808 }
17641809 mStreams [stream] = channel;
1765- channel->mStream = stream;
17661810
17671811#ifdef TEST_QUEUED_DATA
17681812 // It's painful to write a test for this...
@@ -1771,38 +1815,45 @@ DataChannelConnection::OpenFinish(already_AddRefed<DataChannel> aChannel)
17711815 SendMsgInternal (channel, " Help me!" , 8 , DATA_CHANNEL_PPID_DOMSTRING );
17721816#endif
17731817
1774- if (!SendOpenRequestMessage (channel->mLabel , stream,
1775- !!(channel->mFlags & DATA_CHANNEL_FLAG_OUT_OF_ORDER_ALLOWED ),
1776- channel->mPrPolicy , channel->mPrValue )) {
1777- LOG ((" SendOpenRequest failed, errno = %d" , errno));
1778- if (errno == EAGAIN || errno == EWOULDBLOCK ) {
1779- channel->mFlags |= DATA_CHANNEL_FLAGS_SEND_REQ ;
1780- StartDefer ();
1781- } else {
1782- if (channel->mFlags & DATA_CHANNEL_FLAGS_FINISH_OPEN ) {
1783- // We already returned the channel to the app.
1784- NS_ERROR (" Failed to send open request" );
1785- NS_DispatchToMainThread (new DataChannelOnMessageAvailable(
1786- DataChannelOnMessageAvailable::ON_CHANNEL_CLOSED , this ,
1787- channel));
1818+ if (!(channel->mFlags & DATA_CHANNEL_FLAGS_EXTERNAL_NEGOTIATED )) {
1819+ if (!SendOpenRequestMessage (channel->mLabel , channel->mProtocol ,
1820+ stream,
1821+ !!(channel->mFlags & DATA_CHANNEL_FLAG_OUT_OF_ORDER_ALLOWED ),
1822+ channel->mPrPolicy , channel->mPrValue )) {
1823+ LOG ((" SendOpenRequest failed, errno = %d" , errno));
1824+ if (errno == EAGAIN || errno == EWOULDBLOCK ) {
1825+ channel->mFlags |= DATA_CHANNEL_FLAGS_SEND_REQ ;
1826+ StartDefer ();
1827+
1828+ return channel.forget ();
1829+ } else {
1830+ if (channel->mFlags & DATA_CHANNEL_FLAGS_FINISH_OPEN ) {
1831+ // We already returned the channel to the app.
1832+ NS_ERROR (" Failed to send open request" );
1833+ NS_DispatchToMainThread (new DataChannelOnMessageAvailable(
1834+ DataChannelOnMessageAvailable::ON_CHANNEL_CLOSED , this ,
1835+ channel));
1836+ }
1837+ // If we haven't returned the channel yet, it will get destroyed when we exit
1838+ // this function.
1839+ mStreams [stream] = nullptr ;
1840+ channel->mStream = INVALID_STREAM ;
1841+ // we'll be destroying the channel
1842+ channel->mState = CLOSED ;
1843+ return nullptr ;
17881844 }
1789- // If we haven't returned the channel yet, it will get destroyed when we exit
1790- // this function.
1791- mStreams [stream] = nullptr ;
1792- channel->mStream = INVALID_STREAM ;
1793- // we'll be destroying the channel
1794- channel->mState = CLOSED ;
1795- return nullptr ;
1845+ /* NOTREACHED */
17961846 }
1797- } else {
1798- channel->mState = OPEN ;
1799- channel->mReady = true ;
1800- // FIX? Move into DOMDataChannel? I don't think we can send it yet here
1801- LOG ((" %s: sending ON_CHANNEL_OPEN for %p" , __FUNCTION__, channel.get ()));
1802- NS_DispatchToMainThread (new DataChannelOnMessageAvailable(
1803- DataChannelOnMessageAvailable::ON_CHANNEL_OPEN , this ,
1804- channel));
18051847 }
1848+ // Either externally negotiated or we sent Open
1849+ channel->mState = OPEN ;
1850+ channel->mReady = true ;
1851+ // FIX? Move into DOMDataChannel? I don't think we can send it yet here
1852+ LOG ((" %s: sending ON_CHANNEL_OPEN for %p" , __FUNCTION__, channel.get ()));
1853+ NS_DispatchToMainThread (new DataChannelOnMessageAvailable(
1854+ DataChannelOnMessageAvailable::ON_CHANNEL_OPEN , this ,
1855+ channel));
1856+
18061857 return channel.forget ();
18071858}
18081859
0 commit comments