From 88b59d5500d626ce382b2edd8892d4b62ad40177 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Thu, 12 Mar 2009 11:39:51 -0300 Subject: Fix network regression which caused disconnections. --- network/connection.c | 118 ++++++++++++++++++++++----------------------------- 1 file changed, 51 insertions(+), 67 deletions(-) diff --git a/network/connection.c b/network/connection.c index 843a57a7..3f5b7660 100644 --- a/network/connection.c +++ b/network/connection.c @@ -67,7 +67,7 @@ struct network_conn { char dev[16]; /* Interface name */ uint16_t id; /* Role: Service Class Identifier */ conn_state state; - int sk; + GIOChannel *io; guint watch; /* Disconnect watch */ struct network_peer *peer; }; @@ -170,12 +170,43 @@ static gboolean bnep_watchdog_cb(GIOChannel *chan, GIOCondition cond, nc->state = DISCONNECTED; memset(nc->dev, 0, 16); strncpy(nc->dev, prefix, sizeof(nc->dev) - 1); - g_io_channel_shutdown(chan, TRUE, NULL); return FALSE; } -static gboolean bnep_connect_cb(GIOChannel *chan, GIOCondition cond, +static void cancel_connection(struct network_conn *nc, const char *err_msg) +{ + DBusMessage *reply; + + if (nc->watch) { + g_dbus_remove_watch(connection, nc->watch); + nc->watch = 0; + } + + if (nc->msg && err_msg) { + reply = connection_attempt_failed(nc->msg, err_msg); + g_dbus_send_message(connection, reply); + } + + g_io_channel_shutdown(nc->io, TRUE, NULL); + g_io_channel_unref(nc->io); + nc->io = NULL; + + nc->state = DISCONNECTED; +} + +static void connection_destroy(DBusConnection *conn, void *user_data) +{ + struct network_conn *nc = user_data; + + if (nc->state == CONNECTED) { + bnep_if_down(nc->dev); + bnep_kill_connection(&nc->peer->dst); + } else if (nc->io) + cancel_connection(nc, NULL); +} + +static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond, gpointer data) { struct network_conn *nc = data; @@ -184,7 +215,6 @@ static gboolean bnep_connect_cb(GIOChannel *chan, GIOCondition cond, char pkt[BNEP_MTU]; gsize r; int sk; - DBusMessage *reply; const char *pdev, *uuid; gboolean connected; @@ -268,15 +298,13 @@ static gboolean bnep_connect_cb(GIOChannel *chan, GIOCondition cond, /* Start watchdog */ g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL, (GIOFunc) bnep_watchdog_cb, nc); + g_io_channel_unref(nc->io); + nc->io = NULL; + return FALSE; failed: - if (nc->state != DISCONNECTED) { - nc->state = DISCONNECTED; - reply = connection_attempt_failed(nc->msg, strerror(EIO)); - g_dbus_send_message(connection, reply); - g_io_channel_shutdown(chan, TRUE, NULL); - } + cancel_connection(nc, "bnep setup failed"); return FALSE; } @@ -287,8 +315,7 @@ static int bnep_connect(struct network_conn *nc) struct __service_16 *s; struct timeval timeo; unsigned char pkt[BNEP_MTU]; - GIOChannel *io; - int err = 0; + int fd; /* Send request */ req = (void *) pkt; @@ -302,28 +329,21 @@ static int bnep_connect(struct network_conn *nc) memset(&timeo, 0, sizeof(timeo)); timeo.tv_sec = 30; - setsockopt(nc->sk, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo)); + fd = g_io_channel_unix_get_fd(nc->io); + setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo)); - io = g_io_channel_unix_new(nc->sk); - g_io_channel_set_close_on_unref(io, FALSE); + if (send(fd, pkt, sizeof(*req) + sizeof(*s), 0) < 0) + return -errno; - if (send(nc->sk, pkt, sizeof(*req) + sizeof(*s), 0) < 0) { - err = -errno; - goto out; - } + g_io_add_watch(nc->io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, + (GIOFunc) bnep_setup_cb, nc); - g_io_add_watch(io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, - (GIOFunc) bnep_connect_cb, nc); - -out: - g_io_channel_unref(io); - return err; + return 0; } static void connect_cb(GIOChannel *chan, GError *err, gpointer data) { struct network_conn *nc = data; - DBusMessage *reply; const char *err_msg; int perr; @@ -333,41 +353,17 @@ static void connect_cb(GIOChannel *chan, GError *err, gpointer data) goto failed; } - nc->sk = g_io_channel_unix_get_fd(chan); - perr = bnep_connect(nc); if (perr < 0) { err_msg = strerror(-perr); error("bnep connect(): %s (%d)", err_msg, -perr); - g_io_channel_shutdown(chan, TRUE, NULL); - g_io_channel_unref(chan); goto failed; } return; failed: - nc->state = DISCONNECTED; - if (nc->watch) { - g_dbus_remove_watch(connection, nc->watch); - nc->watch = 0; - } - - reply = connection_attempt_failed(nc->msg, err_msg); - g_dbus_send_message(connection, reply); -} - -static void connection_destroy(DBusConnection *conn, void *user_data) -{ - struct network_conn *nc = user_data; - - nc->watch = 0; - - if (nc->state == CONNECTED) { - bnep_if_down(nc->dev); - bnep_kill_connection(&nc->peer->dst); - } else - close(nc->sk); + cancel_connection(nc, err_msg); } /* Connect and initiate BNEP session */ @@ -379,7 +375,6 @@ static DBusMessage *connection_connect(DBusConnection *conn, const char *svc; uint16_t id; GError *err = NULL; - GIOChannel *io; if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &svc, DBUS_TYPE_INVALID) == FALSE) @@ -393,7 +388,7 @@ static DBusMessage *connection_connect(DBusConnection *conn, if (nc->state != DISCONNECTED) return already_connected(msg); - io = bt_io_connect(BT_IO_L2CAP, connect_cb, nc, + nc->io = bt_io_connect(BT_IO_L2CAP, connect_cb, nc, NULL, &err, BT_IO_OPT_SOURCE_BDADDR, &peer->src, BT_IO_OPT_DEST_BDADDR, &peer->dst, @@ -401,7 +396,7 @@ static DBusMessage *connection_connect(DBusConnection *conn, BT_IO_OPT_OMTU, BNEP_MTU, BT_IO_OPT_IMTU, BNEP_MTU, BT_IO_OPT_INVALID); - if (!io) { + if (!nc->io) { DBusMessage *reply; error("%s", err->message); reply = connection_attempt_failed(msg, err->message); @@ -409,8 +404,6 @@ static DBusMessage *connection_connect(DBusConnection *conn, return reply; } - g_io_channel_unref(io); - nc->state = CONNECTING; nc->msg = dbus_message_ref(msg); nc->watch = g_dbus_add_disconnect_watch(conn, @@ -431,12 +424,7 @@ static DBusMessage *connection_cancel(DBusConnection *conn, if (!g_str_equal(owner, caller)) return not_permited(msg); - if (nc->watch) { - g_dbus_remove_watch(conn, nc->watch); - nc->watch = 0; - } - - connection_destroy(conn, data); + connection_destroy(conn, nc); return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); } @@ -511,11 +499,7 @@ static DBusMessage *connection_get_properties(DBusConnection *conn, static void connection_free(struct network_conn *nc) { - if (nc->state == CONNECTED) { - bnep_if_down(nc->dev); - bnep_kill_connection(&nc->peer->dst); - } else if (nc->state == CONNECTING) - close(nc->sk); + connection_destroy(connection, nc); g_free(nc); nc = NULL; -- cgit