aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Barksdale <amatus@amat.us>2020-01-06 18:03:07 -0600
committerDavid Barksdale <amatus@amat.us>2020-01-06 18:03:07 -0600
commit6c0f267e26db5b71d06e90f5884be08168baaf30 (patch)
treeb050401ccb04f502bebe2a78c542385eaf946d19
parent5f6559d09a9685b840c8581ca871c2695eece5e0 (diff)
WIP: WebRTC transport
-rw-r--r--gnunet-build/packages/gnunet/gnunet/files/configuration.js2
-rw-r--r--gnunet-build/packages/gnunet/gnunet/files/plugin_transport_webrtc.c96
-rw-r--r--gnunet-build/packages/gnunet/gnunet/files/plugin_transport_webrtc_int.js66
-rw-r--r--src/cljs/gnunet_web/service.cljs6
-rw-r--r--src/cljs/gnunet_web/webrtc.cljs68
5 files changed, 194 insertions, 44 deletions
diff --git a/gnunet-build/packages/gnunet/gnunet/files/configuration.js b/gnunet-build/packages/gnunet/gnunet/files/configuration.js
index d67d53f..f227ec6 100644
--- a/gnunet-build/packages/gnunet/gnunet/files/configuration.js
+++ b/gnunet-build/packages/gnunet/gnunet/files/configuration.js
@@ -25,7 +25,7 @@ mergeInto(LibraryManager.library, {
transport: {
UNIXPATH: 'transport',
NEIGHBOUR_LIMIT: 50,
- PLUGINS: 'http_client',
+ PLUGINS: 'http_client webrtc',
},
ats: {
UNIXPATH: 'ats',
diff --git a/gnunet-build/packages/gnunet/gnunet/files/plugin_transport_webrtc.c b/gnunet-build/packages/gnunet/gnunet/files/plugin_transport_webrtc.c
index cea8633..f20e3b1 100644
--- a/gnunet-build/packages/gnunet/gnunet/files/plugin_transport_webrtc.c
+++ b/gnunet-build/packages/gnunet/gnunet/files/plugin_transport_webrtc.c
@@ -442,8 +442,25 @@ webrtc_plugin_string_to_address (void *cls,
static void
-create_offer_cb(void *cls,
- char *offer)
+offer_cb(void *cls,
+ char *offer)
+{
+ struct GNUNET_ATS_Session *s = cls;
+ struct GNUNET_MQ_Handle *mq = GNUNET_CADET_get_mq (s->channel);
+ size_t offer_len = strlen (offer);
+ struct GNUNET_MessageHeader *msg;
+ struct GNUNET_MQ_Envelope *env = GNUNET_MQ_msg_extra (msg, offer_len, MESSAGE_TYPE_WEBRTC_OFFER);
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending our offer `%s'\n",
+ offer);
+ memcpy (&msg[1], offer, offer_len);
+ GNUNET_MQ_send (mq, env);
+}
+
+
+static void
+message_cb(void *cls, uint8_t *data, int length)
{
struct GNUNET_ATS_Session *s = cls;
GNUNET_break (0);
@@ -466,6 +483,9 @@ check_answer (void *cls,
}
+extern void set_remote_answer(int, void *, int);
+
+
/**
* Functions with this signature are called whenever a complete answer
* is received.
@@ -478,6 +498,8 @@ handle_answer (void *cls,
const struct GNUNET_MessageHeader *message)
{
struct GNUNET_ATS_Session *s = cls;
+ uint16_t size = ntohs(message->size);
+ set_remote_answer(s->rtc_peer_connection, &message[1], size - sizeof(*message));
GNUNET_break (0);
}
@@ -522,6 +544,7 @@ out_disconnect_cb (void *cls,
GNUNET_break (0);
}
+extern int peer_connect(void *, void *, void *, void *, int, void *);
/**
* Create a new session to transmit data to the target
@@ -571,20 +594,7 @@ webrtc_plugin_get_session (void *cls,
out_disconnect_cb,
handlers);
GNUNET_assert (s->channel != NULL);
-
- extern int create_connection(void *, void *);
-
- s->rtc_peer_connection = create_connection(create_offer_cb, s);
- /* Create RTCPeerConnection, call createOffer, when the returned promise is fulfilled, send it:
- struct GNUNET_MessageHeader msg;
- struct GNUNET_MQ_Envelope *env = GNUNET_MQ_msg (msg, MESSAGE_TYPE_WEBRTC_OFFER);
-
- GNUNET_MQ_notify_sent (env,
- &transmit_pending,
- mh);
- GNUNET_MQ_send (mq,
- env);
- */
+ s->rtc_peer_connection = peer_connect(offer_cb, NULL, message_cb, NULL, 0, s);
notify_session_monitor (plugin,
s,
GNUNET_TRANSPORT_SS_INIT);
@@ -661,6 +671,23 @@ webrtc_plugin_setup_monitor (void *cls,
}
+static void
+answer_cb(void *cls,
+ char *answer)
+{
+ struct GNUNET_ATS_Session *s = cls;
+ struct GNUNET_MQ_Handle *mq = GNUNET_CADET_get_mq (s->channel);
+ size_t answer_len = strlen (answer);
+ struct GNUNET_MessageHeader *msg;
+ struct GNUNET_MQ_Envelope *env = GNUNET_MQ_msg_extra (msg, answer_len, MESSAGE_TYPE_WEBRTC_ANSWER);
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending our answer `%s'\n",
+ answer);
+ memcpy (&msg[1], answer, answer_len);
+ GNUNET_MQ_send (mq, env);
+}
+
/**
* Check if payload is sane (size contains payload).
*
@@ -688,6 +715,12 @@ static void
handle_offer (void *cls,
const struct GNUNET_MessageHeader *message)
{
+ struct GNUNET_ATS_Session *s = cls; // XXX right?
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "handle_offer called with session %p\n",
+ s);
+ uint16_t size = ntohs(message->size);
+ s->rtc_peer_connection = peer_connect(NULL, answer_cb, message_cb, &message[1], size - sizeof(*message), s);
GNUNET_break (0);
}
@@ -699,15 +732,40 @@ handle_offer (void *cls,
* @param channel the channel representing the cadet
* @param initiator the identity of the peer who wants to establish a cadet
* with us; NULL on binding error
- * @return initial channel context (our `struct CadetClient`)
+ * @return initial channel context (our `struct GNUNET_ATS_Session`)
*/
static void *
connect_cb (void *cls,
struct GNUNET_CADET_Channel *channel,
const struct GNUNET_PeerIdentity *initiator)
{
- GNUNET_break (0);
- return NULL;
+ struct Plugin *plugin = cls;
+ struct GNUNET_ATS_Session *s;
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Got CADET connection from peer `%s'\n",
+ GNUNET_i2s (initiator));
+ /* find existing session */
+ s = GNUNET_CONTAINER_multipeermap_get (plugin->sessions,
+ initiator);
+ if (NULL == s)
+ {
+ GNUNET_break (0);
+ return s;
+ }
+ s = GNUNET_new (struct GNUNET_ATS_Session);
+ s->plugin = plugin;
+ s->peer = *initiator;
+ s->channel = channel;
+ /* add new session */
+ (void) GNUNET_CONTAINER_multipeermap_put (plugin->sessions,
+ &s->peer,
+ s,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Returning session %p\n",
+ s);
+ return s;
}
diff --git a/gnunet-build/packages/gnunet/gnunet/files/plugin_transport_webrtc_int.js b/gnunet-build/packages/gnunet/gnunet/files/plugin_transport_webrtc_int.js
index 33fd3c1..cafc2f7 100644
--- a/gnunet-build/packages/gnunet/gnunet/files/plugin_transport_webrtc_int.js
+++ b/gnunet-build/packages/gnunet/gnunet/files/plugin_transport_webrtc_int.js
@@ -15,33 +15,55 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
mergeInto(LibraryManager.library, {
- $RTC_CONFIG: {iceServers: [{url: "stun:stun.l.google.com:19302"}]},
$CONNECTIONS: [],
$NEXT_CONNECTION: 1,
- create_connection__deps: ["$RTC_CONFIG", "$CONNECTIONS", "$NEXT_CONNECTION"],
- create_connection: function(offer_cb, cls) {
- var conn = new RTCPeerConnection(RTC_CONFIG);
- chan = conn.createDataChannel("data", {ordered: false,
- maxRetransmits: 0,
- negotiated: true,
- id: 1});
- chan.onopen = function(e) {
- console.warn("channel open");
+ peer_connect__deps: ["$CONNECTIONS", "$NEXT_CONNECTION"],
+ peer_connect: function(offer_cb, answer_cb, message_cb, offer_ptr, offer_size, cls) {
+ var offer;
+ if (0 != offer_ptr) {
+ offer = Pointer_stringify(offer_ptr, offer_size);
+ }
+ var channel = new MessageChannel();
+ var port = channel.port1;
+ port.onmessage = function(e) {
+ if ('offer' == e.data.type && 0 != offer_cb) {
+ ccallFunc(
+ getFuncWrapper(offer_cb, 'vii'),
+ 'void',
+ ['number', 'string'],
+ [cls, e.data.sdp]);
+ } else if ('answer' == e.data.type && 0 != answer_cb) {
+ ccallFunc(
+ getFuncWrapper(answer_cb, 'vii'),
+ 'void',
+ ['number', 'string'],
+ [cls, e.data.sdp]);
+ } else if ('message' == e.data.type) {
+ console.error('got webrtc message:', e.data);
+ } else {
+ console.error('unhandled message on webrtc message channel', e.data);
+ }
};
- chan.onmessage = function(e) {
- console.warn("channel got message:", e);
- };
- offer = conn.createOffer();
- offer.then(function(e) {
- console.warn("created offer:", e);
- ccallFunc(
- getFuncWrapper(offer_cb, 'vii'),
- 'void',
- ['number', 'string'],
- [cls, e.sdp]);
+ do_to_window(function(w) {
+ w.postMessage({
+ type: 'peer_connect',
+ offer: offer,
+ message_port: channel.port2}, [channel.port2]);
});
- CONNECTIONS[NEXT_CONNECTION] = {conn: conn, chan: chan};
+ CONNECTIONS[NEXT_CONNECTION] = port;
return NEXT_CONNECTION++;
+ },
+ set_remote_answer__deps: ["$CONNECTIONS"],
+ set_remote_answer: function(num, answer_ptr, answer_size) {
+ var port = CONNECTIONS[num];
+ port.postMessage({type: 'answer', sdp: Pointer_stringify(answer_ptr, answer_size)});
+ },
+ peer_disconnect__deps: ["$CONNECTIONS"],
+ peer_disconnect: function(num) {
+ var port = CONNECTIONS[num];
+ port.postMessage({type: 'disconnect'});
+ port.close();
+ delete CONNECTIONS[num];
}
});
diff --git a/src/cljs/gnunet_web/service.cljs b/src/cljs/gnunet_web/service.cljs
index e7e8254..0eea5a2 100644
--- a/src/cljs/gnunet_web/service.cljs
+++ b/src/cljs/gnunet_web/service.cljs
@@ -1,5 +1,5 @@
;; service.cljs - service manager for gnunet-web website
-;; Copyright (C) 2013-2015 David Barksdale <amatus@amat.us>
+;; Copyright (C) 2013-2018 David Barksdale <amatus@amat.us>
;;
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
@@ -15,7 +15,8 @@
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
(ns gnunet-web.service
- (:require [cognitect.transit :as t]))
+ (:require [cognitect.transit :as t]
+ [gnunet-web.webrtc :refer [peer-connect]]))
(def private-key
;; XXX This has no synchronization!
@@ -68,6 +69,7 @@
"client_connect" (client-connect (aget data "service_name")
(aget data "client_name")
(aget data "message_port"))
+ "peer_connect" (peer-connect (aget data "message_port") (aget data "offer"))
(.warn js/console worker-name data))))
(catch :default e
(js/console.error "REKT" e))))
diff --git a/src/cljs/gnunet_web/webrtc.cljs b/src/cljs/gnunet_web/webrtc.cljs
new file mode 100644
index 0000000..d43292e
--- /dev/null
+++ b/src/cljs/gnunet_web/webrtc.cljs
@@ -0,0 +1,68 @@
+;; webrtc.cljs - WebRTC functions for gnunet-web
+;; Copyright (C) 2018 David Barksdale <amatus@amat.us>
+;;
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+(ns gnunet-web.webrtc)
+
+(def rtc-config
+ (clj->js
+ {:ice-servers [{:url "stun:stun.l.google.com:19302"}]}))
+
+(def data-channel-config
+ (clj->js
+ {:ordered false
+ :maxRetransmits 0
+ :negotiated true
+ :id 1}))
+
+(defn peer-connect
+ [message-port offer]
+ (.debug js/console "peer-connect called with offer:" offer)
+ (let [connection (js/RTCPeerConnection. rtc-config)
+ channel (.createDataChannel connection
+ "data"
+ data-channel-config)]
+ (set! (.-onopen channel)
+ nil)
+ (set! (.-onmessage channel)
+ nil)
+ (if (empty? offer)
+ (.then (.createOffer connection)
+ (fn [offer]
+ (.debug js/console "created offer:" offer)
+ (.setLocalDescription connection offer)
+ (.postMessage message-port
+ (js-obj "type" "offer"
+ "sdp" (.-sdp offer)))))
+ (.then (.setRemoteDescription connection
+ (js-obj "type" "offer"
+ "sdp" offer))
+ (fn []
+ (.then (.createAnswer connection)
+ (fn [answer]
+ (.debug js/console "created answer:" answer)
+ (.setLocalDescription connection answer)
+ (.postMessage message-port
+ (js-obj "type" "answer"
+ "sdp" (.-sdp answer))))))))
+ (set! (.-onmessage message-port)
+ (fn [e]
+ (.debug js/console "got webrtc message-channel message" e)
+ (let [data (.-data e)]
+ (condp = (.-type data)
+ "answer" (.then (.setRemoteDescription connection
+ (js-obj "type" "answer"
+ "sdp" (.-sdp data)))
+ (fn []))))))))