From 50b50c99540b85b307bb0e0b169928594c088838 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Sat, 24 Sep 2011 11:30:45 +0200 Subject: Use an asynchronous connection initiation So we arent blocked, and unable to handle cmdline interaction while connecting. --- src/audio.c | 6 +++++ src/cmumble.c | 61 +++++++++++++++++++++++++++++++-------------- src/cmumble.h | 5 ++++ src/connection.c | 75 +++++++++++++++++++++++--------------------------------- 4 files changed, 84 insertions(+), 63 deletions(-) diff --git a/src/audio.c b/src/audio.c index 4d6c5dd..eae47e8 100644 --- a/src/audio.c +++ b/src/audio.c @@ -26,6 +26,12 @@ pull_buffer(GstAppSink *sink, gpointer user_data) MumbleProto__UDPTunnel tunnel; static int seq = 0; + /* FIXME: Make this more generic/disable pulling + * the pipeline completely if not connected? + */ + if (ctx->con.conn == NULL) + return GST_FLOW_OK; + buf = gst_app_sink_pull_buffer(ctx->audio.sink); if (++seq <= 2) { diff --git a/src/cmumble.c b/src/cmumble.c index 7069029..f815456 100644 --- a/src/cmumble.c +++ b/src/cmumble.c @@ -188,6 +188,47 @@ static const struct { .SuggestConfig = NULL, }; +static gboolean +do_ping(struct cmumble_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; + cmumble_send_msg(ctx, &ping.base); + + return TRUE; +} + +void +cmumble_protocol_init(struct cmumble_context *ctx) +{ + MumbleProto__Version version; + MumbleProto__Authenticate authenticate; + GSource *source; + + mumble_proto__version__init(&version); + version.version = 0x010203; + version.release = PACKAGE_STRING; + version.os = "Gentoo/Linux"; + cmumble_send_msg(ctx, &version.base); + + mumble_proto__authenticate__init(&authenticate); + authenticate.username = ctx->user_name; + authenticate.password = ""; + authenticate.n_celt_versions = 1; + authenticate.celt_versions = (int32_t[]) { 0x8000000b }; + cmumble_send_msg(ctx, &authenticate.base); + + 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 main(int argc, char **argv) { char *host = "localhost"; @@ -201,6 +242,7 @@ int main(int argc, char **argv) memset(&ctx, 0, sizeof(ctx)); + ctx.user_name = argv[1]; ctx.users = NULL; g_type_init(); @@ -211,25 +253,6 @@ int main(int argc, char **argv) if (cmumble_connection_init(&ctx, host, port) < 0) return 1; - { - MumbleProto__Version version; - mumble_proto__version__init(&version); - version.version = 0x010203; - version.release = PACKAGE_STRING; - version.os = "Gentoo/Linux"; - cmumble_send_msg(&ctx, &version.base); - } - - { - MumbleProto__Authenticate authenticate; - mumble_proto__authenticate__init(&authenticate); - authenticate.username = argv[1]; - authenticate.password = ""; - authenticate.n_celt_versions = 1; - authenticate.celt_versions = (int32_t[]) { 0x8000000b }; - cmumble_send_msg(&ctx, &authenticate.base); - } - gst_init(&argc, &argv); if (cmumble_audio_init(&ctx) < 0) diff --git a/src/cmumble.h b/src/cmumble.h index afca177..ad0ab33 100644 --- a/src/cmumble.h +++ b/src/cmumble.h @@ -26,6 +26,8 @@ struct cmumble_context { uint32_t session; gboolean authenticated; + char *user_name; + int64_t sequence; GList *users; @@ -47,4 +49,7 @@ enum udp_message_type { udp_voice_celt_beta }; +void +cmumble_protocol_init(struct cmumble_context *ctx); + #endif diff --git a/src/connection.c b/src/connection.c index 58a5e67..c93dbc7 100644 --- a/src/connection.c +++ b/src/connection.c @@ -18,55 +18,20 @@ read_cb(GObject *pollable_stream, gpointer data) return TRUE; } -static gboolean -do_ping(struct cmumble_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; - cmumble_send_msg(ctx, &ping.base); - - return TRUE; -} - static void -setup_ping_timer(struct cmumble_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 cmumble_context *ctx, - const char *host, int port) +connection_ready(GObject *source_object, GAsyncResult *res, gpointer user_data) { + struct cmumble_context *ctx = user_data; struct cmumble_connection *con = &ctx->con; GError *error = NULL; - 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); + con->conn = g_socket_client_connect_to_host_finish (con->sock_client, + res, &error); if (error) { g_printerr("connect failed: %s\n", error->message); - return -1; + g_main_loop_quit(ctx->loop); + g_error_free(error); + return; } g_object_get(G_OBJECT(con->conn), @@ -76,7 +41,8 @@ cmumble_connection_init(struct cmumble_context *ctx, 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; + g_main_loop_quit(ctx->loop); + return; } con->source = g_pollable_input_stream_create_source(con->input, NULL); @@ -84,7 +50,28 @@ cmumble_connection_init(struct cmumble_context *ctx, g_source_attach(con->source, NULL); g_source_unref(con->source); - setup_ping_timer(ctx); + cmumble_protocol_init(ctx); +} + +int +cmumble_connection_init(struct cmumble_context *ctx, + const char *host, int port) +{ + struct cmumble_connection *con = &ctx->con; + + 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); + + g_socket_client_connect_to_host_async(con->sock_client, + host, port, NULL, + connection_ready, ctx); return 0; } -- cgit