OSDN Git Service

Fix network plugin to reflect the api documentation.
authorLuiz Augusto von Dentz <luiz.dentz@indt.org.br>
Wed, 23 Jul 2008 21:45:34 +0000 (18:45 -0300)
committerLuiz Augusto von Dentz <luiz.dentz@indt.org.br>
Mon, 28 Jul 2008 13:49:02 +0000 (10:49 -0300)
network/connection.c
network/main.c
network/manager.c

index 3e99a86..d0b60c8 100644 (file)
@@ -52,9 +52,7 @@
 #include "common.h"
 #include "connection.h"
 
-#define NETWORK_PANU_INTERFACE "org.bluez.network.Peer"
-#define NETWORK_GN_INTERFACE "org.bluez.network.Hub"
-#define NETWORK_NAP_INTERFACE "org.bluez.network.Router"
+#define NETWORK_PEER_INTERFACE "org.bluez.network.Peer"
 
 typedef enum {
        CONNECTED,
@@ -62,15 +60,20 @@ typedef enum {
        DISCONNECTED
 } conn_state;
 
-struct network_conn {
-       DBusMessage     *msg;
+struct network_peer {
        bdaddr_t        src;
        bdaddr_t        dst;
        char            *path;          /* D-Bus path */
+       GSList          *connections;
+};
+
+struct network_conn {
+       DBusMessage     *msg;
        char            dev[16];        /* Interface name */
        uint16_t        id;             /* Role: Service Class Identifier */
        conn_state      state;
        int             sk;
+       struct network_peer *peer;
 };
 
 struct __service_16 {
@@ -80,14 +83,34 @@ struct __service_16 {
 
 static DBusConnection *connection = NULL;
 static const char *prefix = NULL;
-static GSList *connections = NULL;
+static GSList *peers = NULL;
+
+static struct network_peer *find_peer(GSList *list, const char *path)
+{
+       GSList *l;
+
+       for (l = list; l; l = l->next) {
+               struct network_peer *peer = l->data;
+
+               if (!strcmp(peer->path, path))
+                       return peer;
+       }
+
+       return NULL;
+}
 
-gint find_connection(gconstpointer a, gconstpointer b)
+static struct network_conn *find_connection(GSList *list, uint16_t id)
 {
-       const struct network_conn *nc = a;
-       const char *path = b;
+       GSList *l;
+
+       for (l = list; l; l = l->next) {
+               struct network_conn *nc = l->data;
 
-       return strcmp(nc->path, path);
+               if (nc->id == id)
+                       return nc;
+       }
+
+       return NULL;
 }
 
 static inline DBusMessage *not_supported(DBusMessage *msg)
@@ -120,35 +143,17 @@ static inline DBusMessage *connection_attempt_failed(DBusMessage *msg, int err)
                                err ? strerror(err) : "Connection attempt failed");
 }
 
-static const char *id2iface(uint16_t id)
-{
-       switch (id) {
-       case BNEP_SVC_PANU:
-               return NETWORK_PANU_INTERFACE;
-               break;
-       case BNEP_SVC_GN:
-               return NETWORK_GN_INTERFACE;
-               break;
-       case BNEP_SVC_NAP:
-               return NETWORK_NAP_INTERFACE;
-               break;
-       default:
-               return NULL;
-       }
-}
-
 static gboolean bnep_watchdog_cb(GIOChannel *chan, GIOCondition cond,
                                gpointer data)
 {
        struct network_conn *nc = data;
 
        if (connection != NULL) {
-               const char *interface = id2iface(nc->id);
-
-               g_dbus_emit_signal(connection, nc->path,
-                                               interface,
-                                               "Disconnected",
-                                               DBUS_TYPE_INVALID);
+               const char *device = nc->dev;
+               g_dbus_emit_signal(connection, nc->peer->path,
+                               NETWORK_PEER_INTERFACE, "Disconnected",
+                               DBUS_TYPE_STRING, &device,
+                               DBUS_TYPE_INVALID);
        }
 
        info("%s disconnected", nc->dev);
@@ -171,7 +176,7 @@ static gboolean bnep_connect_cb(GIOChannel *chan, GIOCondition cond,
        gsize r;
        int sk;
        DBusMessage *reply;
-       const char *pdev;
+       const char *pdev, *uuid;
 
        if (cond & G_IO_NVAL)
                return FALSE;
@@ -224,16 +229,18 @@ static gboolean bnep_connect_cb(GIOChannel *chan, GIOCondition cond,
        }
 
        bnep_if_up(nc->dev, nc->id);
-       g_dbus_emit_signal(connection, nc->path,
-                                       id2iface(nc->id),
-                                       "Connected",
-                                       DBUS_TYPE_INVALID);
-
        pdev = nc->dev;
+       uuid = bnep_uuid(nc->id);
 
-       reply = g_dbus_create_reply(nc->msg, DBUS_TYPE_STRING, &pdev,
-                                                       DBUS_TYPE_INVALID);
-       g_dbus_send_message(connection, reply);
+       g_dbus_send_reply(connection, nc->msg,
+                       DBUS_TYPE_STRING, &pdev,
+                       DBUS_TYPE_INVALID);
+
+       g_dbus_emit_signal(connection, nc->peer->path,
+                       NETWORK_PEER_INTERFACE, "Connected",
+                       DBUS_TYPE_STRING, &pdev,
+                       DBUS_TYPE_STRING, &uuid,
+                       DBUS_TYPE_INVALID);
 
        nc->state = CONNECTED;
 
@@ -317,33 +324,32 @@ failed:
        g_dbus_send_message(connection, reply);
 }
 
-static DBusMessage *get_interface(DBusConnection *conn,
-                                       DBusMessage *msg, void *data)
-{
-       struct network_conn *nc = data;
-       const char *pdev = nc->dev;
-
-       if (nc->state != CONNECTED)
-               return not_connected(msg);
-
-       return g_dbus_create_reply(msg, DBUS_TYPE_STRING, &pdev,
-                                               DBUS_TYPE_INVALID);
-}
-
 /* Connect and initiate BNEP session */
 static DBusMessage *connection_connect(DBusConnection *conn,
                                                DBusMessage *msg, void *data)
 {
-       struct network_conn *nc = 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 NULL;
+
+       id = bnep_service_id(svc);
+       nc = find_connection(peer->connections, id);
+       if (!nc)
+               return not_supported(msg);
+
        if (nc->state != DISCONNECTED)
                return already_connected(msg);
 
        nc->state = CONNECTING;
        nc->msg = dbus_message_ref(msg);
 
-       err = bt_l2cap_connect(&nc->src, &nc->dst, BNEP_PSM, BNEP_MTU,
+       err = bt_l2cap_connect(&peer->src, &peer->dst, BNEP_PSM, BNEP_MTU,
                                                        connect_cb, nc);
        if (err < 0) {
                error("Connect failed. %s(%d)", strerror(errno), errno);
@@ -361,11 +367,11 @@ static DBusMessage *connection_cancel(DBusConnection *conn,
 {
        struct network_conn *nc = data;
 
-       if (nc->state != CONNECTING)
-               return no_pending_connect(msg);
-
-       close(nc->sk);
-       nc->state = DISCONNECTED;
+       if (nc->state == CONNECTED) {
+               bnep_if_down(nc->dev);
+               bnep_kill_connection(&nc->peer->dst);
+       } else
+               close(nc->sk);
 
        return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
@@ -373,22 +379,36 @@ static DBusMessage *connection_cancel(DBusConnection *conn,
 static DBusMessage *connection_disconnect(DBusConnection *conn,
                                        DBusMessage *msg, void *data)
 {
-       struct network_conn *nc = data;
+       struct network_peer *peer = data;
+       GSList *l;
 
-       if (nc->state != CONNECTED)
-               return not_connected(msg);
+       for (l = peer->connections; l; l = l->next) {
+               struct network_conn *nc = l->data;
 
-       bnep_if_down(nc->dev);
-       bnep_kill_connection(&nc->dst);
+               if (nc->state == DISCONNECTED)
+                       continue;
 
-       return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+               return connection_cancel(conn, msg, nc);
+       }
+
+       return not_connected(msg);
 }
 
 static DBusMessage *is_connected(DBusConnection *conn,
                                DBusMessage *msg, void *data)
 {
-       struct network_conn *nc = data;
-       gboolean up = (nc->state == CONNECTED);
+       struct network_peer *peer = data;
+       GSList *l;
+       dbus_bool_t up = FALSE;
+
+       for (l = peer->connections; l; l = l->next) {
+               struct network_conn *nc = l->data;
+
+               if (nc->state != CONNECTED)
+                       continue;
+
+               up = TRUE;
+       }
 
        return g_dbus_create_reply(msg, DBUS_TYPE_BOOLEAN, &up,
                                                DBUS_TYPE_INVALID);
@@ -396,94 +416,126 @@ static DBusMessage *is_connected(DBusConnection *conn,
 
 static void connection_free(struct network_conn *nc)
 {
-       if (!nc)
-               return;
-
-       if (nc->path)
-               g_free(nc->path);
-
        if (nc->state == CONNECTED) {
                bnep_if_down(nc->dev);
-               bnep_kill_connection(&nc->dst);
-       }
+               bnep_kill_connection(&nc->peer->dst);
+       } else if (nc->state == CONNECTING)
+               close(nc->sk);
 
        g_free(nc);
        nc = NULL;
 }
 
+static void peer_free(struct network_peer *peer)
+{
+       g_slist_foreach(peer->connections, (GFunc) connection_free, NULL);
+       g_slist_free(peer->connections);
+       g_free(peer->path);
+       g_free(peer);
+}
+
 static void path_unregister(void *data)
 {
-       struct network_conn *nc = data;
-       const char *interface = id2iface(nc->id);
+       struct network_peer *peer = data;
 
-       info("Unregistered interface %s on path %s", interface, nc->path);
+       info("Unregistered interface %s on path %s",
+               NETWORK_PEER_INTERFACE, peer->path);
 
-       connections = g_slist_remove(connections, nc);
-       connection_free(nc);
+       peers = g_slist_remove(peers, peer);
+       peer_free(peer);
 }
 
 static GDBusMethodTable connection_methods[] = {
-       { "GetInterface",       "",     "s",    get_interface           },
-       { "Connect",            "",     "s",    connection_connect,
+       { "Connect",            "s",    "s",    connection_connect,
                                                G_DBUS_METHOD_FLAG_ASYNC },
-       { "CancelConnect",      "",     "",     connection_cancel       },
        { "Disconnect",         "",     "",     connection_disconnect   },
        { "IsConnected",        "",     "b",    is_connected            },
        { }
 };
 
 static GDBusSignalTable connection_signals[] = {
-       { "Connected",          ""      },
-       { "Disconnected",       "     },
+       { "Connected",          "ss"    },
+       { "Disconnected",       "s"     },
        { }
 };
 
 void connection_unregister(const char *path, uint16_t id)
 {
-       const char *interface = id2iface(id);
+       struct network_peer *peer;
+       struct network_conn *nc;
+
+       peer = find_peer(peers, path);
+       if (!peer)
+               return;
+
+       nc = find_connection(peer->connections, id);
+       if (!nc)
+               return;
+
+       peer->connections = g_slist_remove(peer->connections, nc);
+       connection_free(nc);
+       if (peer->connections)
+               return;
+
+       g_dbus_unregister_interface(connection, path, NETWORK_PEER_INTERFACE);
+}
+
+static struct network_peer *create_peer(const char *path, bdaddr_t *src,
+                               bdaddr_t *dst)
+{
+       struct network_peer *peer;
+
+       peer = g_new0(struct network_peer, 1);
+       peer->path = g_strdup(path);
+       bacpy(&peer->src, src);
+       bacpy(&peer->dst, dst);
+
+       if (g_dbus_register_interface(connection, path,
+                                       NETWORK_PEER_INTERFACE,
+                                       connection_methods,
+                                       connection_signals, NULL,
+                                       peer, path_unregister) == FALSE) {
+               error("D-Bus failed to register %s interface",
+                       NETWORK_PEER_INTERFACE);
+               g_free(peer);
+               return NULL;
+       }
+
+       info("Registered interface %s on path %s",
+               NETWORK_PEER_INTERFACE, path);
 
-       g_dbus_unregister_interface(connection, path, interface);
+       return peer;
 }
 
 int connection_register(const char *path, bdaddr_t *src, bdaddr_t *dst,
                        uint16_t id)
 {
+       struct network_peer *peer;
        struct network_conn *nc;
-       bdaddr_t default_src;
-       int dev_id;
-       const char *interface;
 
        if (!path)
                return -EINVAL;
 
-       bacpy(&default_src, BDADDR_ANY);
-       dev_id = hci_get_route(&default_src);
-       if (dev_id < 0 || hci_devba(dev_id, &default_src) < 0)
-               return -1;
-
-       nc = g_new0(struct network_conn, 1);
-       interface = id2iface(id);
-
-       if (g_dbus_register_interface(connection, path,
-                                       interface,
-                                       connection_methods,
-                                       connection_signals, NULL,
-                                       nc, path_unregister) == FALSE) {
-               error("D-Bus failed to register %s interface", interface);
-               return -1;
+       peer = find_peer(peers, path);
+       if (!peer) {
+               peer = create_peer(path, src, dst);
+               if (!peer)
+                       return -1;
+               peers = g_slist_append(peers, peer);
        }
 
-       nc->path = g_strdup(path);
-       bacpy(&nc->src, src);
-       bacpy(&nc->dst, dst);
+       nc = find_connection(peer->connections, id);
+       if (nc)
+               return 0;
+
+       nc = g_new0(struct network_conn, 1);
        nc->id = id;
        memset(nc->dev, 0, 16);
        strncpy(nc->dev, prefix, strlen(prefix));
        nc->state = DISCONNECTED;
+       nc->peer = peer;
 
-       connections = g_slist_append(connections, nc);
-
-       info("Registered interface %s on path %s", interface, path);
+       peer->connections = g_slist_append(peer->connections, nc);
 
        return 0;
 }
index e422092..414ff93 100644 (file)
@@ -33,7 +33,6 @@
 #include <gdbus.h>
 
 #include "plugin.h"
-#include "device.h"
 #include "logging.h"
 #include "manager.h"
 
index b3ba1cd..22a6e70 100644 (file)
@@ -45,8 +45,8 @@
 #include "textfile.h"
 #include "glib-helper.h"
 
-#include "../hcid/adapter.h"
-#include "../hcid/device.h"
+#include "adapter.h"
+#include "device.h"
 #include "error.h"
 #include "bridge.h"
 #include "manager.h"
@@ -80,12 +80,14 @@ static void register_server(uint16_t id)
        server_store(path);
 }
 
-static int network_probe(struct btd_device *device, uint16_t id)
+static int network_probe(struct btd_device_driver *driver,
+                       struct btd_device *device, GSList *records)
 {
        struct adapter *adapter = device_get_adapter(device);
        const gchar *path = device_get_path(device);
        const char *source, *destination;
        bdaddr_t src, dst;
+       uint16_t id;
 
        DBG("path %s", path);
 
@@ -94,74 +96,41 @@ static int network_probe(struct btd_device *device, uint16_t id)
 
        str2ba(source, &src);
        str2ba(destination, &dst);
+       id = bnep_service_id(driver->uuids[0]);
 
        return connection_register(path, &src, &dst, id);
 }
 
-static int panu_probe(struct btd_device_driver *driver,
-                       struct btd_device *device, GSList *records)
-{
-       return network_probe(device, BNEP_SVC_PANU);
-}
-
-static int gn_probe(struct btd_device_driver *driver,
-                       struct btd_device *device, GSList *records)
-{
-       return network_probe(device, BNEP_SVC_GN);
-}
-
-static int nap_probe(struct btd_device_driver *driver,
-                       struct btd_device *device, GSList *records)
-{
-       return network_probe(device, BNEP_SVC_NAP);
-}
-
-static void network_remove(struct btd_device *device, uint16_t id)
+static void network_remove(struct btd_device_driver *driver,
+                       struct btd_device *device)
 {
        const gchar *path = device_get_path(device);
+       uint16_t id = bnep_service_id(driver->uuids[0]);
 
        DBG("path %s", path);
 
        connection_unregister(path, id);
 }
 
-static void panu_remove(struct btd_device_driver *driver,
-                       struct btd_device *device)
-{
-       network_remove(device, BNEP_SVC_PANU);
-}
-
-static void gn_remove(struct btd_device_driver *driver,
-                       struct btd_device *device)
-{
-       network_remove(device, BNEP_SVC_GN);
-}
-
-static void nap_remove(struct btd_device_driver *driver,
-                       struct btd_device *device)
-{
-       network_remove(device, BNEP_SVC_NAP);
-}
-
 static struct btd_device_driver network_panu_driver = {
        .name   = "network-panu",
        .uuids  = BTD_UUIDS(PANU_UUID),
-       .probe  = panu_probe,
-       .remove = panu_remove,
+       .probe  = network_probe,
+       .remove = network_remove,
 };
 
 static struct btd_device_driver network_gn_driver = {
        .name   = "network-gn",
        .uuids  = BTD_UUIDS(GN_UUID),
-       .probe  = gn_probe,
-       .remove = gn_remove,
+       .probe  = network_probe,
+       .remove = network_remove,
 };
 
 static struct btd_device_driver network_nap_driver = {
        .name   = "network-nap",
        .uuids  = BTD_UUIDS(NAP_UUID),
-       .probe  = nap_probe,
-       .remove = nap_remove,
+       .probe  = network_probe,
+       .remove = network_remove,
 };
 
 int network_manager_init(DBusConnection *conn, struct network_conf *service_conf)