2012-10-04 03:51:47 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2015-05-03 22:32:37 +03:00
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2012-10-04 03:51:47 +04:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
2013-05-20 11:10:59 +04:00
|
|
|
#include "nsDOMDataChannel.h"
|
|
|
|
|
2012-10-04 03:51:47 +04:00
|
|
|
#include "base/basictypes.h"
|
2015-05-19 21:15:34 +03:00
|
|
|
#include "mozilla/Logging.h"
|
2012-10-04 03:51:47 +04:00
|
|
|
|
2013-05-20 11:10:59 +04:00
|
|
|
#include "nsDOMDataChannelDeclarations.h"
|
2013-10-11 01:04:28 +04:00
|
|
|
#include "nsDOMDataChannel.h"
|
2012-10-04 03:51:47 +04:00
|
|
|
#include "nsIDOMDataChannel.h"
|
2014-04-01 10:13:50 +04:00
|
|
|
#include "mozilla/DOMEventTargetHelper.h"
|
2014-10-08 20:15:23 +04:00
|
|
|
#include "mozilla/dom/File.h"
|
2015-08-12 14:39:31 +03:00
|
|
|
#include "mozilla/dom/MessageEvent.h"
|
2016-01-30 20:05:36 +03:00
|
|
|
#include "mozilla/dom/MessageEventBinding.h"
|
2014-05-23 13:18:37 +04:00
|
|
|
#include "mozilla/dom/ScriptSettings.h"
|
2012-10-04 03:51:47 +04:00
|
|
|
|
|
|
|
#include "nsError.h"
|
|
|
|
#include "nsContentUtils.h"
|
|
|
|
#include "nsCycleCollectionParticipant.h"
|
|
|
|
#include "nsIScriptObjectPrincipal.h"
|
2016-04-26 07:28:53 +03:00
|
|
|
#include "nsProxyRelease.h"
|
2012-10-04 03:51:47 +04:00
|
|
|
|
|
|
|
#include "DataChannel.h"
|
2015-11-03 07:35:29 +03:00
|
|
|
#include "DataChannelLog.h"
|
|
|
|
|
|
|
|
#undef LOG
|
|
|
|
#define LOG(args) MOZ_LOG(mozilla::gDataChannelLog, mozilla::LogLevel::Debug, args)
|
2012-10-04 03:51:47 +04:00
|
|
|
|
2013-10-11 01:04:28 +04:00
|
|
|
// Since we've moved the windows.h include down here, we have to explicitly
|
|
|
|
// undef GetBinaryType, otherwise we'll get really odd conflicts
|
|
|
|
#ifdef GetBinaryType
|
|
|
|
#undef GetBinaryType
|
|
|
|
#endif
|
|
|
|
|
2013-02-26 23:04:13 +04:00
|
|
|
using namespace mozilla;
|
2013-05-20 11:19:45 +04:00
|
|
|
using namespace mozilla::dom;
|
2012-10-04 03:51:47 +04:00
|
|
|
|
2013-05-20 11:10:59 +04:00
|
|
|
nsDOMDataChannel::~nsDOMDataChannel()
|
|
|
|
{
|
|
|
|
// Don't call us anymore! Likely isn't an issue (or maybe just less of
|
|
|
|
// one) once we block GC until all the (appropriate) onXxxx handlers
|
|
|
|
// are dropped. (See WebRTC spec)
|
2016-04-26 07:28:53 +03:00
|
|
|
LOG(("%p: Close()ing %p", this, mDataChannel.get()));
|
2013-05-20 11:10:59 +04:00
|
|
|
mDataChannel->SetListener(nullptr, nullptr);
|
|
|
|
mDataChannel->Close();
|
|
|
|
}
|
|
|
|
|
2013-05-20 11:19:45 +04:00
|
|
|
/* virtual */ JSObject*
|
Bug 1117172 part 3. Change the wrappercached WrapObject methods to allow passing in aGivenProto. r=peterv
The only manual changes here are to BindingUtils.h, BindingUtils.cpp,
Codegen.py, Element.cpp, IDBFileRequest.cpp, IDBObjectStore.cpp,
dom/workers/Navigator.cpp, WorkerPrivate.cpp, DeviceStorageRequestChild.cpp,
Notification.cpp, nsGlobalWindow.cpp, MessagePort.cpp, nsJSEnvironment.cpp,
Sandbox.cpp, XPCConvert.cpp, ExportHelpers.cpp, and DataStoreService.cpp. The
rest of this diff was generated by running the following commands:
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObject\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(Binding(?:_workers)?::Wrap\((?:aCx|cx|aContext|aCtx|js), [^,)]+)\)/\1, aGivenProto)/g'
2015-03-19 17:13:33 +03:00
|
|
|
nsDOMDataChannel::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
2013-05-20 11:19:45 +04:00
|
|
|
{
|
2018-02-10 01:36:48 +03:00
|
|
|
return RTCDataChannelBinding::Wrap(aCx, this, aGivenProto);
|
2013-05-20 11:19:45 +04:00
|
|
|
}
|
|
|
|
|
2013-08-02 05:29:05 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMDataChannel)
|
|
|
|
|
2012-10-04 03:51:47 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMDataChannel,
|
2014-04-01 10:13:50 +04:00
|
|
|
DOMEventTargetHelper)
|
2012-10-04 03:51:47 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMDataChannel,
|
2014-04-01 10:13:50 +04:00
|
|
|
DOMEventTargetHelper)
|
2012-10-04 03:51:47 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
|
|
|
2014-04-01 10:13:50 +04:00
|
|
|
NS_IMPL_ADDREF_INHERITED(nsDOMDataChannel, DOMEventTargetHelper)
|
|
|
|
NS_IMPL_RELEASE_INHERITED(nsDOMDataChannel, DOMEventTargetHelper)
|
2012-10-04 03:51:47 +04:00
|
|
|
|
2017-08-30 02:02:48 +03:00
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMDataChannel)
|
2012-10-04 03:51:47 +04:00
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMDataChannel)
|
2014-04-01 10:13:50 +04:00
|
|
|
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
2012-10-04 03:51:47 +04:00
|
|
|
|
2014-03-15 23:00:17 +04:00
|
|
|
nsDOMDataChannel::nsDOMDataChannel(already_AddRefed<mozilla::DataChannel>& aDataChannel,
|
2016-01-30 20:05:36 +03:00
|
|
|
nsPIDOMWindowInner* aWindow)
|
|
|
|
: DOMEventTargetHelper(aWindow)
|
2014-01-07 06:53:23 +04:00
|
|
|
, mDataChannel(aDataChannel)
|
2013-10-11 01:04:28 +04:00
|
|
|
, mBinaryType(DC_BINARY_TYPE_BLOB)
|
2016-04-26 07:28:53 +03:00
|
|
|
, mCheckMustKeepAlive(true)
|
|
|
|
, mSentClose(false)
|
2013-10-11 01:04:28 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-10-04 03:51:47 +04:00
|
|
|
nsresult
|
2016-01-30 20:05:36 +03:00
|
|
|
nsDOMDataChannel::Init(nsPIDOMWindowInner* aDOMWindow)
|
2012-10-04 03:51:47 +04:00
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
nsAutoString urlParam;
|
|
|
|
|
|
|
|
MOZ_ASSERT(mDataChannel);
|
|
|
|
mDataChannel->SetListener(this, nullptr);
|
|
|
|
|
|
|
|
// Now grovel through the objects to get a usable origin for onMessage
|
|
|
|
nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aDOMWindow);
|
|
|
|
NS_ENSURE_STATE(sgo);
|
|
|
|
nsCOMPtr<nsIScriptContext> scriptContext = sgo->GetContext();
|
|
|
|
NS_ENSURE_STATE(scriptContext);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIScriptObjectPrincipal> scriptPrincipal(do_QueryInterface(aDOMWindow));
|
|
|
|
NS_ENSURE_STATE(scriptPrincipal);
|
|
|
|
nsCOMPtr<nsIPrincipal> principal = scriptPrincipal->GetPrincipal();
|
|
|
|
NS_ENSURE_STATE(principal);
|
|
|
|
|
|
|
|
// Attempt to kill "ghost" DataChannel (if one can happen): but usually too early for check to fail
|
|
|
|
rv = CheckInnerWindowCorrectness();
|
|
|
|
NS_ENSURE_SUCCESS(rv,rv);
|
|
|
|
|
|
|
|
rv = nsContentUtils::GetUTFOrigin(principal,mOrigin);
|
|
|
|
LOG(("%s: origin = %s\n",__FUNCTION__,NS_LossyConvertUTF16toASCII(mOrigin).get()));
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2016-10-20 08:03:44 +03:00
|
|
|
// Most of the GetFoo()/SetFoo()s don't need to touch shared resources and
|
|
|
|
// are safe after Close()
|
2018-01-21 20:07:29 +03:00
|
|
|
void
|
2012-10-04 03:51:47 +04:00
|
|
|
nsDOMDataChannel::GetLabel(nsAString& aLabel)
|
|
|
|
{
|
|
|
|
mDataChannel->GetLabel(aLabel);
|
|
|
|
}
|
|
|
|
|
2018-01-21 20:07:29 +03:00
|
|
|
void
|
2013-04-01 05:09:25 +04:00
|
|
|
nsDOMDataChannel::GetProtocol(nsAString& aProtocol)
|
|
|
|
{
|
|
|
|
mDataChannel->GetProtocol(aProtocol);
|
|
|
|
}
|
|
|
|
|
2013-06-04 01:34:42 +04:00
|
|
|
uint16_t
|
|
|
|
nsDOMDataChannel::Id() const
|
|
|
|
{
|
|
|
|
return mDataChannel->GetStream();
|
|
|
|
}
|
|
|
|
|
2012-10-04 03:51:47 +04:00
|
|
|
// XXX should be GetType()? Open question for the spec
|
2013-05-20 11:19:45 +04:00
|
|
|
bool
|
|
|
|
nsDOMDataChannel::Reliable() const
|
|
|
|
{
|
|
|
|
return mDataChannel->GetType() == mozilla::DataChannelConnection::RELIABLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
nsDOMDataChannel::Ordered() const
|
|
|
|
{
|
|
|
|
return mDataChannel->GetOrdered();
|
|
|
|
}
|
|
|
|
|
|
|
|
RTCDataChannelState
|
|
|
|
nsDOMDataChannel::ReadyState() const
|
|
|
|
{
|
|
|
|
return static_cast<RTCDataChannelState>(mDataChannel->GetReadyState());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t
|
|
|
|
nsDOMDataChannel::BufferedAmount() const
|
|
|
|
{
|
2016-10-20 08:03:44 +03:00
|
|
|
if (!mSentClose) {
|
|
|
|
return mDataChannel->GetBufferedAmount();
|
|
|
|
}
|
|
|
|
return 0;
|
2013-05-20 11:19:45 +04:00
|
|
|
}
|
|
|
|
|
2015-09-29 02:02:23 +03:00
|
|
|
uint32_t
|
|
|
|
nsDOMDataChannel::BufferedAmountLowThreshold() const
|
|
|
|
{
|
|
|
|
return mDataChannel->GetBufferedAmountLowThreshold();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsDOMDataChannel::SetBufferedAmountLowThreshold(uint32_t aThreshold)
|
|
|
|
{
|
|
|
|
mDataChannel->SetBufferedAmountLowThreshold(aThreshold);
|
|
|
|
}
|
|
|
|
|
2018-01-21 20:07:29 +03:00
|
|
|
void
|
2012-10-04 03:51:47 +04:00
|
|
|
nsDOMDataChannel::Close()
|
|
|
|
{
|
|
|
|
mDataChannel->Close();
|
2016-04-26 07:28:53 +03:00
|
|
|
UpdateMustKeepAlive();
|
2012-10-04 03:51:47 +04:00
|
|
|
}
|
|
|
|
|
2013-05-20 11:19:45 +04:00
|
|
|
// All of the following is copy/pasted from WebSocket.cpp.
|
|
|
|
void
|
|
|
|
nsDOMDataChannel::Send(const nsAString& aData, ErrorResult& aRv)
|
|
|
|
{
|
|
|
|
NS_ConvertUTF16toUTF8 msgString(aData);
|
Bug 979417 - Implement EOR when receiving and explicit EOR when sending on data channels (including DCEP). r=drno,jesup
This allows sending and receiving arbitrarily (we limit to 1 GiB atm) sized
messages while not relying on the deprecated PPID fragmentation/reassembly
mode. The code already supports the ndata extension but it's not activated,
yet. Without the SCTP ndata extension, a large data channel message will
monopolise the SCTP association. While this is a problem, it is a temporary
solution until the extension is being activated. Keep in mind that every
application that uses data channels currently does fragmentation/reassembly on
application-level and it's unlikely that this will change until the popular
implementations (libwebrtc) implement EOR as well. Moreover, until the WebRTC
API specifies an API that hands over partial messages, doing application-level
fragmentation/reassembly is still useful for very large messages (sadly).
We fall back to PPID-based fragmentation/reassembly mode IFF a=max-message-size
is not set in the SDP and the negotiated amount of SCTP inbound streams is
exactly 256. Other implementations should avoid using this combination (to be
precise, other implementations should send a=max-message-size).
It also changes behaviour of RTCDataChannel.send which now raises TypeError in
case the message is too large for the other peer to receive. This is a
necessity to ensure that implementations that do not look at the EOR flag when
receiving are always able to receive our messages. Even if these
implementations do not set a=max-message-size, we use a safe default value (64
KiB, dictated by the spec) that every implementation should be able to receive,
with or without EOR support.
* Due to the use of explicit EOR, this required some major refactoring of all
send-related and deferred sending functions (which is now a lot less
complex). There's now only one place where `usrsctp_sendv` is being used.
* All data channel messages and DCEP messages will be sent without copying them
first. Only in case this fails (e.g. usrsctp's buffer is full), the message
will be copied and added to a buffer queue.
* Queued data channel messages will now be re-sent fairly (round-robin).
* Maximum message size and the PPID-based fragmentation are configurable using
about:config (media.peerconnection.sctp.force_ppid_fragmentation and
media.peerconnection.sctp.force_maximum_message_size).
* Enable interleaving of incoming messages for different streams (preparation
for SCTP ndata, has no effect until it is enabled).
* Enable interleaving of outgoing messages (disabled if SCTP ndata has not been
negotiated).
* Add pending messages flag to reduce performance impact from frequent calls to
SendDeferredMessages.
* Handle partial delivery events (for cases where a partially delivered message
is being aborted).
* Close a data channel/the connection in case the message is too large to be
handled (this is only applied in cases where the remote peer ignores our
announced local maximum message size).
* Various size_t to uint32_t conversions (message length) and back should be
safe now.
* Remove aUsingDtls/mUsingDtls from DataChannelConnection.
* Set maximum message size in SDP and in the data channel stack.
* Replace implicit NS_ENSURE_*'s with explicit NS_WARN_IF's.
* Add SetMaxMessageSize method for late-applying those signalling parameters
when a data channel has been created before the remote SDP was available.
* Limit remote maximum message size and add a GetMaxMessageSize method for a
future implementation of RTCSctpTransport.maxMessageSize.
MozReview-Commit-ID: FlmZrpC5zVI
--HG--
extra : rebase_source : 54e1b838c788a3abbded4fb32fe7c2788f8a9bc0
2017-07-26 14:18:54 +03:00
|
|
|
Send(nullptr, msgString, false, aRv);
|
2013-05-20 11:19:45 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2015-05-12 15:09:51 +03:00
|
|
|
nsDOMDataChannel::Send(Blob& aData, ErrorResult& aRv)
|
2013-05-20 11:19:45 +04:00
|
|
|
{
|
2015-02-10 01:34:50 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
|
2013-05-20 11:19:45 +04:00
|
|
|
|
|
|
|
nsCOMPtr<nsIInputStream> msgStream;
|
2017-10-02 14:53:12 +03:00
|
|
|
aData.CreateInputStream(getter_AddRefs(msgStream), aRv);
|
2015-05-19 17:36:37 +03:00
|
|
|
if (NS_WARN_IF(aRv.Failed())){
|
2013-05-20 11:19:45 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-05-19 17:36:37 +03:00
|
|
|
uint64_t msgLength = aData.GetSize(aRv);
|
|
|
|
if (NS_WARN_IF(aRv.Failed())){
|
2013-05-20 11:19:45 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msgLength > UINT32_MAX) {
|
|
|
|
aRv.Throw(NS_ERROR_FILE_TOO_BIG);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
Bug 979417 - Implement EOR when receiving and explicit EOR when sending on data channels (including DCEP). r=drno,jesup
This allows sending and receiving arbitrarily (we limit to 1 GiB atm) sized
messages while not relying on the deprecated PPID fragmentation/reassembly
mode. The code already supports the ndata extension but it's not activated,
yet. Without the SCTP ndata extension, a large data channel message will
monopolise the SCTP association. While this is a problem, it is a temporary
solution until the extension is being activated. Keep in mind that every
application that uses data channels currently does fragmentation/reassembly on
application-level and it's unlikely that this will change until the popular
implementations (libwebrtc) implement EOR as well. Moreover, until the WebRTC
API specifies an API that hands over partial messages, doing application-level
fragmentation/reassembly is still useful for very large messages (sadly).
We fall back to PPID-based fragmentation/reassembly mode IFF a=max-message-size
is not set in the SDP and the negotiated amount of SCTP inbound streams is
exactly 256. Other implementations should avoid using this combination (to be
precise, other implementations should send a=max-message-size).
It also changes behaviour of RTCDataChannel.send which now raises TypeError in
case the message is too large for the other peer to receive. This is a
necessity to ensure that implementations that do not look at the EOR flag when
receiving are always able to receive our messages. Even if these
implementations do not set a=max-message-size, we use a safe default value (64
KiB, dictated by the spec) that every implementation should be able to receive,
with or without EOR support.
* Due to the use of explicit EOR, this required some major refactoring of all
send-related and deferred sending functions (which is now a lot less
complex). There's now only one place where `usrsctp_sendv` is being used.
* All data channel messages and DCEP messages will be sent without copying them
first. Only in case this fails (e.g. usrsctp's buffer is full), the message
will be copied and added to a buffer queue.
* Queued data channel messages will now be re-sent fairly (round-robin).
* Maximum message size and the PPID-based fragmentation are configurable using
about:config (media.peerconnection.sctp.force_ppid_fragmentation and
media.peerconnection.sctp.force_maximum_message_size).
* Enable interleaving of incoming messages for different streams (preparation
for SCTP ndata, has no effect until it is enabled).
* Enable interleaving of outgoing messages (disabled if SCTP ndata has not been
negotiated).
* Add pending messages flag to reduce performance impact from frequent calls to
SendDeferredMessages.
* Handle partial delivery events (for cases where a partially delivered message
is being aborted).
* Close a data channel/the connection in case the message is too large to be
handled (this is only applied in cases where the remote peer ignores our
announced local maximum message size).
* Various size_t to uint32_t conversions (message length) and back should be
safe now.
* Remove aUsingDtls/mUsingDtls from DataChannelConnection.
* Set maximum message size in SDP and in the data channel stack.
* Replace implicit NS_ENSURE_*'s with explicit NS_WARN_IF's.
* Add SetMaxMessageSize method for late-applying those signalling parameters
when a data channel has been created before the remote SDP was available.
* Limit remote maximum message size and add a GetMaxMessageSize method for a
future implementation of RTCSctpTransport.maxMessageSize.
MozReview-Commit-ID: FlmZrpC5zVI
--HG--
extra : rebase_source : 54e1b838c788a3abbded4fb32fe7c2788f8a9bc0
2017-07-26 14:18:54 +03:00
|
|
|
Send(msgStream, EmptyCString(), true, aRv);
|
2013-05-20 11:19:45 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2013-08-05 21:40:01 +04:00
|
|
|
nsDOMDataChannel::Send(const ArrayBuffer& aData, ErrorResult& aRv)
|
2013-05-20 11:19:45 +04:00
|
|
|
{
|
2015-02-10 01:34:50 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
|
2013-05-20 11:19:45 +04:00
|
|
|
|
Bug 999651, bug 995679, bug 1009952, bug 1011007, bug 991981. r=sfink, r=shu, r=jandem, r=jdm, r=luke, r=bbouvier, r=nmatsakis, r=bz, r=ehsan, r=jgilbert, r=smaug, r=sicking, r=terrence, r=bholley, r=bent, r=efaust, r=jorendorff
2014-05-28 01:32:41 +04:00
|
|
|
aData.ComputeLengthAndData();
|
|
|
|
|
|
|
|
static_assert(sizeof(*aData.Data()) == 1, "byte-sized data required");
|
|
|
|
|
2013-05-20 11:19:45 +04:00
|
|
|
uint32_t len = aData.Length();
|
|
|
|
char* data = reinterpret_cast<char*>(aData.Data());
|
|
|
|
|
|
|
|
nsDependentCSubstring msgString(data, len);
|
Bug 979417 - Implement EOR when receiving and explicit EOR when sending on data channels (including DCEP). r=drno,jesup
This allows sending and receiving arbitrarily (we limit to 1 GiB atm) sized
messages while not relying on the deprecated PPID fragmentation/reassembly
mode. The code already supports the ndata extension but it's not activated,
yet. Without the SCTP ndata extension, a large data channel message will
monopolise the SCTP association. While this is a problem, it is a temporary
solution until the extension is being activated. Keep in mind that every
application that uses data channels currently does fragmentation/reassembly on
application-level and it's unlikely that this will change until the popular
implementations (libwebrtc) implement EOR as well. Moreover, until the WebRTC
API specifies an API that hands over partial messages, doing application-level
fragmentation/reassembly is still useful for very large messages (sadly).
We fall back to PPID-based fragmentation/reassembly mode IFF a=max-message-size
is not set in the SDP and the negotiated amount of SCTP inbound streams is
exactly 256. Other implementations should avoid using this combination (to be
precise, other implementations should send a=max-message-size).
It also changes behaviour of RTCDataChannel.send which now raises TypeError in
case the message is too large for the other peer to receive. This is a
necessity to ensure that implementations that do not look at the EOR flag when
receiving are always able to receive our messages. Even if these
implementations do not set a=max-message-size, we use a safe default value (64
KiB, dictated by the spec) that every implementation should be able to receive,
with or without EOR support.
* Due to the use of explicit EOR, this required some major refactoring of all
send-related and deferred sending functions (which is now a lot less
complex). There's now only one place where `usrsctp_sendv` is being used.
* All data channel messages and DCEP messages will be sent without copying them
first. Only in case this fails (e.g. usrsctp's buffer is full), the message
will be copied and added to a buffer queue.
* Queued data channel messages will now be re-sent fairly (round-robin).
* Maximum message size and the PPID-based fragmentation are configurable using
about:config (media.peerconnection.sctp.force_ppid_fragmentation and
media.peerconnection.sctp.force_maximum_message_size).
* Enable interleaving of incoming messages for different streams (preparation
for SCTP ndata, has no effect until it is enabled).
* Enable interleaving of outgoing messages (disabled if SCTP ndata has not been
negotiated).
* Add pending messages flag to reduce performance impact from frequent calls to
SendDeferredMessages.
* Handle partial delivery events (for cases where a partially delivered message
is being aborted).
* Close a data channel/the connection in case the message is too large to be
handled (this is only applied in cases where the remote peer ignores our
announced local maximum message size).
* Various size_t to uint32_t conversions (message length) and back should be
safe now.
* Remove aUsingDtls/mUsingDtls from DataChannelConnection.
* Set maximum message size in SDP and in the data channel stack.
* Replace implicit NS_ENSURE_*'s with explicit NS_WARN_IF's.
* Add SetMaxMessageSize method for late-applying those signalling parameters
when a data channel has been created before the remote SDP was available.
* Limit remote maximum message size and add a GetMaxMessageSize method for a
future implementation of RTCSctpTransport.maxMessageSize.
MozReview-Commit-ID: FlmZrpC5zVI
--HG--
extra : rebase_source : 54e1b838c788a3abbded4fb32fe7c2788f8a9bc0
2017-07-26 14:18:54 +03:00
|
|
|
Send(nullptr, msgString, true, aRv);
|
2013-05-20 11:19:45 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2013-08-05 21:40:01 +04:00
|
|
|
nsDOMDataChannel::Send(const ArrayBufferView& aData, ErrorResult& aRv)
|
2013-05-20 11:19:45 +04:00
|
|
|
{
|
2015-02-10 01:34:50 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
|
2013-05-20 11:19:45 +04:00
|
|
|
|
Bug 999651, bug 995679, bug 1009952, bug 1011007, bug 991981. r=sfink, r=shu, r=jandem, r=jdm, r=luke, r=bbouvier, r=nmatsakis, r=bz, r=ehsan, r=jgilbert, r=smaug, r=sicking, r=terrence, r=bholley, r=bent, r=efaust, r=jorendorff
2014-05-28 01:32:41 +04:00
|
|
|
aData.ComputeLengthAndData();
|
|
|
|
|
|
|
|
static_assert(sizeof(*aData.Data()) == 1, "byte-sized data required");
|
|
|
|
|
2013-05-20 11:19:45 +04:00
|
|
|
uint32_t len = aData.Length();
|
|
|
|
char* data = reinterpret_cast<char*>(aData.Data());
|
|
|
|
|
|
|
|
nsDependentCSubstring msgString(data, len);
|
Bug 979417 - Implement EOR when receiving and explicit EOR when sending on data channels (including DCEP). r=drno,jesup
This allows sending and receiving arbitrarily (we limit to 1 GiB atm) sized
messages while not relying on the deprecated PPID fragmentation/reassembly
mode. The code already supports the ndata extension but it's not activated,
yet. Without the SCTP ndata extension, a large data channel message will
monopolise the SCTP association. While this is a problem, it is a temporary
solution until the extension is being activated. Keep in mind that every
application that uses data channels currently does fragmentation/reassembly on
application-level and it's unlikely that this will change until the popular
implementations (libwebrtc) implement EOR as well. Moreover, until the WebRTC
API specifies an API that hands over partial messages, doing application-level
fragmentation/reassembly is still useful for very large messages (sadly).
We fall back to PPID-based fragmentation/reassembly mode IFF a=max-message-size
is not set in the SDP and the negotiated amount of SCTP inbound streams is
exactly 256. Other implementations should avoid using this combination (to be
precise, other implementations should send a=max-message-size).
It also changes behaviour of RTCDataChannel.send which now raises TypeError in
case the message is too large for the other peer to receive. This is a
necessity to ensure that implementations that do not look at the EOR flag when
receiving are always able to receive our messages. Even if these
implementations do not set a=max-message-size, we use a safe default value (64
KiB, dictated by the spec) that every implementation should be able to receive,
with or without EOR support.
* Due to the use of explicit EOR, this required some major refactoring of all
send-related and deferred sending functions (which is now a lot less
complex). There's now only one place where `usrsctp_sendv` is being used.
* All data channel messages and DCEP messages will be sent without copying them
first. Only in case this fails (e.g. usrsctp's buffer is full), the message
will be copied and added to a buffer queue.
* Queued data channel messages will now be re-sent fairly (round-robin).
* Maximum message size and the PPID-based fragmentation are configurable using
about:config (media.peerconnection.sctp.force_ppid_fragmentation and
media.peerconnection.sctp.force_maximum_message_size).
* Enable interleaving of incoming messages for different streams (preparation
for SCTP ndata, has no effect until it is enabled).
* Enable interleaving of outgoing messages (disabled if SCTP ndata has not been
negotiated).
* Add pending messages flag to reduce performance impact from frequent calls to
SendDeferredMessages.
* Handle partial delivery events (for cases where a partially delivered message
is being aborted).
* Close a data channel/the connection in case the message is too large to be
handled (this is only applied in cases where the remote peer ignores our
announced local maximum message size).
* Various size_t to uint32_t conversions (message length) and back should be
safe now.
* Remove aUsingDtls/mUsingDtls from DataChannelConnection.
* Set maximum message size in SDP and in the data channel stack.
* Replace implicit NS_ENSURE_*'s with explicit NS_WARN_IF's.
* Add SetMaxMessageSize method for late-applying those signalling parameters
when a data channel has been created before the remote SDP was available.
* Limit remote maximum message size and add a GetMaxMessageSize method for a
future implementation of RTCSctpTransport.maxMessageSize.
MozReview-Commit-ID: FlmZrpC5zVI
--HG--
extra : rebase_source : 54e1b838c788a3abbded4fb32fe7c2788f8a9bc0
2017-07-26 14:18:54 +03:00
|
|
|
Send(nullptr, msgString, true, aRv);
|
2013-05-20 11:19:45 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsDOMDataChannel::Send(nsIInputStream* aMsgStream,
|
|
|
|
const nsACString& aMsgString,
|
|
|
|
bool aIsBinary,
|
|
|
|
ErrorResult& aRv)
|
2012-10-04 03:51:47 +04:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2016-10-20 08:03:44 +03:00
|
|
|
uint16_t state = mozilla::DataChannel::CLOSED;
|
|
|
|
if (!mSentClose) {
|
|
|
|
state = mDataChannel->GetReadyState();
|
|
|
|
}
|
2012-10-04 03:51:47 +04:00
|
|
|
|
|
|
|
// In reality, the DataChannel protocol allows this, but we want it to
|
|
|
|
// look like WebSockets
|
|
|
|
if (state == mozilla::DataChannel::CONNECTING) {
|
2013-05-20 11:19:45 +04:00
|
|
|
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
|
|
|
return;
|
2012-10-04 03:51:47 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (state == mozilla::DataChannel::CLOSING ||
|
|
|
|
state == mozilla::DataChannel::CLOSED) {
|
2013-05-20 11:19:45 +04:00
|
|
|
return;
|
2012-10-04 03:51:47 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(state == mozilla::DataChannel::OPEN,
|
2013-05-20 11:19:45 +04:00
|
|
|
"Unknown state in nsDOMDataChannel::Send");
|
2012-10-04 03:51:47 +04:00
|
|
|
|
2013-05-20 11:19:45 +04:00
|
|
|
if (aMsgStream) {
|
Bug 979417 - Implement EOR when receiving and explicit EOR when sending on data channels (including DCEP). r=drno,jesup
This allows sending and receiving arbitrarily (we limit to 1 GiB atm) sized
messages while not relying on the deprecated PPID fragmentation/reassembly
mode. The code already supports the ndata extension but it's not activated,
yet. Without the SCTP ndata extension, a large data channel message will
monopolise the SCTP association. While this is a problem, it is a temporary
solution until the extension is being activated. Keep in mind that every
application that uses data channels currently does fragmentation/reassembly on
application-level and it's unlikely that this will change until the popular
implementations (libwebrtc) implement EOR as well. Moreover, until the WebRTC
API specifies an API that hands over partial messages, doing application-level
fragmentation/reassembly is still useful for very large messages (sadly).
We fall back to PPID-based fragmentation/reassembly mode IFF a=max-message-size
is not set in the SDP and the negotiated amount of SCTP inbound streams is
exactly 256. Other implementations should avoid using this combination (to be
precise, other implementations should send a=max-message-size).
It also changes behaviour of RTCDataChannel.send which now raises TypeError in
case the message is too large for the other peer to receive. This is a
necessity to ensure that implementations that do not look at the EOR flag when
receiving are always able to receive our messages. Even if these
implementations do not set a=max-message-size, we use a safe default value (64
KiB, dictated by the spec) that every implementation should be able to receive,
with or without EOR support.
* Due to the use of explicit EOR, this required some major refactoring of all
send-related and deferred sending functions (which is now a lot less
complex). There's now only one place where `usrsctp_sendv` is being used.
* All data channel messages and DCEP messages will be sent without copying them
first. Only in case this fails (e.g. usrsctp's buffer is full), the message
will be copied and added to a buffer queue.
* Queued data channel messages will now be re-sent fairly (round-robin).
* Maximum message size and the PPID-based fragmentation are configurable using
about:config (media.peerconnection.sctp.force_ppid_fragmentation and
media.peerconnection.sctp.force_maximum_message_size).
* Enable interleaving of incoming messages for different streams (preparation
for SCTP ndata, has no effect until it is enabled).
* Enable interleaving of outgoing messages (disabled if SCTP ndata has not been
negotiated).
* Add pending messages flag to reduce performance impact from frequent calls to
SendDeferredMessages.
* Handle partial delivery events (for cases where a partially delivered message
is being aborted).
* Close a data channel/the connection in case the message is too large to be
handled (this is only applied in cases where the remote peer ignores our
announced local maximum message size).
* Various size_t to uint32_t conversions (message length) and back should be
safe now.
* Remove aUsingDtls/mUsingDtls from DataChannelConnection.
* Set maximum message size in SDP and in the data channel stack.
* Replace implicit NS_ENSURE_*'s with explicit NS_WARN_IF's.
* Add SetMaxMessageSize method for late-applying those signalling parameters
when a data channel has been created before the remote SDP was available.
* Limit remote maximum message size and add a GetMaxMessageSize method for a
future implementation of RTCSctpTransport.maxMessageSize.
MozReview-Commit-ID: FlmZrpC5zVI
--HG--
extra : rebase_source : 54e1b838c788a3abbded4fb32fe7c2788f8a9bc0
2017-07-26 14:18:54 +03:00
|
|
|
mDataChannel->SendBinaryStream(aMsgStream, aRv);
|
2012-10-04 03:51:47 +04:00
|
|
|
} else {
|
2013-05-20 11:19:45 +04:00
|
|
|
if (aIsBinary) {
|
Bug 979417 - Implement EOR when receiving and explicit EOR when sending on data channels (including DCEP). r=drno,jesup
This allows sending and receiving arbitrarily (we limit to 1 GiB atm) sized
messages while not relying on the deprecated PPID fragmentation/reassembly
mode. The code already supports the ndata extension but it's not activated,
yet. Without the SCTP ndata extension, a large data channel message will
monopolise the SCTP association. While this is a problem, it is a temporary
solution until the extension is being activated. Keep in mind that every
application that uses data channels currently does fragmentation/reassembly on
application-level and it's unlikely that this will change until the popular
implementations (libwebrtc) implement EOR as well. Moreover, until the WebRTC
API specifies an API that hands over partial messages, doing application-level
fragmentation/reassembly is still useful for very large messages (sadly).
We fall back to PPID-based fragmentation/reassembly mode IFF a=max-message-size
is not set in the SDP and the negotiated amount of SCTP inbound streams is
exactly 256. Other implementations should avoid using this combination (to be
precise, other implementations should send a=max-message-size).
It also changes behaviour of RTCDataChannel.send which now raises TypeError in
case the message is too large for the other peer to receive. This is a
necessity to ensure that implementations that do not look at the EOR flag when
receiving are always able to receive our messages. Even if these
implementations do not set a=max-message-size, we use a safe default value (64
KiB, dictated by the spec) that every implementation should be able to receive,
with or without EOR support.
* Due to the use of explicit EOR, this required some major refactoring of all
send-related and deferred sending functions (which is now a lot less
complex). There's now only one place where `usrsctp_sendv` is being used.
* All data channel messages and DCEP messages will be sent without copying them
first. Only in case this fails (e.g. usrsctp's buffer is full), the message
will be copied and added to a buffer queue.
* Queued data channel messages will now be re-sent fairly (round-robin).
* Maximum message size and the PPID-based fragmentation are configurable using
about:config (media.peerconnection.sctp.force_ppid_fragmentation and
media.peerconnection.sctp.force_maximum_message_size).
* Enable interleaving of incoming messages for different streams (preparation
for SCTP ndata, has no effect until it is enabled).
* Enable interleaving of outgoing messages (disabled if SCTP ndata has not been
negotiated).
* Add pending messages flag to reduce performance impact from frequent calls to
SendDeferredMessages.
* Handle partial delivery events (for cases where a partially delivered message
is being aborted).
* Close a data channel/the connection in case the message is too large to be
handled (this is only applied in cases where the remote peer ignores our
announced local maximum message size).
* Various size_t to uint32_t conversions (message length) and back should be
safe now.
* Remove aUsingDtls/mUsingDtls from DataChannelConnection.
* Set maximum message size in SDP and in the data channel stack.
* Replace implicit NS_ENSURE_*'s with explicit NS_WARN_IF's.
* Add SetMaxMessageSize method for late-applying those signalling parameters
when a data channel has been created before the remote SDP was available.
* Limit remote maximum message size and add a GetMaxMessageSize method for a
future implementation of RTCSctpTransport.maxMessageSize.
MozReview-Commit-ID: FlmZrpC5zVI
--HG--
extra : rebase_source : 54e1b838c788a3abbded4fb32fe7c2788f8a9bc0
2017-07-26 14:18:54 +03:00
|
|
|
mDataChannel->SendBinaryMsg(aMsgString, aRv);
|
2012-10-04 03:51:47 +04:00
|
|
|
} else {
|
Bug 979417 - Implement EOR when receiving and explicit EOR when sending on data channels (including DCEP). r=drno,jesup
This allows sending and receiving arbitrarily (we limit to 1 GiB atm) sized
messages while not relying on the deprecated PPID fragmentation/reassembly
mode. The code already supports the ndata extension but it's not activated,
yet. Without the SCTP ndata extension, a large data channel message will
monopolise the SCTP association. While this is a problem, it is a temporary
solution until the extension is being activated. Keep in mind that every
application that uses data channels currently does fragmentation/reassembly on
application-level and it's unlikely that this will change until the popular
implementations (libwebrtc) implement EOR as well. Moreover, until the WebRTC
API specifies an API that hands over partial messages, doing application-level
fragmentation/reassembly is still useful for very large messages (sadly).
We fall back to PPID-based fragmentation/reassembly mode IFF a=max-message-size
is not set in the SDP and the negotiated amount of SCTP inbound streams is
exactly 256. Other implementations should avoid using this combination (to be
precise, other implementations should send a=max-message-size).
It also changes behaviour of RTCDataChannel.send which now raises TypeError in
case the message is too large for the other peer to receive. This is a
necessity to ensure that implementations that do not look at the EOR flag when
receiving are always able to receive our messages. Even if these
implementations do not set a=max-message-size, we use a safe default value (64
KiB, dictated by the spec) that every implementation should be able to receive,
with or without EOR support.
* Due to the use of explicit EOR, this required some major refactoring of all
send-related and deferred sending functions (which is now a lot less
complex). There's now only one place where `usrsctp_sendv` is being used.
* All data channel messages and DCEP messages will be sent without copying them
first. Only in case this fails (e.g. usrsctp's buffer is full), the message
will be copied and added to a buffer queue.
* Queued data channel messages will now be re-sent fairly (round-robin).
* Maximum message size and the PPID-based fragmentation are configurable using
about:config (media.peerconnection.sctp.force_ppid_fragmentation and
media.peerconnection.sctp.force_maximum_message_size).
* Enable interleaving of incoming messages for different streams (preparation
for SCTP ndata, has no effect until it is enabled).
* Enable interleaving of outgoing messages (disabled if SCTP ndata has not been
negotiated).
* Add pending messages flag to reduce performance impact from frequent calls to
SendDeferredMessages.
* Handle partial delivery events (for cases where a partially delivered message
is being aborted).
* Close a data channel/the connection in case the message is too large to be
handled (this is only applied in cases where the remote peer ignores our
announced local maximum message size).
* Various size_t to uint32_t conversions (message length) and back should be
safe now.
* Remove aUsingDtls/mUsingDtls from DataChannelConnection.
* Set maximum message size in SDP and in the data channel stack.
* Replace implicit NS_ENSURE_*'s with explicit NS_WARN_IF's.
* Add SetMaxMessageSize method for late-applying those signalling parameters
when a data channel has been created before the remote SDP was available.
* Limit remote maximum message size and add a GetMaxMessageSize method for a
future implementation of RTCSctpTransport.maxMessageSize.
MozReview-Commit-ID: FlmZrpC5zVI
--HG--
extra : rebase_source : 54e1b838c788a3abbded4fb32fe7c2788f8a9bc0
2017-07-26 14:18:54 +03:00
|
|
|
mDataChannel->SendMsg(aMsgString, aRv);
|
2012-10-04 03:51:47 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsDOMDataChannel::DoOnMessageAvailable(const nsACString& aData,
|
|
|
|
bool aBinary)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
|
|
|
LOG(("DoOnMessageAvailable%s\n",aBinary ? ((mBinaryType == DC_BINARY_TYPE_BLOB) ? " (blob)" : " (binary)") : ""));
|
|
|
|
|
|
|
|
nsresult rv = CheckInnerWindowCorrectness();
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2014-06-19 11:21:14 +04:00
|
|
|
AutoJSAPI jsapi;
|
2014-06-25 14:17:17 +04:00
|
|
|
if (NS_WARN_IF(!jsapi.Init(GetOwner()))) {
|
2014-05-23 13:18:37 +04:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
JSContext* cx = jsapi.cx();
|
2012-10-04 03:51:47 +04:00
|
|
|
|
2013-05-08 06:34:56 +04:00
|
|
|
JS::Rooted<JS::Value> jsData(cx);
|
2012-10-04 03:51:47 +04:00
|
|
|
|
|
|
|
if (aBinary) {
|
|
|
|
if (mBinaryType == DC_BINARY_TYPE_BLOB) {
|
2016-10-25 08:53:54 +03:00
|
|
|
RefPtr<Blob> blob =
|
|
|
|
Blob::CreateStringBlob(GetOwner(), aData, EmptyString());
|
|
|
|
MOZ_ASSERT(blob);
|
|
|
|
|
|
|
|
if (!ToJSValue(cx, blob, &jsData)) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2012-10-04 03:51:47 +04:00
|
|
|
} else if (mBinaryType == DC_BINARY_TYPE_ARRAYBUFFER) {
|
2013-05-08 06:34:56 +04:00
|
|
|
JS::Rooted<JSObject*> arrayBuf(cx);
|
|
|
|
rv = nsContentUtils::CreateArrayBuffer(cx, aData, arrayBuf.address());
|
2012-10-04 03:51:47 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2015-07-01 07:09:46 +03:00
|
|
|
jsData.setObject(*arrayBuf);
|
2012-10-04 03:51:47 +04:00
|
|
|
} else {
|
2016-12-03 00:46:53 +03:00
|
|
|
MOZ_CRASH("Unknown binary type!");
|
2012-10-04 03:51:47 +04:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
NS_ConvertUTF8toUTF16 utf16data(aData);
|
|
|
|
JSString* jsString = JS_NewUCStringCopyN(cx, utf16data.get(), utf16data.Length());
|
|
|
|
NS_ENSURE_TRUE(jsString, NS_ERROR_FAILURE);
|
|
|
|
|
2015-06-30 21:20:56 +03:00
|
|
|
jsData.setString(jsString);
|
2012-10-04 03:51:47 +04:00
|
|
|
}
|
|
|
|
|
2016-10-12 16:17:10 +03:00
|
|
|
RefPtr<MessageEvent> event = new MessageEvent(this, nullptr, nullptr);
|
2012-10-04 03:51:47 +04:00
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
event->InitMessageEvent(nullptr, NS_LITERAL_STRING("message"), false, false,
|
2016-10-25 08:48:05 +03:00
|
|
|
jsData, mOrigin, EmptyString(), nullptr,
|
|
|
|
Sequence<OwningNonNull<MessagePort>>());
|
2012-10-04 03:51:47 +04:00
|
|
|
event->SetTrusted(true);
|
|
|
|
|
|
|
|
LOG(("%p(%p): %s - Dispatching\n",this,(void*)mDataChannel,__FUNCTION__));
|
2017-08-06 20:28:52 +03:00
|
|
|
bool dummy;
|
|
|
|
rv = DispatchEvent(static_cast<Event*>(event), &dummy);
|
2012-10-04 03:51:47 +04:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
NS_WARNING("Failed to dispatch the message event!!!");
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsDOMDataChannel::OnMessageAvailable(nsISupports* aContext,
|
|
|
|
const nsACString& aMessage)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
return DoOnMessageAvailable(aMessage, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsDOMDataChannel::OnBinaryMessageAvailable(nsISupports* aContext,
|
|
|
|
const nsACString& aMessage)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
return DoOnMessageAvailable(aMessage, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsDOMDataChannel::OnSimpleEvent(nsISupports* aContext, const nsAString& aName)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
|
|
|
nsresult rv = CheckInnerWindowCorrectness();
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
|
2012-10-04 03:51:47 +04:00
|
|
|
|
2015-11-13 03:09:42 +03:00
|
|
|
event->InitEvent(aName, false, false);
|
2012-10-04 03:51:47 +04:00
|
|
|
event->SetTrusted(true);
|
|
|
|
|
2017-08-06 20:28:52 +03:00
|
|
|
bool dummy;
|
|
|
|
return DispatchEvent(event, &dummy);
|
2012-10-04 03:51:47 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsDOMDataChannel::OnChannelConnected(nsISupports* aContext)
|
|
|
|
{
|
|
|
|
LOG(("%p(%p): %s - Dispatching\n",this,(void*)mDataChannel,__FUNCTION__));
|
|
|
|
|
|
|
|
return OnSimpleEvent(aContext, NS_LITERAL_STRING("open"));
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsDOMDataChannel::OnChannelClosed(nsISupports* aContext)
|
|
|
|
{
|
2016-04-26 07:28:53 +03:00
|
|
|
nsresult rv;
|
|
|
|
// so we don't have to worry if we're notified from different paths in
|
|
|
|
// the underlying code
|
|
|
|
if (!mSentClose) {
|
2016-10-20 08:03:44 +03:00
|
|
|
// Ok, we're done with it.
|
|
|
|
mDataChannel->ReleaseConnection();
|
2016-04-26 07:28:53 +03:00
|
|
|
LOG(("%p(%p): %s - Dispatching\n",this,(void*)mDataChannel,__FUNCTION__));
|
|
|
|
|
|
|
|
rv = OnSimpleEvent(aContext, NS_LITERAL_STRING("close"));
|
|
|
|
// no more events can happen
|
|
|
|
mSentClose = true;
|
|
|
|
} else {
|
|
|
|
rv = NS_OK;
|
|
|
|
}
|
|
|
|
DontKeepAliveAnyMore();
|
|
|
|
return rv;
|
2012-10-04 03:51:47 +04:00
|
|
|
}
|
|
|
|
|
2015-09-29 02:02:23 +03:00
|
|
|
nsresult
|
|
|
|
nsDOMDataChannel::OnBufferLow(nsISupports* aContext)
|
|
|
|
{
|
|
|
|
LOG(("%p(%p): %s - Dispatching\n",this,(void*)mDataChannel,__FUNCTION__));
|
|
|
|
|
|
|
|
return OnSimpleEvent(aContext, NS_LITERAL_STRING("bufferedamountlow"));
|
|
|
|
}
|
|
|
|
|
2016-04-26 07:28:53 +03:00
|
|
|
nsresult
|
|
|
|
nsDOMDataChannel::NotBuffered(nsISupports* aContext)
|
|
|
|
{
|
|
|
|
// In the rare case that we held off GC to let the buffer drain
|
|
|
|
UpdateMustKeepAlive();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-10-04 03:51:47 +04:00
|
|
|
void
|
|
|
|
nsDOMDataChannel::AppReady()
|
|
|
|
{
|
2016-10-20 08:03:44 +03:00
|
|
|
if (!mSentClose) { // may not be possible, simpler to just test anyways
|
|
|
|
mDataChannel->AppReady();
|
|
|
|
}
|
2012-10-04 03:51:47 +04:00
|
|
|
}
|
|
|
|
|
2016-04-26 07:28:53 +03:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Methods that keep alive the DataChannel object when:
|
|
|
|
// 1. the object has registered event listeners that can be triggered
|
|
|
|
// ("strong event listeners");
|
|
|
|
// 2. there are outgoing not sent messages.
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void
|
|
|
|
nsDOMDataChannel::UpdateMustKeepAlive()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
|
|
|
if (!mCheckMustKeepAlive) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool shouldKeepAlive = false;
|
|
|
|
uint16_t readyState = mDataChannel->GetReadyState();
|
|
|
|
|
|
|
|
switch (readyState)
|
|
|
|
{
|
|
|
|
case DataChannel::CONNECTING:
|
|
|
|
case DataChannel::WAITING_TO_OPEN:
|
|
|
|
{
|
|
|
|
if (mListenerManager &&
|
|
|
|
(mListenerManager->HasListenersFor(nsGkAtoms::onopen) ||
|
|
|
|
mListenerManager->HasListenersFor(nsGkAtoms::onmessage) ||
|
|
|
|
mListenerManager->HasListenersFor(nsGkAtoms::onerror) ||
|
|
|
|
mListenerManager->HasListenersFor(nsGkAtoms::onbufferedamountlow) ||
|
|
|
|
mListenerManager->HasListenersFor(nsGkAtoms::onclose))) {
|
|
|
|
shouldKeepAlive = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DataChannel::OPEN:
|
|
|
|
case DataChannel::CLOSING:
|
|
|
|
{
|
|
|
|
if (mDataChannel->GetBufferedAmount() != 0 ||
|
|
|
|
(mListenerManager &&
|
|
|
|
(mListenerManager->HasListenersFor(nsGkAtoms::onmessage) ||
|
|
|
|
mListenerManager->HasListenersFor(nsGkAtoms::onerror) ||
|
|
|
|
mListenerManager->HasListenersFor(nsGkAtoms::onbufferedamountlow) ||
|
|
|
|
mListenerManager->HasListenersFor(nsGkAtoms::onclose)))) {
|
|
|
|
shouldKeepAlive = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DataChannel::CLOSED:
|
|
|
|
{
|
|
|
|
shouldKeepAlive = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mSelfRef && !shouldKeepAlive) {
|
2017-07-14 09:49:22 +03:00
|
|
|
ReleaseSelf();
|
2016-04-26 07:28:53 +03:00
|
|
|
} else if (!mSelfRef && shouldKeepAlive) {
|
|
|
|
mSelfRef = this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsDOMDataChannel::DontKeepAliveAnyMore()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
|
|
|
if (mSelfRef) {
|
2017-07-14 09:49:22 +03:00
|
|
|
// Since we're on MainThread, force an eventloop trip to avoid deleting
|
|
|
|
// ourselves.
|
|
|
|
ReleaseSelf();
|
2016-04-26 07:28:53 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
mCheckMustKeepAlive = false;
|
|
|
|
}
|
|
|
|
|
2017-07-14 09:49:22 +03:00
|
|
|
void
|
|
|
|
nsDOMDataChannel::ReleaseSelf()
|
|
|
|
{
|
|
|
|
// release our self-reference (safely) by putting it in an event (always)
|
|
|
|
NS_ReleaseOnMainThreadSystemGroup("nsDOMDataChannel::mSelfRef",
|
|
|
|
mSelfRef.forget(), true);
|
|
|
|
}
|
|
|
|
|
2016-04-26 07:28:53 +03:00
|
|
|
void
|
2017-10-03 01:05:19 +03:00
|
|
|
nsDOMDataChannel::EventListenerAdded(nsAtom* aType)
|
2016-04-26 07:28:53 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
UpdateMustKeepAlive();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-10-03 01:05:19 +03:00
|
|
|
nsDOMDataChannel::EventListenerRemoved(nsAtom* aType)
|
2016-04-26 07:28:53 +03:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
UpdateMustKeepAlive();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-10-04 03:51:47 +04:00
|
|
|
/* static */
|
|
|
|
nsresult
|
2014-03-15 23:00:17 +04:00
|
|
|
NS_NewDOMDataChannel(already_AddRefed<mozilla::DataChannel>&& aDataChannel,
|
2016-01-30 20:05:36 +03:00
|
|
|
nsPIDOMWindowInner* aWindow,
|
2012-10-04 03:51:47 +04:00
|
|
|
nsIDOMDataChannel** aDomDataChannel)
|
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsDOMDataChannel> domdc =
|
2014-01-07 06:53:23 +04:00
|
|
|
new nsDOMDataChannel(aDataChannel, aWindow);
|
2012-10-04 03:51:47 +04:00
|
|
|
|
|
|
|
nsresult rv = domdc->Init(aWindow);
|
|
|
|
NS_ENSURE_SUCCESS(rv,rv);
|
|
|
|
|
|
|
|
return CallQueryInterface(domdc, aDomDataChannel);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
void
|
|
|
|
NS_DataChannelAppReady(nsIDOMDataChannel* aDomDataChannel)
|
|
|
|
{
|
|
|
|
((nsDOMDataChannel *)aDomDataChannel)->AppReady();
|
|
|
|
}
|