Opened 6 years ago

Closed 22 months ago

#5578 closed task (implemented)

Investigate WebRTC for flash proxy NAT punching

Reported by: dcf Owned by: dcf
Priority: Medium Milestone:
Component: Archived/Flashproxy Version:
Severity: Normal Keywords:
Cc: cjb, arlolra, ln5, asn, infinity0, serene Actual Points:
Parent ID: Points:
Reviewer: Sponsor:

Description

hellais suggested WebRTC (http://www.webrtc.org/, https://en.wikipedia.org/wiki/WebRTC) as a way to directly connect browsers behind NATs. This could be useful for the JavaScript flash proxy, which otherwise doesn't work at all when the censored user is behind NAT.

We should examine WebRTC to find out at least
# How much information it discloses to a third party. (For facilitation of NAT punching, for example. This was a problem with the Adobe RTMFP transport in the Flash-based proxy.)
# How common it is or can be expected to become; i.e., will a censor be reluctant to block it wholesale.
# What are the implications for protocol fingerprinting.
# What browsers it is supported in.
# How easy it is to implement and deploy.

Child Tickets

Change History (41)

comment:2 Changed 5 years ago by dcf

We will probably have to add some metadata to client registrations to indicate what kind of connections the client supports. Registrations currently look like this:

client=1.2.3.4:9000

We can augment them so:

client=1.2.3.4:9000&transports=websocket,webrtc

Maybe that doesn't make sense, as webrtc needs its own port number, or something. Perhaps something like

client-1.2.3.4:9000&client-webrtc=1.2.3.4:10000

Where client is implictly client-websocket.

Flash proxies would also advise the facilitator of the types of connection they can serve. So a Chrome browser arrives supporting websocket and webrtc, and the facilitator is free to give it a client that supports either of those two.

Having a raw transport separate from websocket would also be nice for #6284+#7721 (plain sockets in Chrome addons, browser addon) and #7944 (standalone flash proxy). When we're not limited by a browser, then we shouldn't have to pay the WebSocket overhead.

comment:3 in reply to:  2 Changed 5 years ago by dcf

Replying to dcf:

We will probably have to add some metadata to client registrations to indicate what kind of connections the client supports.

See comment:5:ticket:7944 for more musings about this topic.

comment:4 Changed 5 years ago by cjb

# What browsers it is supported in.

I think we want to use reliable (TCP) "RTCDataChannels"; their API is extremely similar to WebSockets. The support for this part of the WebRTC spec is still very new; most people are using the audio/video UDP APIs instead.

Chrome only supports RTCDataChannels using RDP (which is UDP plus headers) at the moment. Firefox *does* support reliable RTCDataChannels in Firefox Nightly, behind a flag. Firefox and Chrome RTCDataChannels aren't interoperable, but that's okay for us because the Flashproxy design never has one browser's socket talking to another browser's socket.

So I think the short answer is that we could start implementing in Firefox now, with the expectation that one day the same code will work in Chrome.

comment:5 Changed 5 years ago by cjb

Cc: cjb added

comment:6 Changed 5 years ago by dcf

Some more information, paraphrasing from what cjb told me.

WebRTC supported only unreliable media (audio/video) channels until recently. RTCDataChannel is in Chrome 26 and Firefox 18. The two browsers don't yet interoperate out of the box. This demo connection, http://www.webrtc.org/demo, requires setting the media.peerconnection.enabled pref. Chrome's RTCDataChannel is unreliable, while Firefox has a reliable one.

Nice Mozilla docs: https://developer.mozilla.org/en-US/docs/WebRTC

comment:7 Changed 5 years ago by cjb

http://peerjs.com/ looks interesting, and comes with an open-source server component to broker connections. (It doesn't help with the problems of Chrome not having implemented reliable transfers or binary data types, though.)

comment:8 Changed 5 years ago by cjb

I chatted with a friend who is a Google WebRTC developer (Ben Schwartz), and he had some good ideas and pointed out some problems that I hadn't thought of.

The largest problem is how the client transport plugin is going to work, because there's not yet any headless WebRTC implementation; it's very attached to the DOM. I'd been assuming that node.js will grow a library that speaks WebRTC across each of Firefox/Chrome/node with a common API -- socket.io does this for websockets -- but the requirements for WebRTC are far greater. Ideally you need a full libjingle port, and at the least you need ICE and SCTP. Node currently doesn't have any SCTP support, as far as I can see.

So our options include waiting for node to grow a lot of code that doesn't exist right now, or having the client transport plugin be written in C instead of node and linked with libjingle, or finding a way to avoid having a full client transport plugin.

Ben's suggestion for avoiding a client transport plugin is that the plugin could be a SOCKS-style proxy that bounces the data back into the local browser through a websocket on the local machine, and some JavaScript in the browser handles brokering between the websocket and an outgoing WebRTC datachannel.

Some interesting node projects:

https://npmjs.org/package/peer-connection-shim
https://github.com/rogerwang/node-webkit

Current status of the browser-side code is that peerjs.com looks like the right thing for a common API, but it only supports Chrome rather than Firefox, and only Firefox has support for reliable transfers in datachannels. So we're either waiting for Chrome to support reliable transfers, or PeerJS to support Firefox.

comment:9 Changed 5 years ago by cjb

Chrome bug tracking their datachannels implementation: https://code.google.com/p/webrtc/issues/detail?id=1408

comment:10 in reply to:  8 Changed 5 years ago by dcf

Priority: minornormal

Replying to cjb:

The largest problem is how the client transport plugin is going to work, because there's not yet any headless WebRTC implementation; it's very attached to the DOM. I'd been assuming that node.js will grow a library that speaks WebRTC across each of Firefox/Chrome/node with a common API -- socket.io does this for websockets -- but the requirements for WebRTC are far greater. Ideally you need a full libjingle port, and at the least you need ICE and SCTP. Node currently doesn't have any SCTP support, as far as I can see.

So our options include waiting for node to grow a lot of code that doesn't exist right now, or having the client transport plugin be written in C instead of node and linked with libjingle, or finding a way to avoid having a full client transport plugin.

WebRTC is more complicated than I thought. All the things you mention are doable, but it sounds like a big development effort.

I'd rather not have new code written in C. Even if we have to link with C libraries, we should find a way to do it in a safer language.

Ben's suggestion for avoiding a client transport plugin is that the plugin could be a SOCKS-style proxy that bounces the data back into the local browser through a websocket on the local machine, and some JavaScript in the browser handles brokering between the websocket and an outgoing WebRTC datachannel.

This works, but only as a prototype. I don't want to deploy the "browser-as-transport" because it's confusing and leads to mistakes. From the user's point of view, you launch your TBB, that's fine, but then for some reason you also have to have another browser open, that is not a TBB, and then you have to remember to do your anonymous browsing in one and not the other.

We did something like the above a long time ago when we still used Flash, in order to use the Adobe RTMFP transport, which has uses similar to those of WebRTC. Our implementation let you register either an IP address or an RTMFP address, and then the proxy code used either a TCP socket or a socket abstraction over RTMFP. I didn't like it for the reasons above, plus the fact that it required running proprietary code on the client. (Plus the fact that the code was the same program as the flash proxy code, just with a different query string, which was way confusing. Try explaining that to anyone: "No, the flash proxy runs outside the firewall, where it can reach the Tor relay. Well, technically it also runs inside the firewall, but that's only for the sake of code reuse.")

Anyway, here's the ancient RTMFP branch in case it's useful.
https://gitweb.torproject.org/flashproxy.git/shortlog/refs/heads/rtmfp

I'm fine if we have an implementation of WebRTC that only does the things we need. I realize though, that this may still be most of the hard parts. Perhaps an implementation could be pulled out of a browser too.

Suppose we used the unreliable transport as if it were reliable. What could go wrong? If a packet gets dropped or duplicated, it will get noticed by the integrity checks in lower-level crypto. It seems the worst is that some of your circuits would get killed, if you're dropping packets.

comment:11 Changed 5 years ago by cjb

I've started prototyping, but my prototype Javascript reliably crashes Firefox (across multiple operating systems):

https://bugzilla.mozilla.org/show_bug.cgi?id=851997

The developers seem interested in fixing this, I expect they'll look at it soon.

comment:12 Changed 5 years ago by cjb

Mozilla devs say that they expect this to be fixed by the imminent landing of a patch that removes the need to call connectDataConnection():

https://bugzilla.mozilla.org/show_bug.cgi?id=852908
https://bugzilla.mozilla.org/show_bug.cgi?id=837035

I'm not sure I agree with them that it'll fix this bug, but hopefully we'll find out soon.

comment:13 Changed 5 years ago by arlolra

Cc: arlolra@… added

comment:14 Changed 5 years ago by cjb

Yay, I'm unblocked thanks to patches that landed in today's Firefox Nightly.

comment:15 Changed 4 years ago by cjb

Still haven't got a prototype working, but I did blog (with code) about using webrtc purely peer-to-peer without a signaling server:

http://blog.printf.net/articles/2013/05/17/webrtc-without-a-signaling-server/

comment:16 Changed 4 years ago by ln5

Cc: ln5 added

comment:17 Changed 4 years ago by arlolra

Someone went through the trouble of implementing Jingle for Strophe.js:
https://github.com/ESTOS/strophe.jingle

comment:18 Changed 4 years ago by arma

Might be worth asking for a copy of uproxy to see what they do / don't do in webrtc-land?

(I haven't gotten a copy yet so I don't know if it is open source yet or just "in the plans".)

comment:19 Changed 4 years ago by infinity0

Cc: infinity0 added

comment:20 in reply to:  18 Changed 4 years ago by dcf

Replying to arma:

Might be worth asking for a copy of uproxy to see what they do / don't do in webrtc-land?

(I haven't gotten a copy yet so I don't know if it is open source yet or just "in the plans".)

I wrote a letter to the developers listed at http://news.cs.washington.edu/2013/10/22/uw-cses-uproxy-unveiled-at-google-ideas-summit-in-nyc/.

comment:21 Changed 4 years ago by dcf

I have some good news. Raymond Cheng from uProxy wrote back and informed me that the standalone (not browser-embedded) WebRTC source code is available:

I think this code release is new since we were last looking seriously at WebRTC.

This is good, because it means we can (probably) implement a WebRTC peer without involving a browser. It's just a matter of writing a little C++ :)

Proposed plan of attack:

  1. Implement a little C++ application and JavaScript program capable of exchanging data.
  2. Somehow merge the prototypes into flashproxy-client and flashproxy.js.

Since #9349 we have the infrastructure in place to allow clients to register with a "webrtc" transport. I don't see a reason why proxy–relay communication can't still be "websocket".

comment:22 Changed 4 years ago by infinity0

They have a git mirror of that SVN repo, which is a lot faster to clone:

http://git.chromium.org/gitweb/?p=external/webrtc.git;a=summary

Did you guys ever solve the signalling issue? We might be able to implement it in the facilitator (if ICE lets us get away with a single round trip, in which case we could bundle that into the existing client registration), but I'm wondering if there is a better way... Another option is to use public SIP servers, which may or may not be blocked by a censor.

Version 0, edited 4 years ago by infinity0 (next)

comment:23 Changed 4 years ago by infinity0

Some more links:

http://www.w3.org/TR/webrtc/#peer-to-peer-data-example

https://bitbucket.org/webrtc/codelab#markdown-header-step-5-set-up-a-signaling-server-and-exchange-messages

Overview of ICE operation:

  1. each side, L/R finds out its own "candidate addresses" - addresses it might be contacted on, LAN or WAN or internet. then it sides this information to the other side via the signalling channel.
  2. each side forms candidate-pairs out of these address, and sorts them in priority order
  3. each side performs connectivity checks using each of these candidate-pairs.
  4. the controlling agent (either L/R) nominates a candidate-pair to use for the data channel

In the option where we are using the facilitator rendezvous as a simplex signalling channel, we have some differences from plain ICE which assumes a duplex signalling channel:

  1. The client, L, is unable to directly receive the list of candidate addresses from R. However, if R's connectivity checks reach L, then L implicitly knows R's candidate address (or, now the actual address that works) this way. (This requires that L can authenticate R, the next point.)
  2. ICE assumes L and R know each other's keys, but L cannot receive from R. Instead, the facilitator can give R a token that it can present to L as authentication.

In both those situations, at present I don't know if we can fit those tweaks into the standard ICE flow that the WebRTC code implements. In (a) we essentially require (1) and (2) to occur concurrently, and in (b) we need some non-standard form of authentication that would probably involve the facilitator certifying R. (Also at the moment the facilitator only has an encryption key, not a certification key; we ought not to mix key uses unless we can prove it's secure to do so.)

I'll continue to investigate.

comment:24 Changed 4 years ago by infinity0

Continuing from the above, the following option probably would not require any changes to the ICE authentication code, nor the facilitator to have another certification key (nor to use the existing encryption key for certification) - but it does assume the existence of a fully-known confidential channel between the facilitator and the browser proxy (i.e. not SSL with x509).

  1. the client, L, generates a secret key K(R) and sends it to the facilitator in an encrypted client registration. this means only the facilitator can read K(R).
  2. when the facilitator picks a proxy, R, to serve L, it gives it K(R) via the confidential channel. now only the facilitator and the proxy can read K(R).
  3. R then uses K(R) as the authentication key for ICE as normal. no changes to normal ICE authentication are needed.
  4. L assumes that the facilitator works honestly, and that no-one else can read K(R) in transit, due to the confidential channel.

edit: thinking more about it, in the current system it's not so necessary for K(R) to remain fully-known confidential, since we're not assuming anything about the behaviour of proxies. they could be malicious, and they could be MITMd and replaced by an adversary. so, the above sequence is only really needed "for show" to be compatible with what ICE expects.

(it may become more relevant if we ever track the behaviour of proxies in some future reputation system, but such a system would require the solution of this problem anyway.)

Last edited 4 years ago by infinity0 (previous) (diff)

comment:25 in reply to:  24 Changed 4 years ago by dcf

Replying to infinity0:

Continuing from the above, the following option probably would not require any changes to the ICE authentication code, nor the facilitator to have another certification key (nor to use the existing encryption key for certification) - but it does assume the existence of a fully-known confidential channel between the facilitator and the browser proxy (i.e. not SSL with x509).

  1. the client, L, generates a secret key K(R) and sends it to the facilitator in an encrypted client registration. this means only the facilitator can read K(R).
  2. when the facilitator picks a proxy, R, to serve L, it gives it K(R) via the confidential channel. now only the facilitator and the proxy can read K(R).
  3. R then uses K(R) as the authentication key for ICE as normal. no changes to normal ICE authentication are needed.
  4. L assumes that the facilitator works honestly, and that no-one else can read K(R) in transit, due to the confidential channel.

edit: thinking more about it, in the current system it's not so necessary for K(R) to remain fully-known confidential, since we're not assuming anything about the behaviour of proxies. they could be malicious, and they could be MITMd and replaced by an adversary. so, the above sequence is only really needed "for show" to be compatible with what ICE expects.

(it may become more relevant if we ever track the behaviour of proxies in some future reputation system, but such a system would require the solution of this problem anyway.)

Thanks for finding these links. I'm beginning to understand better. The key exchange you describe seems reasonable on first reading.

Can signalling be done as a single request/response? If so, we might be able to build it into appspot rendezvous.

It may also be fine to use whatever signalling and ICE channel is used by Google hangouts, or whatever is the most common user of WebRTC.

I don't know what you mean by "fully-known confidential channel."

A good first goal would be to have two C++ programs that are capable of chatting with each other, after being given an offer and answer manually. That can serve as a basis for the client and server transport plugins. We can use it to test our ideas as we work out the details of signalling.

comment:26 in reply to:  21 Changed 3 years ago by dcf

Replying to dcf:

I have some good news. Raymond Cheng from uProxy wrote back and informed me that the standalone (not browser-embedded) WebRTC source code is available:

I think this code release is new since we were last looking seriously at WebRTC.

Raymond sent along some more links:

comment:27 Changed 3 years ago by cjb

Hi,

https://github.com/js-platform/node-webrtc example of linking the webrtc library to other projects.

I've ported my serverless-webrtc app (chat after manual exchange of offer and answer) to this node-webrtc library now, so you can share a text or binary datachannel between Node<->Node, Node<->Chrome, or Node<->Firefox. Here's a blog post with details and instructions:

http://blog.printf.net/articles/2014/07/01/serverless-webrtc-continued/

Since node-webrtc wraps the C++ WebRTC Native API, it should be straightforward to go from the node version to a raw C++ app, since it's just removing the JS abstractions that node-webrtc introduced. But the Native API is pretty sparsely documented and the sample code in the package doesn't actually include the SDP offer/answer exchange, so it might be tough.

comment:28 Changed 3 years ago by cjb

  1. Implement a little C++ application and JavaScript program capable of exchanging data.

Okay, I finally (a mere 18 months later, ugh) have this now. Here's a patch against Google's Native WebRTC code SVN repo which adds a new "webrtc_cmd" C++ binary:

http://printf.net/webrtc-cmd.patch

webrtc_cmd can share a datachannel with my serverless-webrtc project in any combination of:

  1. C++ binary
  2. Node.JS
  3. Chrome
  4. Firefox

(I'll see if the webrtc developers would consider including this example code in their repo after I tidy it up, since their current example C++ programs use neither SDP offer/answer nor datachannels.)

comment:29 Changed 3 years ago by infinity0

I just had a play about with cjb's serverless-webrtc demo. I tried to tweak the SDP answer that the session creator (i.e. client) expects to receive back from the joiner (i.e. proxy), hoping that we could hard-code a fake answer and still have everything work - i.e. the proxy would do NAT traversal but the client would just sit there with a useless fake answer, and wait for the proxy to connect to it.

Unfortunately, WebRTC has some pretty strong checks on the answer, namely fingerprint, ice-ufrag, and ice-pwd, which cannot be predicted in advance (see RFC 5245). So, we will either need one of the following:

  • a duplex registration methods (http/appspot could be modified to do this). However, if the facilitator doesn't have a proxy ready to serve the client, it will need to wait for one, so that it can respond to the client (with the proxy's SDP answer).
  • tweak the webrtc implementation on the client side to work without checking the aforementioned attributes of the SDP answer. This is would be quite intensive and involve digging into WebRTC C++ code, and would be harder to maintain in the long run. But it would let us use all the existing registration methods without modification.
Last edited 3 years ago by infinity0 (previous) (diff)

comment:30 Changed 3 years ago by infinity0

(Another alternative is to have a signalling mechanism separate from the registration process, but then we'd need to ensure/assume this isn't being censored either.)

comment:31 Changed 3 years ago by infinity0

Taking a step back, perhaps bundling the SDP offer with the client registration is not the best approach. There are a few reasons:

  • the SDP offer is supposed to be fresh for each connection (with a new ice-ufrag and ice-pwd), though it does contains information that is constant across connections (such as ICE candidates). By contrast, flashproxy-client does not currently try to send a new registration for every single connection it wants. We would also have to tweak the client-side webrtc code to give out constant ice-ufrag/ice-pwd which is against the RFC (link above) and might open up attacks.
  • there is no "listen" port, nor any other way of receiving information, so we don't know (beyond the first connection) when subsequent proxies will want to contact us.

So maybe a separate signalling mechanism would be best.

comment:32 Changed 3 years ago by asn

Cc: asn added

comment:34 Changed 3 years ago by dcf

I made a webrtc branch for us to start dumping files.

I put cjb's webrtc_cmd patch there, and a README about building the Native Code Package.

comment:35 Changed 3 years ago by dcf

cjb, I had trouble applying your patch to the Native Code Package. It looks like the surrounding code has changed. I tried making some simple changes but wasn't entirely successful. Can you help?

Here's what I did.

http://www.webrtc.org/reference/getting-started
http://www.webrtc.org/reference/getting-started/prerequisite-sw

$ sudo apt-get install g++ python libnss3-dev libasound2-dev libpulse-dev libjpeg62-turbo-dev libxv-dev libgtk2.0-dev libexpat1-dev openjdk-7-jdk libxss-dev libudev-dev libpci-dev

https://sites.google.com/a/chromium.org/dev/developers/how-tos/depottools
https://sites.google.com/a/chromium.org/dev/developers/how-tos/install-depot-tools

$ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
$ export PATH=$PWD/depot_tools:$PATH
$ mkdir webrtc
$ cd webrtc
$ gclient config --name src http://webrtc.googlecode.com/svn/trunk
$ gclient sync --force
$ cd src
$ ninja -C out/Debug
$ wget http://printf.net/webrtc-cmd.patch
$ patch -p1 < webrtc-cmd.patch
$ gclient sync
$ ninja -C out/Debug

The first error I get is something about json.h:

../../talk/examples/peerconnection/webrtc_cmd.cc:36:10: fatal error: 'talk/base/json.h' file not found
#include "talk/base/json.h"
         ^
1 error generated.
[4/19] LINK video_engine_core_unittests
ninja: build stopped: subcommand failed.

So I change it an other headers from talk/base to webrtc/base, which seems to work. After that I get some errors about the talk_base namespace, which seems to have changed to rtc:

../../talk/examples/peerconnection/webrtc_cmd.cc:43:7: error: use of undeclared identifier 'talk_base'
using talk_base::scoped_ptr;
      ^
../../talk/examples/peerconnection/webrtc_cmd.cc:44:7: error: use of undeclared identifier 'talk_base'
using talk_base::scoped_refptr;
      ^
../../talk/examples/peerconnection/webrtc_cmd.cc:85:3: error: use of undeclared identifier 'talk_base'
  talk_base::scoped_refptr<webrtc::DataChannelInterface> channel_;
  ^
../../talk/examples/peerconnection/webrtc_cmd.cc:85:27: error: expected member name or ';' after declaration specifiers
  talk_base::scoped_refptr<webrtc::DataChannelInterface> channel_;
  ~~~~~~~~~~~~~~~~~~~~~~~~^

After fixing that, I get an API error, and I'm out of my depth:

../../talk/examples/peerconnection/webrtc_cmd.cc:179:40: error: too many arguments to function call, expected single argument 'stream', have 2 arguments
  peer_connection_->AddStream(stream_, &constraints_);
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~          ^~~~~~~~~~~~~
../../talk/app/webrtc/peerconnectioninterface.h:258:3: note: 'AddStream' declared here
  virtual bool AddStream(MediaStreamInterface* stream) = 0;
  ^

Here's the full diff of the changes I made to webrtc_cmd.cc:

--- webrtc_cmd.cc.orig	2014-11-13 09:51:49.253103179 -0800
+++ webrtc_cmd.cc	2014-11-13 10:03:38.616560815 -0800
@@ -33,15 +33,15 @@
 #include "talk/app/webrtc/datachannelinterface.h"
 #include "talk/app/webrtc/test/fakeconstraints.h"
 #include "talk/app/webrtc/test/mockpeerconnectionobservers.h"
-#include "talk/base/json.h"
-#include "talk/base/logging.h"
-#include "talk/base/ssladapter.h"
-#include "talk/base/sslstreamadapter.h"
-#include "talk/base/thread.h"
+#include "webrtc/base/json.h"
+#include "webrtc/base/logging.h"
+#include "webrtc/base/ssladapter.h"
+#include "webrtc/base/sslstreamadapter.h"
+#include "webrtc/base/thread.h"
 #include "talk/app/webrtc/test/fakedtlsidentityservice.h"
 
-using talk_base::scoped_ptr;
-using talk_base::scoped_refptr;
+using rtc::scoped_ptr;
+using rtc::scoped_refptr;
 using webrtc::MediaStreamInterface;
 using webrtc::CreatePeerConnectionFactory;
 using webrtc::DataChannelInterface;
@@ -82,7 +82,7 @@
   bool IsOpen() const { return state_ == DataChannelInterface::kOpen; }
 
  private:
-  talk_base::scoped_refptr<webrtc::DataChannelInterface> channel_;
+  rtc::scoped_refptr<webrtc::DataChannelInterface> channel_;
   DataChannelInterface::DataState state_;
 };
 
@@ -91,7 +91,7 @@
  public:
   static DummySetSessionDescriptionObserver* Create() {
     return
-        new talk_base::RefCountedObject<DummySetSessionDescriptionObserver>();
+        new rtc::RefCountedObject<DummySetSessionDescriptionObserver>();
   }
   virtual void OnSuccess() {
     LOG(INFO) << __FUNCTION__;
@@ -145,15 +145,15 @@
   virtual int AddRef() { return 1; }
   virtual int Release() { return 0; }
  private:
-  talk_base::scoped_refptr<webrtc::PeerConnectionFactoryInterface>
+  rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface>
       peer_connection_factory_;
   webrtc::PeerConnectionInterface::IceServers servers_;
   webrtc::PeerConnectionInterface::IceServer server_;
   webrtc::FakeConstraints constraints_;
-  talk_base::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection_;
-  talk_base::scoped_refptr<webrtc::AudioTrackInterface> audio_track_;
-  talk_base::scoped_refptr<webrtc::MediaStreamInterface> stream_;
-  talk_base::scoped_refptr<webrtc::DataChannelInterface> data_channel_;
+  rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection_;
+  rtc::scoped_refptr<webrtc::AudioTrackInterface> audio_track_;
+  rtc::scoped_refptr<webrtc::MediaStreamInterface> stream_;
+  rtc::scoped_refptr<webrtc::DataChannelInterface> data_channel_;
 };
 
 const char kStunServerUri[] = "stun:stun.l.google.com:19302";
@@ -170,7 +170,7 @@
 }
 
 bool WebRtcConnectionManager::InitConnection() {
-  FakeIdentityService* dtls_service = talk_base::SSLStreamAdapter::HaveDtlsSrtp() ? new FakeIdentityService() : NULL;
+  FakeIdentityService* dtls_service = rtc::SSLStreamAdapter::HaveDtlsSrtp() ? new FakeIdentityService() : NULL;
   peer_connection_ = peer_connection_factory_->CreatePeerConnection(servers_,        NULL, NULL, dtls_service, this);
   audio_track_ = peer_connection_factory_->CreateAudioTrack(kAudioLabel,
                                                             NULL);
@@ -264,7 +264,7 @@
 int main(int argc, char **argv) {
   WebRtcConnectionManager manager;
 
-  talk_base::InitializeSSL(NULL);
+  rtc::InitializeSSL(NULL);
 
   while (1) {
     std::string input;
@@ -314,7 +314,7 @@
       }
     }
   }
-  talk_base::CleanupSSL();
+  rtc::CleanupSSL();
   return 0;
 }

comment:36 Changed 3 years ago by cjb

Aw, that's frustrating. I've got to try to get this code upstream so they'll take care of their (apparently many) API breaks for us. Thanks for taking a stab at it, I should be able to get it working again this week.

comment:37 Changed 3 years ago by cjb

dcf, you were super close -- here are the only changes needed on top of those you already made:

--- webrtc_cmd_dcf.cc	2014-11-15 21:58:44.300202059 -0500
+++ webrtc_cmd.cc	2014-11-15 21:59:02.703906098 -0500
@@ -166,7 +166,6 @@
   servers_.push_back(server_);
   constraints_.SetMandatoryReceiveAudio(false);
   constraints_.SetMandatoryReceiveVideo(false);
-  constraints_.AddOptional(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, webrtc::MediaConstraintsInterface::kValueTrue);
 }
 
 bool WebRtcConnectionManager::InitConnection() {
@@ -176,7 +175,7 @@
                                                             NULL);
   stream_ = peer_connection_factory_->CreateLocalMediaStream(kStreamLabel);
   stream_->AddTrack(audio_track_);
-  peer_connection_->AddStream(stream_, &constraints);
+  peer_connection_->AddStream(stream_);
   data_channel_ = peer_connection_->CreateDataChannel("test1", NULL);
   data_channel_->RegisterObserver(new ChatDataChannelObserver(data_channel_));
   return true;

Also needed to add more requirements to the build script, which I copied from those for peerconnection_client:

--- libjingle_examples_cjb.gyp	2014-11-15 22:01:55.617125522 -0500
+++ libjingle_examples.gyp	2014-11-15 22:02:08.768914041 -0500
@@ -100,6 +100,9 @@
       ],
       'dependencies': [
         'libjingle.gyp:libjingle',
+        '<(DEPTH)/third_party/jsoncpp/jsoncpp.gyp:jsoncpp',
+        'libjingle.gyp:libjingle_peerconnection',
+        '<@(libjingle_tests_additional_deps)',
       ],
       # TODO(ronghuawu): crbug.com/167187 fix size_t to int truncations.
       'msvs_disabled_warnings': [ 4309, ],

Then re-run gclient sync --force followed by ninja, and the resulting binary is able to text chat with serverless-webrtc in-browser.

comment:38 Changed 3 years ago by cjb

I'm not sure if or where I described how to actually use the binary, so let me do that here:

  • cd out/Debug
  • ./webrtc_cmd
  • init
  • offer
  • print

move to serverless-webrtc, click join, paste the offer you just printed, receive reply

  • reply

paste reply from serverless-webrtc, you should see lots of "Connection created" messages

  • chat

on serverless-webrtc, click "Okay, I sent it!" to make the modal disappear; now you can exchange messages

comment:39 in reply to:  38 Changed 3 years ago by dcf

Replying to cjb:

I'm not sure if or where I described how to actually use the binary, so let me do that here:

  • cd out/Debug
  • ./webrtc_cmd
  • init
  • offer
  • print

move to serverless-webrtc, click join, paste the offer you just printed, receive reply

  • reply

paste reply from serverless-webrtc, you should see lots of "Connection created" messages

  • chat

on serverless-webrtc, click "Okay, I sent it!" to make the modal disappear; now you can exchange messages

That's great. It all worked for me, including communication between Chrome and webrtc_cmd. I added the updated patch and the webrtc_cmd instructions to the webrtc branch.

comment:40 Changed 3 years ago by dcf

cjb links this project, a DataChannel-only libwebrtc:
https://github.com/js-platform/libwebrtc

comment:41 Changed 22 months ago by arlolra

Cc: arlolra serene added; arlolra@… removed
Resolution: implemented
Severity: Normal
Status: newclosed

With the announcement of snowflake (https://lists.torproject.org/pipermail/tor-dev/2016-January/010310.html), let's consider this investigation resolved.

Note: See TracTickets for help on using tickets.