summaryrefslogtreecommitdiff
path: root/src/connection.c
diff options
context:
space:
mode:
authorBenjamin Franzke <benjaminfranzke@googlemail.com>2011-09-25 11:18:03 +0200
committerBenjamin Franzke <benjaminfranzke@googlemail.com>2012-02-12 19:27:21 +0100
commit81e0d7d65a55be7df908567da622e1e2f249ceec (patch)
treee1c71557d865f7bcc2a6495200f8d74e3264bb7f /src/connection.c
parent269297401c5b63f3f462a66b2e7652e726ad605a (diff)
downloadcmumble-81e0d7d65a55be7df908567da622e1e2f249ceec.tar.gz
cmumble-81e0d7d65a55be7df908567da622e1e2f249ceec.tar.bz2
cmumble-81e0d7d65a55be7df908567da622e1e2f249ceec.zip
Add support for transporting audio data using udpudp-3
With crypt.c importet from umurmur, changed encrypt key to use raw_key instead of decrypt_iv.
Diffstat (limited to 'src/connection.c')
-rw-r--r--src/connection.c114
1 files changed, 113 insertions, 1 deletions
diff --git a/src/connection.c b/src/connection.c
index 7fefdb3..e7f74bd 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -3,6 +3,7 @@
#include "connection.h"
#include "cmumble.h"
+#include "varint.h"
static gboolean
read_cb(GObject *pollable_stream, gpointer data)
@@ -18,6 +19,118 @@ read_cb(GObject *pollable_stream, gpointer data)
return TRUE;
}
+static gboolean
+read_udp_socket(GSocket *socket, GIOCondition condition, gpointer user_data)
+{
+ struct cmumlbe *cm = user_data;
+ GError *error = NULL;
+ guchar data[1024];
+ guchar plain[1020];
+ gssize size;
+
+ size = g_socket_receive(socket, (gchar *) data, sizeof(data),
+ NULL, &error);
+ if (size <= 4)
+ return TRUE;
+
+ if (!CryptState_decrypt(&cm->crypt, data, plain, size))
+ return TRUE;
+
+ cm->con.udp.connected = TRUE;
+
+ cmumble_read_udp_data(cm, plain, size - 4);
+
+ return TRUE;
+}
+
+static void
+send_udp_tcptunnel(struct cmumlbe *cm, guint8 *data, gsize len)
+{
+ MumbleProto__UDPTunnel tunnel;
+
+ mumble_proto__udptunnel__init(&tunnel);
+ tunnel.packet.data = data;
+ tunnel.packet.len = len;
+ cmumble_send_msg(cm, &tunnel.base);
+}
+
+static void
+send_udp(struct cmumlbe *cm, guint8 *data, gsize len)
+{
+ guint8 encrypted[1024];
+ GError *error = NULL;
+
+ g_assert(len <= (sizeof(encrypted) - 4));
+
+ CryptState_encrypt(&cm->crypt, data, encrypted, len);
+ g_socket_send(cm->con.udp.sock, (gchar *) encrypted, len + 4,
+ NULL, &error);
+}
+
+void
+cmumble_connection_send_udp_data(struct cmumlbe *cm, guint8 *data, gsize len)
+{
+ if (cm->con.udp.connected)
+ send_udp(cm, data, len);
+ else
+ send_udp_tcptunnel(cm, data, len);
+}
+
+static void
+do_udp_ping(struct cmumlbe *cm)
+{
+ uint8_t data[16];
+ uint32_t written = 0, pos = 0;
+ GTimeVal tv;
+
+ g_get_current_time(&tv);
+
+ data[pos++] = (udp_ping << 5);
+ encode_varint(&data[pos], &written, tv.tv_sec, sizeof(data)-pos);
+ pos += written;
+
+ send_udp(cm, data, pos);
+
+ g_print("udp ping sent: timestamp: %ld\n", tv.tv_sec);
+}
+
+void
+cmumble_connection_udp_init(struct cmumlbe *cm)
+{
+ GError *error = NULL;
+ GSocketAddress *saddr;
+
+ cm->con.udp.connected = FALSE;
+ cm->con.udp.sock = g_socket_new(G_SOCKET_FAMILY_IPV4,
+ G_SOCKET_TYPE_DATAGRAM,
+ G_SOCKET_PROTOCOL_UDP,
+ &error);
+ g_assert(error == NULL);
+
+ saddr = g_socket_connection_get_remote_address(cm->con.conn, &error);
+ if (saddr == NULL) {
+ g_printerr("Failed to get remote address for udp setup: %s\n",
+ error->message);
+ return;
+ }
+
+ if (!g_socket_connect(cm->con.udp.sock, saddr, NULL, &error)) {
+ g_object_unref(saddr);
+ g_object_unref(cm->con.udp.sock);
+ cm->con.udp.sock = NULL;
+ return;
+ }
+ g_object_unref(saddr);
+
+ cm->con.udp.source = g_socket_create_source(cm->con.udp.sock,
+ G_IO_IN, NULL);
+ g_source_set_callback(cm->con.udp.source,
+ (GSourceFunc) read_udp_socket, cm, NULL);
+ g_source_attach(cm->con.udp.source, NULL);
+
+ do_udp_ping(cm);
+}
+
static void
connection_ready(GObject *source_object, GAsyncResult *res, gpointer user_data)
{
@@ -48,7 +161,6 @@ connection_ready(GObject *source_object, GAsyncResult *res, gpointer user_data)
con->source = g_pollable_input_stream_create_source(con->input, NULL);
g_source_set_callback(con->source, (GSourceFunc) read_cb, cm, NULL);
g_source_attach(con->source, NULL);
- g_source_unref(con->source);
cmumble_protocol_init(cm);
}