

Ask HN: HTTP P2P? - andrewcooke

Is it possible to have a Javascript game running in a web browser that somehow allows networked play without going through a central server?  How about with web sockets and TCP hole punching (obviously this would need a server for initial setup)?<p>Has anyone heard of any work in this area?  Am I missing something obvious, simpler and easier?  Thanks.
======
huhtenberg
FWIW, I managed to get two clients, each behind its own HTTP proxy, connect to
each other using symmetrical TCP open. Not browsers, and with the help of a
coordinating server, but the clients did end up with a direct connection
between themselves.

People tend to think it is hard, because no one does it, and no one does it,
because everyone thinks it's hard. Catch 22. Just try it, damn it. It's
trivial :)

------
IgorPartola
You need a server. JavaScript does not have access to the necessary sys calls
to open sockets or perform IO. This could be possible with browser support,
but I doubt browsers would want to support such features since they could be
abused really badly. AFAIK Opera bundles a web server to allow for some kind
of file sharing, but it seems unlikely you would be able to use it for your
purpose.

~~~
andrewcooke
Thanks, but why wouldn't web sockets work with TCP hole punching?
[<http://www.acooke.org/cute/WhatisTCPh1.html> \- self link, but used to be a
reasonable Quora post] Is it just that no-one has done this yet? I don't see
an obvious technical reason.

~~~
IgorPartola
Does web sockets actually allow you to bind() and listen()? I do not believe
so. Will take a look at your link in a bit.

~~~
andrewcooke
TCP hole punching avoids the need to bind and listen. You arrange things
(thanks to some looseness in the TCP spec, with the help of a central server)
so that two "outgoing" connections talk to each other. It's how Skype manages
to make incoming connections to computers, for example, even though they are
behind NAT (firewalls and modems).

[edit: for some reason I can't reply to your reply below, but you are
misunderstanding how hole punching works. They do not listen - that (avoiding
listening) is pretty much the whole reason why hole punching is needed/used.
But the latter point about complexity is probably valid.]

~~~
IgorPartola
According to [1], section 4.2:

> From the same local TCP ports that $A$ and $B$ used to register with $S$,
> $A$ and $B$ each asynchronously make outgoing connection attempts to the
> other's public and private endpoints as reported by $S$, while
> simultaneously listening for incoming connections on their respective local
> TCP ports.

This makes it sound like both hosts have to listen for incoming connections:
there is no way to hijack a TCP session and redirect it to a different host on
the fly (aside from some very special circumstances where you have set up
anycast and TCP session sharing, which you wouldn't be able to do in a network
you do not fully control).

Also, AFAI remember, the WebSockets API is a step above TCP: you ask the
browser to make a connection to endpoint S, and it negotiates the connection
by asking the server if it supports not just TCP, but WebSockets and from
where, etc. Thus the example from [1] would get much more complicated: you now
have to make sure the browser not only performs the normal WebSocket setup,
but then makes a new connection to a different server, while simultaneously
listening for an incoming connection: not something, I believe, a part of the
WebSockets spec.

[1] <http://www.brynosaurus.com/pub/net/p2pnat/>

------
mike-cardwell
A signed Java applet which has asked the user for permission can bind to local
ports and make arbitrary connections to any IP. JavaScript can interact with
the Java applet too. I don't know, but the same might be possible with Flash
too?

~~~
andrewcooke
yes, i think this would work. unfortunately, i can't see anything in "pure"
javascript that is equivalent: the xmlhttprequest is restricted to the
originating ip (and it looks like they are single request/response, but in
practice perhaps that could be worked around); websockets have the same
restriction (but are bi-directional and multiple message) _plus_ they are
implemented on top/inside of the http stream, so don't (uniquely) own a tcp
connection.

and server-side java libs exist for hole punching. so you could pretty easily
implement a java-only solution, called from javascript.

------
andrewcooke
ok, since there's little in the way of useful responses, here are some results
i've found since asking.

first, there's a draft standard for arranging p2p connections with tcp hole
punching (STUNT or STUN for TCP) - <http://tools.ietf.org/html/draft-ietf-
mmusic-ice-tcp-16>

second, there's a draft standard for sip over websockets (sip is a protocol
used to arrange a connection between two peers) -
[http://tools.ietf.org/html/draft-ibc-sipcore-sip-
websocket-0...](http://tools.ietf.org/html/draft-ibc-sipcore-sip-websocket-00)

these almost overlap, but there's an annoying gap, which is that i can still
find no way to connect websockets to tcp. so you could use sip to negotiate a
circuit, and you could use ice to close the circuit using tcp, but not
(afaict) with websockets. furthermore, because of how websockets seems to be
implemented (it's kind of multiplexed in to http, as far as i can tell) it
seems like it would be hard to close this gap.

~~~
andrewcooke
This is so late I doubt anyone will see it, but I finally have an answer,
thanks to Saul Ibarra Corretge. The missing link is WebRTC -
<http://www.webrtc.org/>

You can set up a connection using SIP (see above) and then WebRTC will provide
a Javascript API for making the connection between peers (and the WebRTC docs
include various references to ICE which makes me suspect they will work
correctly behind NAT etc).

So it's possible with experimental Google APIs today ("Latest Google Chrome
(dev channel) comes with WebRTC support" - Saul).

