static DBusMessage *connection_get_properties(DBusConnection *conn, DBusMessage *msg, void *data) { struct network_peer *peer = data; struct network_conn *nc = NULL; DBusMessage *reply; DBusMessageIter iter; DBusMessageIter dict; dbus_bool_t connected; const char *property; GSList *l; reply = dbus_message_new_method_return(msg); if (!reply) return NULL; dbus_message_iter_init_append(reply, &iter); dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); /* Connected */ for (l = peer->connections; l; l = l->next) { struct network_conn *tmp = l->data; if (tmp->state != CONNECTED) continue; nc = tmp; break; } connected = nc ? TRUE : FALSE; dict_append_entry(&dict, "Connected", DBUS_TYPE_BOOLEAN, &connected); /* Interface */ property = nc ? nc->dev : ""; dict_append_entry(&dict, "Interface", DBUS_TYPE_STRING, &property); /* UUID */ property = nc ? bnep_uuid(nc->id) : ""; dict_append_entry(&dict, "UUID", DBUS_TYPE_STRING, &property); dbus_message_iter_close_container(&iter, &dict); return reply; }
static gboolean network_property_get_uuid(const GDBusPropertyTable *property, DBusMessageIter *iter, void *data) { struct network_peer *peer = data; struct network_conn *nc; const char *uuid; nc = find_connection_by_state(peer->connections, CONNECTED); if (nc == NULL) return FALSE; uuid = bnep_uuid(nc->id); dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &uuid); return TRUE; }
static DBusMessage *local_connect(DBusConnection *conn, DBusMessage *msg, void *data) { struct network_peer *peer = data; struct btd_service *service; struct network_conn *nc; const char *svc; const char *uuid; uint16_t id; int err; if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &svc, DBUS_TYPE_INVALID) == FALSE) return btd_error_invalid_args(msg); id = bnep_service_id(svc); uuid = bnep_uuid(id); if (uuid == NULL) return btd_error_invalid_args(msg); service = btd_device_get_service(peer->device, uuid); if (service == NULL) return btd_error_not_supported(msg); nc = btd_service_get_user_data(service); if (nc->connect != NULL) return btd_error_busy(msg); err = connection_connect(nc->service); if (err < 0) return btd_error_failed(msg, strerror(-err)); nc->connect = dbus_message_ref(msg); return NULL; }
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 *pdev, *uuid; gboolean connected; if (cond & G_IO_NVAL) return FALSE; 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); pdev = nc->dev; uuid = bnep_uuid(nc->id); g_dbus_send_reply(connection, nc->msg, DBUS_TYPE_STRING, &pdev, DBUS_TYPE_INVALID); connected = TRUE; emit_property_changed(connection, nc->peer->path, NETWORK_PEER_INTERFACE, "Connected", DBUS_TYPE_BOOLEAN, &connected); emit_property_changed(connection, nc->peer->path, NETWORK_PEER_INTERFACE, "Interface", DBUS_TYPE_STRING, &pdev); emit_property_changed(connection, nc->peer->path, NETWORK_PEER_INTERFACE, "UUID", DBUS_TYPE_STRING, &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, "bnep setup failed"); return FALSE; }