static void cancel_connection(struct network_conn *nc, int err) { btd_service_connecting_complete(nc->service, err); if (nc->connect) local_connect_cb(nc, err); g_io_channel_shutdown(nc->io, TRUE, NULL); g_io_channel_unref(nc->io); nc->io = NULL; nc->state = DISCONNECTED; }
static void bnep_conn_cb(GIOChannel *chan, char *iface, int err, void *data) { struct network_conn *nc = data; const char *path; DBusConnection *conn; DBG(""); if (err < 0) { error("connect failed %s", strerror(-err)); goto failed; } info("%s connected", nc->dev); memcpy(nc->dev, iface, sizeof(nc->dev)); btd_service_connecting_complete(nc->service, 0); if (nc->connect) local_connect_cb(nc, 0); conn = btd_get_dbus_connection(); path = device_get_path(nc->peer->device); g_dbus_emit_property_changed(conn, path, NETWORK_PEER_INTERFACE, "Connected"); g_dbus_emit_property_changed(conn, path, NETWORK_PEER_INTERFACE, "Interface"); g_dbus_emit_property_changed(conn, path, NETWORK_PEER_INTERFACE, "UUID"); nc->state = CONNECTED; nc->dc_id = device_add_disconnect_watch(nc->peer->device, disconnect_cb, nc, NULL); g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL, bnep_watchdog_cb, nc); g_io_channel_unref(nc->io); nc->io = NULL; return; failed: cancel_connection(nc, -EIO); }
static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond, gpointer data) { struct network_conn *nc = data; struct bnep_control_rsp *rsp; struct timeval timeo; char pkt[BNEP_MTU]; ssize_t r; int sk; const char *path; DBusConnection *conn; DBG("cond %u", cond); if (cond & G_IO_NVAL) return FALSE; if (nc->timeout_source > 0) { g_source_remove(nc->timeout_source); nc->timeout_source = 0; } if (cond & (G_IO_HUP | G_IO_ERR)) { error("Hangup or error on l2cap server socket"); goto failed; } sk = g_io_channel_unix_get_fd(chan); memset(pkt, 0, BNEP_MTU); r = read(sk, pkt, sizeof(pkt) -1); if (r < 0) { error("IO Channel read error"); goto failed; } if (r == 0) { error("No packet received on l2cap socket"); goto failed; } errno = EPROTO; if ((size_t) r < sizeof(*rsp)) { error("Packet received is not bnep type"); goto failed; } rsp = (void *) pkt; if (rsp->type != BNEP_CONTROL) { error("Packet received is not bnep type"); goto failed; } if (rsp->ctrl != BNEP_SETUP_CONN_RSP) return TRUE; r = ntohs(rsp->resp); if (r != BNEP_SUCCESS) { error("bnep failed"); goto failed; } memset(&timeo, 0, sizeof(timeo)); timeo.tv_sec = 0; setsockopt(sk, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo)); if (bnep_connadd(sk, BNEP_SVC_PANU, nc->dev)) { error("%s could not be added", nc->dev); goto failed; } bnep_if_up(nc->dev); btd_service_connecting_complete(nc->service, 0); if (nc->connect) local_connect_cb(nc, 0); conn = btd_get_dbus_connection(); path = device_get_path(nc->peer->device); g_dbus_emit_property_changed(conn, path, NETWORK_PEER_INTERFACE, "Connected"); g_dbus_emit_property_changed(conn, path, NETWORK_PEER_INTERFACE, "Interface"); g_dbus_emit_property_changed(conn, path, NETWORK_PEER_INTERFACE, "UUID"); nc->state = CONNECTED; nc->dc_id = device_add_disconnect_watch(nc->peer->device, disconnect_cb, nc, NULL); info("%s connected", nc->dev); /* 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: cancel_connection(nc, -EIO); return FALSE; }