diff options
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/cmumble.c | 69 | ||||
-rw-r--r-- | src/cmumble.h | 9 | ||||
-rw-r--r-- | src/connection.c | 108 | ||||
-rw-r--r-- | src/connection.h | 30 | ||||
-rw-r--r-- | src/messages.c | 9 |
6 files changed, 151 insertions, 78 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 3418def..8af2758 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,9 +1,9 @@ bin_PROGRAMS = cmumble -noinst_HEADERS = cmumble.h varint.h io.h +noinst_HEADERS = cmumble.h varint.h io.h connection.h nodist_noinst_HEADERS = mumble.pb-c.h messages.h -cmumble_SOURCES = cmumble.c messages.c varint.c io.c +cmumble_SOURCES = cmumble.c messages.c varint.c io.c connection.c nodist_cmumble_SOURCES = mumble.pb-c.c cmumble_LDADD = $(PROTOBUF_LIBS) $(GLIB_LIBS) $(GIO_LIBS) \ diff --git a/src/cmumble.c b/src/cmumble.c index 31a5747..bb2e934 100644 --- a/src/cmumble.c +++ b/src/cmumble.c @@ -5,6 +5,7 @@ #include "varint.h" #include "cmumble.h" #include "io.h" +#include "connection.h" static struct user * find_user(struct context *ctx, uint32_t session) @@ -233,35 +234,6 @@ static struct mumble_callbacks callbacks = { .SuggestConfig = NULL, }; -static gboolean -do_ping(struct context *ctx) -{ - MumbleProto__Ping ping; - GTimeVal tv; - - g_get_current_time(&tv); - mumble_proto__ping__init(&ping); - ping.timestamp = tv.tv_sec; - ping.resync = 1; - send_msg(ctx, &ping.base); - - return TRUE; -} - -static gboolean -read_cb(GObject *pollable_stream, gpointer data) -{ - GPollableInputStream *input = G_POLLABLE_INPUT_STREAM(pollable_stream); - struct context *ctx = data; - gint count; - - do { - count = recv_msg(ctx, &callbacks); - } while (count && g_pollable_input_stream_is_readable(input)); - - return TRUE; -} - static void set_pulse_states(gpointer data, gpointer user_data) { @@ -396,8 +368,6 @@ int main(int argc, char **argv) char *host = "localhost"; unsigned int port = 64738; struct context ctx; - GError *error = NULL; - GSource *source; if (argc >= 3) host = argv[2]; @@ -409,30 +379,10 @@ int main(int argc, char **argv) ctx.users = NULL; g_type_init(); - ctx.sock_client = g_socket_client_new(); - g_socket_client_set_tls(ctx.sock_client, TRUE); - g_socket_client_set_tls_validation_flags(ctx.sock_client, - G_TLS_CERTIFICATE_INSECURE); - g_socket_client_set_family(ctx.sock_client, G_SOCKET_FAMILY_IPV4); - g_socket_client_set_protocol(ctx.sock_client, G_SOCKET_PROTOCOL_TCP); - g_socket_client_set_socket_type(ctx.sock_client, G_SOCKET_TYPE_STREAM); - - ctx.conn = g_socket_client_connect_to_host(ctx.sock_client, - host, port, NULL, &error); - if (error) { - g_printerr("connect failed: %s\n", error->message); - return 1; - } - - g_object_get(G_OBJECT(ctx.conn), - "input-stream", &ctx.input, - "output-stream", &ctx.output, NULL); + ctx.loop = g_main_loop_new(NULL, FALSE); - if (!G_IS_POLLABLE_INPUT_STREAM(ctx.input) || - !g_pollable_input_stream_can_poll(ctx.input)) { - g_printerr("Error: GSocketConnection is not pollable\n"); + if (cmumble_connection_init(&ctx, host, port, &callbacks) < 0) return 1; - } { MumbleProto__Version version; @@ -455,24 +405,12 @@ int main(int argc, char **argv) gst_init(&argc, &argv); - ctx.loop = g_main_loop_new(NULL, FALSE); - if (setup_playback_gst_pipeline(&ctx) < 0) return 1; if (setup_recording_gst_pipeline(&ctx) < 0) return 1; - source = g_pollable_input_stream_create_source(ctx.input, NULL); - g_source_set_callback(source, (GSourceFunc) read_cb, &ctx, NULL); - g_source_attach(source, NULL); - g_source_unref(source); - - source = g_timeout_source_new_seconds(5); - g_source_set_callback(source, (GSourceFunc) do_ping, &ctx, NULL); - g_source_attach(source, NULL); - g_source_unref(source); - cmumble_io_init(&ctx); g_main_loop_run(ctx.loop); @@ -480,6 +418,7 @@ int main(int argc, char **argv) g_main_loop_unref(ctx.loop); cmumble_io_fini(&ctx); + cmumble_connection_fini(&ctx); return 0; } diff --git a/src/cmumble.h b/src/cmumble.h index d9d1d53..f315368 100644 --- a/src/cmumble.h +++ b/src/cmumble.h @@ -16,21 +16,16 @@ #include "mumble.pb-c.h" #include "messages.h" #include "io.h" +#include "connection.h" struct context { + struct cmumble_connection con; struct cmumble_io io; GMainLoop *loop; uint32_t session; gboolean authenticated; - GSocketClient *sock_client; - GSocketConnection *conn; - GSocket *sock; - - GPollableInputStream *input; - GOutputStream *output; - uint8_t celt_header_packet[sizeof(CELTHeader)]; CELTHeader celt_header; CELTMode *celt_mode; diff --git a/src/connection.c b/src/connection.c new file mode 100644 index 0000000..3494d08 --- /dev/null +++ b/src/connection.c @@ -0,0 +1,108 @@ +#include <glib.h> +#include <gio/gio.h> + +#include "connection.h" +#include "cmumble.h" + +static gboolean +read_cb(GObject *pollable_stream, gpointer data) +{ + GPollableInputStream *input = G_POLLABLE_INPUT_STREAM(pollable_stream); + struct context *ctx = data; + gint count; + + do { + count = recv_msg(ctx, ctx->con.callbacks); + } while (count && g_pollable_input_stream_is_readable(input)); + + return TRUE; +} + +static gboolean +do_ping(struct context *ctx) +{ + MumbleProto__Ping ping; + GTimeVal tv; + + g_get_current_time(&tv); + mumble_proto__ping__init(&ping); + ping.timestamp = tv.tv_sec; + ping.resync = 1; + send_msg(ctx, &ping.base); + + return TRUE; +} + +static void +setup_ping_timer(struct context *ctx) +{ + GSource *source; + + source = g_timeout_source_new_seconds(5); + g_source_set_callback(source, (GSourceFunc) do_ping, ctx, NULL); + g_source_attach(source, NULL); + g_source_unref(source); +} + +int +cmumble_connection_init(struct context *ctx, + const char *host, int port, + struct mumble_callbacks *callbacks) +{ + struct cmumble_connection *con = &ctx->con; + GError *error = NULL; + + con->callbacks = callbacks; + con->sock_client = g_socket_client_new(); + g_socket_client_set_tls(con->sock_client, TRUE); + g_socket_client_set_tls_validation_flags(con->sock_client, + G_TLS_CERTIFICATE_INSECURE); + g_socket_client_set_family(con->sock_client, G_SOCKET_FAMILY_IPV4); + g_socket_client_set_protocol(con->sock_client, + G_SOCKET_PROTOCOL_TCP); + g_socket_client_set_socket_type(con->sock_client, + G_SOCKET_TYPE_STREAM); + + con->conn = + g_socket_client_connect_to_host(con->sock_client, + host, port, NULL, &error); + if (error) { + g_printerr("connect failed: %s\n", error->message); + return -1; + } + + g_object_get(G_OBJECT(con->conn), + "input-stream", &con->input, + "output-stream", &con->output, NULL); + + if (!G_IS_POLLABLE_INPUT_STREAM(con->input) || + !g_pollable_input_stream_can_poll(con->input)) { + g_printerr("Error: GSocketConnection is not pollable\n"); + return 1; + } + + 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); + + setup_ping_timer(ctx); + + return 0; +} + +int +cmumble_connection_fini(struct context *ctx) +{ + g_source_remove(g_source_get_id(ctx->con.source)); + g_source_unref(ctx->con.source); + + g_object_unref(G_OBJECT(ctx->con.input)); + g_object_unref(G_OBJECT(ctx->con.output)); + + g_io_stream_close(G_IO_STREAM(ctx->con.conn), NULL, NULL); + g_object_unref(G_OBJECT(ctx->con.conn)); + g_object_unref(G_OBJECT(ctx->con.sock_client)); + + return 0; +} diff --git a/src/connection.h b/src/connection.h new file mode 100644 index 0000000..e38150d --- /dev/null +++ b/src/connection.h @@ -0,0 +1,30 @@ +#ifndef _CONNECTION_H_ +#define _CONNECTION_H_ + +#include <glib.h> + +struct cmumble_connection { + GSocketClient *sock_client; + GSocketConnection *conn; + GSocket *sock; + + GPollableInputStream *input; + GOutputStream *output; + + GSource *source; + + struct mumble_callbacks *callbacks; +}; + +struct context; +struct mumble_callbacks; + +int +cmumble_connection_init(struct context *ctx, + const char *host, int port, + struct mumble_callbacks *cbs); + +int +cmumble_connection_fini(struct context *ctx); + +#endif /* _CONNECTION_H_ */ diff --git a/src/messages.c b/src/messages.c index 899ac14..8807166 100644 --- a/src/messages.c +++ b/src/messages.c @@ -63,8 +63,8 @@ send_msg(struct context *ctx, ProtobufCMessage *msg) add_preamble(preamble, type, buffer.len); g_static_mutex_lock(&write_mutex); - g_output_stream_write(ctx->output, preamble, PREAMBLE_SIZE, NULL, NULL); - g_output_stream_write(ctx->output, buffer.data, buffer.len, NULL, NULL); + g_output_stream_write(ctx->con.output, preamble, PREAMBLE_SIZE, NULL, NULL); + g_output_stream_write(ctx->con.output, buffer.data, buffer.len, NULL, NULL); g_static_mutex_unlock(&write_mutex); PROTOBUF_C_BUFFER_SIMPLE_CLEAR(&buffer); @@ -81,7 +81,7 @@ recv_msg(struct context *ctx, const struct mumble_callbacks *cbs) const callback_t *callbacks = (const callback_t *) cbs; GError *error = NULL; - ret = g_pollable_input_stream_read_nonblocking(ctx->input, + ret = g_pollable_input_stream_read_nonblocking(ctx->con.input, preamble, PREAMBLE_SIZE, NULL, &error); @@ -109,7 +109,8 @@ recv_msg(struct context *ctx, const struct mumble_callbacks *cbs) g_printerr("out of mem\n"); g_main_loop_quit (ctx->loop); } - ret = g_input_stream_read(G_INPUT_STREAM(ctx->input), data, len, NULL, NULL); + ret = g_input_stream_read(G_INPUT_STREAM(ctx->con.input), + data, len, NULL, NULL); /* tunneled udp data - not a regular protobuf message * create dummy ProtobufCMessage */ |