WebRTC DataChannel flow/control/back-pressure - javascript

The RTCDataChannel API does not provide any kind of flow/control or back-pressure, does this mean, that a sender could, theoretically, crash the browser of the receiver ? In my opinion the browser, (Chrome, Firefox, etc. all use SCTP under the hood), reads from the SCTP connection and schedules to run the js-callback consuming the packet. If the event queue cannot not keep up with the sender, the browser basically reads continuously packets while storing the packets in a buffer, which grows indefinitely. So when you connect two browsers, the sender can actually always overwhelm the other one, because there is no barrier like TCP receive windows or something similar.
This applies to the websocket api as well.
Do I just miss something or are these API just broken ? If I'm right, this would be a severe security issue when talking to unauthenticated browsers (in a torrent scenario for instance).

The webrtc data channel used to be based on UDP. During that time there was artificial throttling imposed by the browser in order to prevent network flooding. This was the case until chrome v32, I believe.
Nowadays the data channel is based on SCTP which has build-in flow control (FC) and there is no browser throttling any more (thank God). The parameters that control FC are not exposed through the API but that doesn't mean there is no FC.
I am not familiar with the implementation of webrtc in Chrome/FF but I don't think you can crash the browser with a simple flood attack. The "producer is faster than the consumer" is a pretty old problem.
That said, I have been working with the data channel, for more than an year now and have seen my browser crash almost on a daily basis, so there are probably many bugs in the webrtc implementation. Hopefully they won't pose any threat to security.
Sending big chunks of data useing webrtc data channel is not a particularly pleasant experience. The API doesn't offer a "channel is ready for write" callback or anything of the sort, so, yes!, you have to poll the bufferedamount value and try to keep it inside an optimal window. To add insult to injury bufferedamount used to be broken under Windows versions of Chrome, it was always 0. But I think they fixed this in chrome v37 or around that time.
IMHO the webrtc API is not very well thought through but it does the job and honestly I cannot think of any js API that is well thought through.

Related

How to get around browser's 6 concurrent connections per domain limit?

As the title says, how do I get around a browser's 6 connections per domain limit?
I have a web app that needs to download data from the server as quickly as possible. Currently, I have up to about a dozen connections being opened at once, but in the network tab I see that several of the connections are stalled (Chrome) or blocked (Firefox) shown in gray:
After some digging around I believe this is due to Chrome's 6 connections per domain limit. How do I get around this?
After some searching, I have some reason to believe that one of these options may work, but I would like to know which option is the best (not a hack):
Use several subdomains (a.mysite.com, b.mysite.com etc...) and point them to the main server so that Chrome believes that they are different sites. This sounds like the most "hacky" option in my opinion and I don't know how long this will actually work for.
Some answers suggest that HTTP2 isn't restricted by the 6 connection limit, but when I look into using HTTP2 it seems like if the browser supports it then it will use it. So I guess this doesn't actually work since I'm still getting the stalled message in Chrome's most recent version.
I'm currently using fetch to get a stream of data from the server, would using Web Sockets or WebRTC instead not be limited by the 6 connection limit?
What other options are there?
I don't think webRTC is limited to 6 connections per domain, since it is often used for P2P mesh connections where that restriction would make no sense.
But I'd be surprised if you got better performance out of 20 datachannels than one HTTP2 connection since the webRTC datachannel is really not optimized for throughput.
You might also want to look at using Service Workers to work around the problem in a different way.

Is there any way to predict if the client's network will support WebRTC peer connection?

I am creating a video conversation App and there's a device configuration check I run every time anyone wants to access the system. I could check browser getUserMedia, RTCPeerConnection, Also could check internet speed. But in many cases, RTCPeerConnection can still fail from that client's side because of some specific network restrictions/issues.
Is there any way to predict if a client's network will support video/audio streaming through RTCPeerConnection?
Kind of! Here are something things people have done, not perfect but you can explore from here.
Establish a DataChannel to another PeerConnection in the same tab, but run all communication through a TURN server. You can measure the quality of the connection without requiring any user interaction (allowing webcam access etc...)
You could also do some basic network mapping! Like determining your NAT Type, you could get some hints at if you need a TURN server (or can do P2P) before the call. This will never get you a perfect answer, but at least some data!
I don't have a single good answer for you though, but these are some good places to start.
With the hint from the Accepted answer, I Initially created a Gist, later created a full fledge set of tools to determine if a certain webRTC feature works on not. this includes testing to see if RTCPeerConnection works, and also test for some other features as well.
Here's the Github link: https://github.com/theanam/webrtc-test-suite

Do websockets allow for p2p (browser to browser) communication?

To clarify when I ask about browser to browser communication I mean without a server in between forwarding message. I would like to implement something like this for a game. If p2p in websockets isn't possible are there similar alternatives? Any help is appreciated.
No. Browsers can only initiate WebSockets connections, not receive them. The W3C browser API spec only defines how to start an outbound connection.
You can make an application that would both initiate and accept WebSockets connections, but browsers do not do this.
You might look at Pusher App which you could use to build a WebSockets application with multiple clients. The service provides up to 20 simultaneous WebSockets clients for free (you can pay for higher scaling).
Update:
The WebRTC protocol and API is making rapid progress and allows a Data Channel to be established between two peers (you still may need a STUN/TURN server for the initial NAT traversal and setup).
In theory it is possible with WebRTC DataChannel:
RTCDataChannel is a WebRTC API for high performance, low latency,
peer-to-peer communication of arbritary data. The API is
simple—similar to WebSocket—but communication occurs directly between
browsers, so RTCDataChannel can be much faster than WebSocket even if
a relay (TURN) server is required (when 'hole punching' to cope with
firewalls and NATs fails).
"In theory" because it isn't supported by a stable browser yet and you still need a relay server (TURN) if one of the browsers is behind a symmetric NAT. Nevertheless, it is a really promising feature.
Update: Chrome 26 and Firefox 22 support RTCDataChannel by default and Firefox 19-21 if you enable WebRTC by setting media.peerconnection.enabled to true (about:config).
I was reading about websocket and peer 2 peer and found PeerJS.
I still haven't made anything though, but by the examples it looks promising.
Now days it's possible, currently only Chrome,FF and Opera support it (desktop).
There's some libraries starting to pop up around the web right now, such as PeerJS and js-platform-p2p which pretty much simplifies things.
Simple and reliable cross browser supported way is to use http://httprelay.io with AJAX calls. It is also implements one to many communication what could be useful for game development.

How does Gmail do comet on Opera?

I would like to know how Gmail (or anyone else) does comet on Opera.
Here is what I know so far from my experiments.
It doesn't use the event-source tag which is broken in Opera 10.51.
It doesn't use iframe which displays a spinning throbber and a busy mouse cursor.
It doesn't use responseText on xmlhttprequest when readyState = 3 which is known to be broken on Opera.
I tried seeing how it was done in mibbit and etherpad, and I found that they both use long-polling.
Bounty
The bounty goes to whoever can tell me a method better than "event-source" for Opera comet streaming, or how gmail does streaming (or long-polling if it does that).
GMail uses BrowserChannel (Docs | Source), which is included in Google's Closure Library.
#fileoverview Definition of the BrowserChannel class. A BrowserChannel
simulates a bidirectional socket over HTTP. It is the basis of the
Gmail Chat IM connections to the server.
I really don't have any idea on what the answer is. But I know Opera supports server-events : http://my.opera.com/WebApplications/blog/show.dml/438711 . Maybe it's a step towards the anwser?
I'm not really sure either, but I think they use it within Opera Unite.
I think that rather cross-browser (including Opera) approach might be to stream data through an Adobe Flash application. Though it would introduce dependence on the Flash plugin and is not very popular because of that.
I am the author of an in progess C++ HTTP server that is compatible with goog.netBrowserChannel. You can find the docs I've written while studying the protocol here:
http://code.google.com/p/libevent-browserchannel-server/wiki/BrowserChannelProtocol
Long story short, BrowserChannel uses forever frames on IE and XHR streaming on all other browsers. The protocol is divided into several phases, the first of which is network testing:
1) test the network to ensure response "streaming" is supported (in other words no buffering proxy exists)
2) check access to a variety of network prefixes (to make sure the network admin has not blocked access to chat)
Then the actual data transmission can start. Data is divided into two channels (forward and back). The back channel is a series of long lived (about 4 mins each) requests used for the server to "stream" content to the client. To do so HTTP chunked encoding is used. The client does it's best to make sure that one backchannel is always open. The server will close it about every 4 mins after which the client will open a new backchannel. The forward channel is used to send data from the client to the server. This pushing of data is done as necessary.

Long held AJAX connections being blocked by Anti-Virus

Ok, this is downright bizarre. I am building a web application that relies on long held HTTP connection using COMET, and using this to stream data from the server to the application.
Now, the problem is that this does not seem to go well with some anti-virus programs. We are now on beta, and some users are facing problems with the application when the anti-virus is enabled. It's not just one specific anti-virus either.. I found this work around for Avast when I looked online: http://avricot.com/blog/index.php?post/2009/05/20/Comet-and-ajax-with-Avast-s-shield-web-:-The-salvation-or-not
However, anyone here has any suggestions on how to handled this? Should I send any specific header to please these security programs?
This is a tough one. The kind of anti-virus feature that causes this tries to prevent malicious code running in the browser from uploading your personal data to a remote server. To do that, the anti-virus tries to buffer all outgoing traffic before it hits the network, and scan it for pre-defined strings.
This works when the application sends a complete HTTP request on the socket, because the anti-virus sees the end of the the HTTP request and knows that it can stop scanning and send the data.
In your case, there's probably just a header without a length field, so until you send enough data to fill the anti-virus's buffer, nothing will be written to the network.
If that's not a good reason to turn that particular feature off, I don't know what is. I ran into this with AVast and McAfee - at this point, the rest of the anti-virus industry is probably doing something like that. Specifically, I ran into this with McAfee's Personal Information Protection feature, which as far as I can tell, is simply too buggy to use.
If you can, just keep sending data on the socket, or send the data in HTTP messages that have a length field. I tried reporting this to a couple of anti-virus vendors - one of them fixed it, the other one didn't, to the best of my knowledge.
Of course, this sort of feature is completely useless. All a malicious application would need to do to get around it is to ROT13 the data before sending it.
Try using https instead of http. There are scanners that intercept https, too, but they're less common and the feature defaulted to off last time I checked. It also broke Firefox SSL connectivity when activated, so I think very few people will activate it and the vendor will hopefully kill the feature.
The problem is that some files can't be scanned in order - later parts are required to determine if the earlier parts are malicious.
So scanners have a problem with channels that are streaming data. I doubt your stream of data is able to be recognised as a clean file type, so the scanner is attempting to scan the data as best it can, and I guess holding up your stream in the process.
The only think I can suggest is to do the data transfer in small transactions, and use the COMET connection for notification only (closing each channel after a single notification).
If you use a non-standard port for your web requests, you may be able to work around this, there are a number of other issues, namely that this will be considered cross-domain by many browsers. Not sure if I have a better suggestion to offer here. It really depends on how the AV program intercepts a given port's traffic.
I think you're going to be forced to break the connection and reconnect. What does your code do if the connection goes down in an outage situation? I had a similar problem with a firewall once. The code had to detect the disconnect, then reconnect. I like the answer about breaking up the data transfer.

Categories