From b53fa04f47b54e08733ba3859bfaac171ab1c7af Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Sun, 25 Sep 2011 11:18:03 +0200 Subject: [WIP] Add support for transporting audio data using udp --- src/cmumble.c | 35 ++++++-------- src/cmumble.h | 6 +++ src/connection.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/connection.h | 9 ++++ 4 files changed, 163 insertions(+), 23 deletions(-) diff --git a/src/cmumble.c b/src/cmumble.c index 00e7afa..844a4d3 100644 --- a/src/cmumble.c +++ b/src/cmumble.c @@ -93,28 +93,19 @@ recv_server_sync(MumbleProto__ServerSync *sync, struct cmumble_context *ctx) static void recv_crypt_setup(MumbleProto__CryptSetup *crypt, struct cmumble_context *ctx) { -#if 0 - int i; - - if (crypt->has_key) { - g_print("key: 0x"); - for (i = 0; i < crypt->key.len; ++i) - g_print("%x", crypt->key.data[i]); - g_print("\n"); - } - if (crypt->has_client_nonce) { - g_print("client nonce: 0x"); - for (i = 0; i < crypt->client_nonce.len; ++i) - g_print("%x", crypt->client_nonce.data[i]); - g_print("\n"); - } - if (crypt->has_server_nonce) { - g_print("server nonce: 0x"); - for (i = 0; i < crypt->server_nonce.len; ++i) - g_print("%x", crypt->server_nonce.data[i]); - g_print("\n"); - } -#endif + /* FIXME: require all data lengths to be 16? */ + + ctx->ocb_key = g_memdup(crypt->key.data, + crypt->key.len); + ctx->ocb_client_nonce = g_memdup(crypt->client_nonce.data, + crypt->client_nonce.len); + ctx->ocb_server_nonce = g_memdup(crypt->server_nonce.data, + crypt->server_nonce.len); + + ctx->ocb = ocb_aes_init(ctx->ocb_key, 16, NULL); + g_assert(ctx->ocb); + + cmumble_connection_udp_init(ctx); } static void diff --git a/src/cmumble.h b/src/cmumble.h index 8caa9ef..9e65ec2 100644 --- a/src/cmumble.h +++ b/src/cmumble.h @@ -11,6 +11,7 @@ #include "connection.h" #include "audio.h" #include "commands.h" +#include "ocb/ocb.h" typedef void (*callback_t)(ProtobufCMessage *msg, struct cmumble_context *); @@ -32,6 +33,11 @@ struct cmumble_context { GList *users; GList *channels; + + keystruct *ocb; + guchar *ocb_key; + guchar *ocb_client_nonce; + guchar *ocb_server_nonce; }; struct cmumble_user { diff --git a/src/connection.c b/src/connection.c index c93dbc7..66b2cdd 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,140 @@ read_cb(GObject *pollable_stream, gpointer data) return TRUE; } +static gboolean +read_udp(GSocket *socket, GIOCondition condition, gpointer user_data) +{ + GError *error = NULL; + gchar buf[1024]; + gssize size; + + size = g_socket_receive(socket, buf, sizeof(buf), NULL, &error); + + g_print("got udp data: %ld\n", size); + + return TRUE; +} + +static gboolean +read_udp_io(GIOChannel *source, GIOCondition condition, gpointer data) +{ + g_print("got udp data from channel\n"); + + return TRUE; +} + +static void +print_hex(char *hex, int num) +{ + int i; + + for (i = 0; i < num; ++i) + printf("%02x", hex[i] & 0xff); + +} + +static void +do_udp_ping(struct cmumble_context *ctx) +{ + uint8_t data[16]; + uint32_t write = 0, pos = 0; + GTimeVal tv; + GError *error = NULL; + gssize sent; + int i; + + g_get_current_time(&tv); + + data[pos++] = (udp_ping << 5); + encode_varint(&data[pos], &write, tv.tv_sec, 16-pos); + pos += write; + g_print("write: %d\n", write); + + char tag[16] = { 0 }; + char foo[16] = { 0 }; + + /* Increase nonce, see: + * http://www.cs.ucdavis.edu/~rogaway/ocb/ocb-back.htm#nonce */ + for (i = 0; i < 16; ++i) + if (++ctx->ocb_client_nonce[i]) + break; + + ocb_aes_encrypt(ctx->ocb, ctx->ocb_client_nonce, + data, pos, + foo+4, tag); + + printf("\n"); + printf("nonce: 0x"); + print_hex(ctx->ocb_client_nonce, 16); + printf("\n"); + + printf("tag: 0x"); + print_hex(tag, 3); + printf("\n"); + + printf("data: 0x"); + print_hex((char *)data, pos); + printf("\n"); + + printf("foo: 0x"); + print_hex(foo, pos+4); + printf("\n"); + + //memset(tag, 0, 128); + +#if 0 + ocb_aes_decrypt(ctx->ocb, ctx->ocb_client_nonce, + foo+4, pos, + bar, tag); + + printf("decrypt: 0x"); + print_hex(bar, pos); + printf("\n"); +#endif + + foo[0] = ctx->ocb_client_nonce[0]; + foo[1] = tag[0]; + foo[2] = tag[1]; + foo[3] = tag[2]; + + sent = g_socket_send(ctx->con.udp.sock, foo, pos+4, NULL, &error); + + g_print("udp sent: %ld\n", sent); +} + +void +cmumble_connection_udp_init(struct cmumble_context *ctx) +{ + GError *error = NULL; + + ctx->con.udp.connected = FALSE; + ctx->con.udp.sock = g_socket_new(G_SOCKET_FAMILY_IPV4, + G_SOCKET_TYPE_DATAGRAM, + G_SOCKET_PROTOCOL_UDP, + &error); + g_assert(error == NULL); + + GInetAddress *addr = g_inet_address_new_from_string("192.168.2.232"); + g_assert(addr); + GSocketAddress *saddr = g_inet_socket_address_new(addr, 64738); + + if (!g_socket_connect(ctx->con.udp.sock, saddr, NULL, &error)) + return; + + ctx->con.udp.connected = TRUE; + ctx->con.udp.source = g_socket_create_source(ctx->con.udp.sock, G_IO_IN, NULL); + g_source_set_callback(ctx->con.udp.source, (GSourceFunc) read_udp, ctx, NULL); + g_source_attach(ctx->con.udp.source, NULL); + + int fd = g_socket_get_fd(ctx->con.udp.sock); + GIOChannel* channel = g_io_channel_unix_new(fd); + g_io_add_watch(channel, G_IO_IN, + (GIOFunc) read_udp_io, ctx); + g_io_channel_unref(channel); + + do_udp_ping(ctx); +} + static void connection_ready(GObject *source_object, GAsyncResult *res, gpointer user_data) { @@ -48,7 +183,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, ctx, NULL); g_source_attach(con->source, NULL); - g_source_unref(con->source); cmumble_protocol_init(ctx); } diff --git a/src/connection.h b/src/connection.h index f37c0c7..2b9a97f 100644 --- a/src/connection.h +++ b/src/connection.h @@ -12,6 +12,12 @@ struct cmumble_connection { GOutputStream *output; GSource *source; + + struct { + GSocket *sock; + gboolean connected; + GSource *source; + } udp; }; struct cmumble_context; @@ -23,4 +29,7 @@ cmumble_connection_init(struct cmumble_context *ctx, int cmumble_connection_fini(struct cmumble_context *ctx); +void +cmumble_connection_udp_init(struct cmumble_context *ctx); + #endif /* _CONNECTION_H_ */ -- cgit