
WebRTC: the future of web games - getkey
https://getkey.eu/blog/5862b0cf/webrtc:-the-future-of-web-games
======
Matheus28
I'm the guy that made Agar.io, Diep.io and a few smaller games. I analyzed the
possibility of using WebRTC in my games several times so far, but it seems
that right now, it's still hard to use in a server-client architecture. You
need to bring this [1] behemoth and all of its dependencies to your project
dependencies on the server side, even though you only care about a tiny bit of
it (unreliable data channels). It's unlikely that people will start using it
until there is an easy stripped-down version that only deals with data
channels.

[1]
[https://chromium.googlesource.com/external/webrtc](https://chromium.googlesource.com/external/webrtc)

~~~
pthatcherg
Hi, I'm a member of the WebRTC team at Google, and I wrote a lot of the data
channel and network code that's part of that behemoth.

I'm glad you got this to work :). I've always hoped someone would do exactly
what you've done (use the data channel code on a server to do low-latency
client<->server communication).

We're aware of the difficulty and are actively working on making it easier to
work with just he components you need for data channels (ICE, DTLS, and SCTP).
It might take a while, but it's one of our goals.

~~~
comboy
Where does the low latency in WebRTC come from? Is it just packet ordering in
TCP or is there something more to it?

~~~
pthatcherg
You can receive data messages our of order. That's all there is to it. If you
could receive TCP out of order, you could just use TCP.

~~~
gravypod
Is there a way to specifiy ordering on specific packet types?

~~~
oneweekwonder
From the Article:

    
    
      Because SCTP is configurable, we can open multiple data channels with different settings, which saves us tons of work!
      Typically we have:
      an unreliable and unordered data channel for game state data and user inputs
      a reliable and ordered data channel for chat messages, scores and deaths

------
AshleysBrain
We've been using WebRTC Datachannels for multiplayer gaming in the browser in
our game editor Construct 2 (www.scirra.com) for a couple of years now.
Generally they work great! However the main problem we have is switching tab
suspends the game, which if you're acting as the host, freezes the game for
_everybody_. This is really inconvenient. There ought to be some way to exempt
tabs with WebRTC connections from being suspended. I filed a bug for it here:
[https://bugs.chromium.org/p/chromium/issues/detail?id=676036](https://bugs.chromium.org/p/chromium/issues/detail?id=676036)

~~~
j_s
The answer is a server hosting the games, but that costs money.

~~~
yincrash
Websockets are much simpler if you just want to do server<>client. A lot of
webrtc is to handles the problems that come with p2p.

~~~
j_s
AFAIK, websockets can't UDP (which is useful for many games).

~~~
banachtarski
Not only can they not do UDP, they are framed as HTTP connections so until
HTTP supports an alternative transport, WS is stuck.

------
rayboy1995
I picked websockets and socket.io for our web game:
[https://rocketblitz.com/](https://rocketblitz.com/)

When I started development WebRTC wasn't very well supported, now I am
considering using a hybrid. I already use two websockets, one for binary state
snapshots and the other for JSON important updates like entity creation and
chat. It would be interesting to implement WebRTC to my servers just for the
state snapshots.

------
azurelogic
[http://iswebrtcreadyyet.com/](http://iswebrtcreadyyet.com/)

~~~
nickthemagicman
Is Safari the new Internet Explorer?

~~~
azurelogic
It's hard to say this. On the one hand, they're totally missing out on extra
features like WebRTC. On the other hand, they're the only browser with 100%
ES2015 shipping and 100% ES2016+ complete in dev.

You can beat on them for missing the bonus questions, but they're the only one
answered all of the questions on the main exam correctly and they were the
first ones done...

[https://kangax.github.io/compat-table/es6/](https://kangax.github.io/compat-
table/es6/)

[https://kangax.github.io/compat-
table/es2016plus/](https://kangax.github.io/compat-table/es2016plus/)

~~~
indexerror
Service workers aren't a bonus anymore. Safari alone is holding back webapps
considerably.

------
latenightcoding
Too bad the API is an absolute mess, I worked on a WebRTC application 2 years
ago and it was a nightmare.

~~~
bratsche
Can you tell us about any of the problems you experienced?

~~~
latenightcoding
I just remember it was a nightmare to get it working in both chrome and
firefox, the tutorials were outdated, the official docs at w3.org were wrong
(suggested settings would break the app), error handling was not consistent,
lots of race conditions, API was too complex and awkward, etc.

~~~
cpncrunch
Try shane tully's example code. Its simple and works well.

[https://shanetully.com/2014/09/a-dead-simple-webrtc-
example/](https://shanetully.com/2014/09/a-dead-simple-webrtc-example/)

------
shurcooL

        I have to warn you though, the server-side WebRTC libraries are not very mature
        yet. I advise you to do thorough research before building your game.
    

Are there any good server and/or client WebRTC libraries written in Go yet?

~~~
pthatcherg
There was a discussion about this on go-nuts:

[http://grokbase.com/t/gg/golang-nuts/161wbn1vf0/go-nuts-
nati...](http://grokbase.com/t/gg/golang-nuts/161wbn1vf0/go-nuts-native-go-
implementation-of-webrtc-any-interest-in-such-a-project)

There are two bindings for Go built on top of the WebRTC code at webrtc.org:

[https://github.com/keroserene/go-webrtc](https://github.com/keroserene/go-
webrtc) [https://github.com/fd/webrtc](https://github.com/fd/webrtc)

By the way, I work on the WebRTC team at Google, and I don't think it would be
that hard to write a data channel server in Go. Here's how you should do it.

1\. Get an "SDP offer" from the client. Parse it mainly to get the DTLS
fingerprint. You may also choose to get the SCTP max message size.

2\. Open a UDP socket. Listen for incoming STUN binding requests and send back
binding responses:

You can see how the WebRTC client code constructs requests here:
[https://cs.chromium.org/chromium/src/third_party/webrtc/p2p/...](https://cs.chromium.org/chromium/src/third_party/webrtc/p2p/base/port.cc?sq=package:chromium&dr=CSs&rcl=1482855583&l=755)

You can see how the WebRTC client code processes responses here:
[https://cs.chromium.org/chromium/src/third_party/webrtc/p2p/...](https://cs.chromium.org/chromium/src/third_party/webrtc/p2p/base/port.cc?sq=package:chromium&dr=CSs&rcl=1482855583&l=363)

Or you can read the RFC (warning: not light reading):
[https://tools.ietf.org/html/rfc5245](https://tools.ietf.org/html/rfc5245)

3\. Once a valid STUN binding request is received, listen for DTLS packets and
hand those over to BoringSSL. Also listen to when BoringSSL wants to send a
packet and send those out on the UDP socket back to the client.

You can see how the WebRTC client code passes DTLS packets down to BoringSSL
here:
[https://cs.chromium.org/chromium/src/third_party/webrtc/base...](https://cs.chromium.org/chromium/src/third_party/webrtc/base/opensslstreamadapter.cc?cl=GROK&rcl=1482855583&l=221)

You can see how the WebRTC client code gets packets to send from BoringSSL
here:
[https://cs.chromium.org/chromium/src/third_party/webrtc/base...](https://cs.chromium.org/chromium/src/third_party/webrtc/base/opensslstreamadapter.cc?cl=GROK&rcl=1482855583&l=239)

4\. Once BoringSSL finishes the DTLS handshake and is processing incoming SCTP
packets, listen for those and hand those over to usrsctplib. Also listen to
packets usrsctplib wants to send and hand those over to DTLS to send.

You can see how the WebRTC client code reads decrypted packets from BoringSSL
here:
[https://cs.chromium.org/chromium/src/third_party/webrtc/base...](https://cs.chromium.org/chromium/src/third_party/webrtc/base/opensslstreamadapter.cc?cl=GROK&rcl=1482855583&l=647)

And how it passes them down to usrsctplib here:
[https://cs.chromium.org/chromium/src/third_party/webrtc/medi...](https://cs.chromium.org/chromium/src/third_party/webrtc/media/sctp/sctpdataengine.cc?q=sctpdataengine&sq=package:chromium&l=702)

You can see how the WebRTC client code gets packets to send from usrsctplib
here:
[https://cs.chromium.org/chromium/src/third_party/webrtc/medi...](https://cs.chromium.org/chromium/src/third_party/webrtc/media/sctp/sctpdataengine.cc?sq=package:chromium&rcl=1482855583&l=254)

And how it passes them to BoringSSL here:
[https://cs.chromium.org/chromium/src/third_party/webrtc/base...](https://cs.chromium.org/chromium/src/third_party/webrtc/base/opensslstreamadapter.cc?cl=GROK&rcl=1482855583&l=583)

5\. Process data channel messages from usrsctplib and send data channel
message through usrsctplib. Note that you can ignore the whole "OPEN message"
protocol if you call PeerConnection.createDataChannel with the "negotiated:
true" option on the WebRTC client side. You can specify the SID you want to
use for the data channel as well.

You can see how the WebRTC client code passes messages to usrsctplib here:
[https://cs.chromium.org/chromium/src/third_party/webrtc/medi...](https://cs.chromium.org/chromium/src/third_party/webrtc/media/sctp/sctpdataengine.cc?sq=package:chromium&rcl=1482855583&l=666)

And how it receives them:
[https://cs.chromium.org/chromium/src/third_party/webrtc/medi...](https://cs.chromium.org/chromium/src/third_party/webrtc/media/sctp/sctpdataengine.cc?sq=package:chromium&rcl=1482855583&l=428)
[https://cs.chromium.org/chromium/src/third_party/webrtc/medi...](https://cs.chromium.org/chromium/src/third_party/webrtc/media/sctp/sctpdataengine.cc?sq=package:chromium&rcl=1482855583&l=214)

6\. Serialize an "SDP answer" message which basically just hands back the same
looking blob of text, but with a different DTLS fingerprint (the one for the
certificate of the server). It also must have two random strings: the ICE
username fragment (ufrag) and ICE password (pwd). If you pass that answer to
the WebRTC client, all the ICE, DTLS, and SCTP work should happen and after
around 6 round trips on the network, you should incoming and outgoing
messages.

Ok, that probably sounds like a lot, but most of the work is done by BoringSSL
and usrsctplib. The bulk of the Go code would be implementing the STUN
messages and gluing everything together. Good luck to whoever tries :).

~~~
chadnickbok
I tried!

[https://github.com/chadnickbok/librtcdcpp](https://github.com/chadnickbok/librtcdcpp)

------
ndesaulniers
Not until server-side implementations exist. Depending on the physical
location and amount of data being replicated, you'll need the flexibility to
move master-game simulation logic from dedicated server to shared client.
WebRTC works great if you're doing p2p among browsers, which severely limits
the kinds of multiplayer experiences you can create.

I love WebRTC and think it's great. I studied and read all related RFCs and
tried implementing a stack in JavaScript for Node.js. Got stuck on DTLS, then
switched jobs.

I do think WebRTC is "the future," but we don't seem to be moving AT ALL
towards that future. Having multiple implementations would move the needle.
Otherwise, there was this big leap forward when it was developed and added to
browsers, but not much since.

------
SCdF
Deep down there is the conversation about using both TCP and UDP. This leads
to a paper[1] presented in 1997.

How much does this sort of thing (and the hardware / capability it's running
on) change in 20 years? I wonder if it's worth revisiting.

[1]
[https://www.isoc.org/INET97/proceedings/F3/F3_1.HTM](https://www.isoc.org/INET97/proceedings/F3/F3_1.HTM)

~~~
banachtarski
This paper always baffled me in terms of why it was significant. Basically,
TCP is just nasty to ALL other transports passing through the same node/pipe
(including other TCP). I don't know why, a) this is a surprise or b) only UDP
is singled out as an affected transport in this scenario.

------
k__
To the security people here.

I like the idea of P2P and UDP for better latency.

But how dangerous is this?

~~~
man5quid
[http://gafferongames.com/networking-for-game-
programmers/wha...](http://gafferongames.com/networking-for-game-
programmers/what-every-programmer-needs-to-know-about-game-networking/)

A great series for you to read.

tl;dr

Udp is good. client to client sessions are terrible over the internet.

~~~
zurn
The P2P case this article discusses is "peer-to-peer lockstep", which is only
a small subset of possible p2p systems.

(it's called peer-to-peer instead of client-to-client, because there is no
client role in such a system).

------
browseatwork
My coworker (a mobile game developer, currently working on a web game), says:

I don't think WebRTC is ready yet for games, too much complexity on the server
side.

Instead, he's using websockets for his web game.

Disclosure: we work for a WebRTC company.

------
suhith
WebRTC Datachannels are awesome, I've always thought they could be leveraged
for efficient peer to peer gaming but this is definitely interesting as well.

Getting started with webrtc datachannels is easy and you can even have your
server in Python Flask, but keep in mind you'll have to handle multiple
concurrent connections.

Here's a simple file sharing demo I made a while ago
[https://github.com/suhithr/CampFile](https://github.com/suhithr/CampFile)

------
yeldarb
I haven't looked at WebRTC in a while but what's the compatibility of data
channels nowadays? Does it finally work on mobile?

~~~
kosinus
Works fine on Firefox and Chrome, on all systems except iOS. (On iOS, all
browsers are Webkit shills.)

Safari currently lacks support everywhere.

[http://caniuse.com/#feat=rtcpeerconnection](http://caniuse.com/#feat=rtcpeerconnection)

~~~
Marqin
For iOS you can use Bowser browser, which has WebRTC support.

------
sherwinsim
The data channel seems like one of the most under-utilized features for
WebRTC. On our platform we've seen a handful of companies develop RT games and
applications. Nice to see people developing applications other than AV
applications.

Going to also shamelessly promote our webrtc platform www.temasys.io It has
very strong support for data channel, and socket messaging.

------
ceejay

      WebSockets are just too slow
    

[https://www.w3.org/TR/tcp-udp-sockets/](https://www.w3.org/TR/tcp-udp-
sockets/)

Not sure status of this standard, or plans for adoption. As long as proper
steps are taken to allow for secure implementations I'm all for it.

------
vvanders
Last I looked at WebRTC it fell back to TCP if it couldn't open a UDP session
which means it's fairly useless as a game protocol.

Is that still the case or do the guarantee a non-blocking protocol?

~~~
nitwit005
If you need UDP, and a UDP connection can't be set up, aren't you screwed
regardless?

~~~
stcredzero
If you've designed your protocol, such that you're sending packets smaller
than 1.5k (or better 572 bytes) then over a really good connection, TCP will
perform like UDP, or close enough in any case. With modern 1st world broadband
(which doesn't include _all_ of the US, unfortunately) you just want UDP to
minimize that fraction of the populace that gives you a 1-star rating and says
your game sucks because their network sucks.

The big difference comes in with packet drops. TCP, with its delivery and
order guarantees, will cause huge outliers in latency. Even when those
outliers are rare, they will make your game look completely janky. With good
broadband, those outliers will be very, very rare, and the game will look
good.

~~~
vvanders
It's not just packet drops and MTU, you also have congestion control, Nagel
algorithm and a host of other things working against you in a TCP connection.

You're trying to turn a stream protocol into a message based protocol and
you're going to experience an impedance mismatch if you try to use the wrong
protocol for your use case.

~~~
stcredzero
_You 're trying to turn a stream protocol into a message based protocol and
you're going to experience an impedance mismatch_

Definitely. But the reality is that it won't bite you for the part of your
audience that's on premium broadband and corporate networks. Conversely, it's
going to _really really_ suck for people in crowded apartments on WiFi and bad
connections of all kinds. I know this because I'm operating an MMO server on
Amazon AWS right now.

------
bullen
I made this HTTP comet-stream solution for multiplayer games:
[http://fuse.rupy.se/fuse.html](http://fuse.rupy.se/fuse.html)

------
hardwaresofton
Note that signaling for WebRTC is still recommended to be sent over HTTPS!
Signaling (before the p2p connection is fully negotiated) can be eavesdropped
if not done properly.

------
fredliu
Great article.

Does anybody have any experience using WebRTC out of the browser context? E.g.
using Android's webRTC lib without using a browser?

~~~
emcpoland
Have experience using it as a VoIP app. The main issue with it, is that
there's constant regressions, with no real stable version.

For example if a new Android device comes out you can run into issues
regarding gain and echoing, they also maintain a list of pecular devices which
don't strictly adhere to standards (Mostly Samsung devices). So you end up
having to upgrade to a later version. Which ends up causing regressions in
many other devices which previously had no issues.

I am ofcourse talking about Google's WebRTC. The best thing to a stable
version, is the commit hash used in chrome, but they have just as many
regressions as any other version. Building it is also a bit of a pain,
although no where near as bad as it used to be, but once it's set up it does
the job quite well.

~~~
fredliu
Interesting, I'm aware of the hassle to build it, but constant
regression...that means it's not production ready yet. Regarding the same
regression in Chrome, does it mean the WebRTC in stable version of Chrome also
has the same compatibility/gain/echoing problems with new android devices?

~~~
emcpoland
Yeah, there are frequent regressions in Chrome. Although Ive never had
personal experience of them in the browser, but Ive used the same commit hash,
and tickets Ive come across also tend to refer to the browser. Most of the
issues I have come across are device specific.

Sadly I believe its as production ready as its ever going to be, they seem to
be taken the motto of "move fast and break things". The issue isn't the
project, its the carefree way that its being handled.

------
bluetwo
Am I wrong in thinking this will shortly kill Adobe Connect, WebX, Chat
Roulette, IRC, every other messenger platform out there?

~~~
duskwuff
Yes, you are wrong in thinking that. :)

WebRTC is a technology. It is not an application, and cannot replace
applications.

In the cases of some of those applications, it could conceivably be used to
implement future versions of those applications -- but that certainly doesn't
equate to "killing" them.

~~~
bluetwo
OK, thanks. :)

I wasn't saying that it would kill them out of the box. I am thinking that
those application rely of a heavy dose of proprietary technology in order to
pull off their magic, and WebRTC is going to enable countless competitors to
arise with much less investment in tech.

In the long run, this tends to kill off established applications.

~~~
tokenizerrr
IRC? Proprietary technology?

~~~
bluetwo
You might be missing the point here.

~~~
tokenizerrr
> I am thinking that those application rely of a heavy dose of proprietary
> technology

> IRC

[https://tools.ietf.org/html/rfc1459](https://tools.ietf.org/html/rfc1459)

~~~
bluetwo
Sorry. You are absolutely missing the point of my posts.

I know it can feel good to tell people they are wrong, but you are off the
mark.

The point was WebRTC could kill these technologies, all of which are
proprietary or one-trick ponies. At least that was my question. I was looking
for what others thought on the topic. I clearly was not trying to convince
anyone IRC was purely proprietary, and anyone who would read what I wrote and
would think that was clearly looking for a fight. I'm not interested. Move
along.

------
trevyn
Interesting. What are the server-side software options for hosting bandwidth-
intensive WebRTC data channels?

~~~
getkey
On Node.js you have [https://github.com/js-platform/node-
webrtc](https://github.com/js-platform/node-webrtc) and
[https://github.com/vmolsa/webrtc-native](https://github.com/vmolsa/webrtc-
native) which are a bit unstable, or [https://github.com/mappum/electron-
webrtc](https://github.com/mappum/electron-webrtc) which works fine but
requires running an Electron process.

------
amelius
Somewhat related: is there a good open source video conferencing webrtc
library written in JavaScript yet?

~~~
reitanqild
Linked from the article:

\- [https://talky.io](https://talky.io) (commercial)

\- [https://simplewebrtc.com/](https://simplewebrtc.com/) (mit licensed)

------
mrfusion
I didn't follow the nat traversal part.

~~~
getkey
When a game server connects to the master to be registered, what the master
gets is the the IP address relatively to it. If this address happens to be
accessible from a client, everything's fine. However in some cases, it is not.
For example in the case described where 127.0.0.1 is the game server's address
(relatively to the master), if the master sent the address 127.0.0.1 to a
client, it wouldn't connect. So we need to find out the public IP address in
some cases, but sometimes it is better to use the local IP address (for
example if the master, the game server and a client are on the same network
and the client is not allowed to access the internet).

So basically finding out which IP address the master must send to the client
is a huge pain. WebRTC does it automatically (to traverse NATs).

------
kLeeIsDead
Heh, the web. The only platform where it's considered normal to use elaborate
workarounds for problems that have been solved decades ago

~~~
legulere
But also the only platform where you can run arbitrary code without having to
fear it take over your computer or steal all your data on your computer.

~~~
kuschku
Nah. The same is possible on phones – the "put every program in a container,
and restrict access to any hardware or files" allows exactly that.

------
fulafel
Using unreliable or out-of-order data for game state sounds hard and difficult
to test, no? Are there code level patterns that help reduce the complexity
while keeping the possible performance benefits?

If your entity state changes ("move player 1 to 3,4", "open door 3") are
dropped/switch order, the logic no worker works. This way the unreliability
seems to leak directly to game logic/scripting layer.

On the face of it the complexity cost seems high for supporting bad network
connections. A normal TCP connection rarely sees losses or reorderings. There
are exceptions (twitch games) of course.

~~~
zurn
Somehow networked shooters manage to leverage it. They probably only use
unreliable messages for the twich mechanic hot-path which is heavily analyzed,
iterated and tested anyway.

