From 0624791ea6e917d6c9ecb8e7e6e5a1327199448d Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 21 Dec 2012 01:21:32 +0200 Subject: [PATCH] Revert "network: Remove Network.Connect and Network.Disconnect" This reverts commit 9c62de94e5044038bcaae6cd6c0ec783fbee607a. For convenience (mainly for ConnMan) bring back Network1.Connect/Disconnect since they also give the interface name directly. --- doc/network-api.txt | 26 ++++++++++ profiles/network/common.c | 25 ++++++++++ profiles/network/common.h | 1 + profiles/network/connection.c | 94 ++++++++++++++++++++++++++++++++++- 4 files changed, 145 insertions(+), 1 deletion(-) diff --git a/doc/network-api.txt b/doc/network-api.txt index 2ec59abcb..109da28bf 100644 --- a/doc/network-api.txt +++ b/doc/network-api.txt @@ -9,6 +9,32 @@ Service org.bluez Interface org.bluez.Network1 Object path [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX +Methods string Connect(string uuid) + + Connect to the network device and return the network + interface name. Examples of the interface name are + bnep0, bnep1 etc. + + uuid can be either one of "gn", "panu" or "nap" (case + insensitive) or a traditional string representation of + UUID or a hexadecimal number. + + The connection will be closed and network device + released either upon calling Disconnect() or when + the client disappears from the message bus. + + Possible errors: org.bluez.Error.AlreadyConnected + org.bluez.Error.ConnectionAttemptFailed + + void Disconnect() + + Disconnect from the network device. + + To abort a connection attempt in case of errors or + timeouts in the client it is fine to call this method. + + Possible errors: org.bluez.Error.Failed + Properties boolean Connected [readonly] Indicates if the device is connected. diff --git a/profiles/network/common.c b/profiles/network/common.c index 8589a3e9c..34bdc0e6e 100644 --- a/profiles/network/common.c +++ b/profiles/network/common.c @@ -59,6 +59,31 @@ static struct { { NULL } }; +uint16_t bnep_service_id(const char *svc) +{ + int i; + uint16_t id; + + /* Friendly service name */ + for (i = 0; __svc[i].name; i++) { + if (!strcasecmp(svc, __svc[i].name)) + return __svc[i].id; + } + + /* UUID 128 string */ + for (i = 0; __svc[i].uuid128; i++) { + if (!strcasecmp(svc, __svc[i].uuid128)) + return __svc[i].id; + } + + /* Try convert to HEX */ + id = strtol(svc, NULL, 16); + if ((id < BNEP_SVC_PANU) || (id > BNEP_SVC_GN)) + return 0; + + return id; +} + const char *bnep_uuid(uint16_t id) { int i; diff --git a/profiles/network/common.h b/profiles/network/common.h index ca357c496..9a8caac0b 100644 --- a/profiles/network/common.h +++ b/profiles/network/common.h @@ -24,6 +24,7 @@ int bnep_init(void); int bnep_cleanup(void); +uint16_t bnep_service_id(const char *svc); const char *bnep_uuid(uint16_t id); const char *bnep_name(uint16_t id); diff --git a/profiles/network/connection.c b/profiles/network/connection.c index 5fa3e1b8f..b56312fe0 100644 --- a/profiles/network/connection.c +++ b/profiles/network/connection.c @@ -73,6 +73,7 @@ struct network_conn { struct network_peer *peer; guint attempt_cnt; guint timeout_source; + DBusMessage *connect; }; struct __service_16 { @@ -147,6 +148,24 @@ static gboolean bnep_watchdog_cb(GIOChannel *chan, GIOCondition cond, return FALSE; } +static void local_connect_cb(struct network_conn *nc, int err) +{ + DBusConnection *conn = btd_get_dbus_connection(); + const char *pdev = nc->dev; + + if (err < 0) { + DBusMessage *reply = btd_error_failed(nc->connect, + strerror(-err)); + g_dbus_send_message(conn, reply); + } else { + g_dbus_send_reply(conn, nc->connect, DBUS_TYPE_STRING, &pdev, + DBUS_TYPE_INVALID); + } + + dbus_message_unref(nc->connect); + nc->connect = NULL; +} + static void cancel_connection(struct network_conn *nc, int err) { if (nc->timeout_source > 0) { @@ -155,6 +174,8 @@ static void cancel_connection(struct network_conn *nc, int err) } network_connected(nc->peer->device, nc->id, err); + if (nc->connect) + local_connect_cb(nc, err); g_io_channel_shutdown(nc->io, TRUE, NULL); g_io_channel_unref(nc->io); @@ -259,6 +280,8 @@ static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond, bnep_if_up(nc->dev); network_connected(nc->peer->device, nc->id, 0); + if (nc->connect) + local_connect_cb(nc, 0); conn = btd_get_dbus_connection(); path = device_get_path(nc->peer->device); @@ -374,6 +397,38 @@ failed: cancel_connection(nc, -EIO); } +static DBusMessage *local_connect(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct network_peer *peer = data; + struct network_conn *nc; + const char *svc; + 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); + + nc = find_connection(peer->connections, id); + if (nc && nc->connect) + return btd_error_busy(msg); + + err = connection_connect(peer->device, id); + if (err < 0) + return btd_error_failed(msg, strerror(-err)); + + nc = find_connection(peer->connections, id); + if (!nc) + return btd_error_failed(msg, strerror(-err)); + + nc->connect = dbus_message_ref(msg); + + return NULL; +} + /* Connect and initiate BNEP session */ int connection_connect(struct btd_device *device, uint16_t id) { @@ -435,6 +490,29 @@ int connection_disconnect(struct btd_device *device, uint16_t id) return 0; } +static DBusMessage *local_disconnect(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct network_peer *peer = data; + GSList *l; + + for (l = peer->connections; l; l = l->next) { + struct network_conn *nc = l->data; + int err; + + if (nc->state == DISCONNECTED) + continue; + + err = connection_disconnect(peer->device, nc->id); + if (err < 0) + return btd_error_failed(msg, strerror(-err)); + + return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); + } + + return btd_error_not_connected(msg); +} + static gboolean network_property_get_connected(const GDBusPropertyTable *property, DBusMessageIter *iter, void *data) @@ -510,6 +588,9 @@ static void connection_free(void *data) connection_destroy(NULL, nc); + if (nc->connect) + dbus_message_unref(nc->connect); + g_free(nc); nc = NULL; } @@ -532,6 +613,16 @@ static void path_unregister(void *data) peer_free(peer); } +static const GDBusMethodTable connection_methods[] = { + { GDBUS_ASYNC_METHOD("Connect", + GDBUS_ARGS({"uuid", "s"}), + GDBUS_ARGS({"interface", "s"}), + local_connect) }, + { GDBUS_METHOD("Disconnect", + NULL, NULL, local_disconnect) }, + { } +}; + static const GDBusPropertyTable connection_properties[] = { { "Connected", "b", network_property_get_connected }, { "Interface", "s", network_property_get_interface, NULL, @@ -569,7 +660,8 @@ static struct network_peer *create_peer(struct btd_device *device) if (g_dbus_register_interface(btd_get_dbus_connection(), path, NETWORK_PEER_INTERFACE, - NULL, NULL, connection_properties, + connection_methods, + NULL, connection_properties, peer, path_unregister) == FALSE) { error("D-Bus failed to register %s interface", NETWORK_PEER_INTERFACE); -- 2.47.3