Fix network plugin to reflect the api documentation.

This commit is contained in:
Luiz Augusto von Dentz 2008-07-23 18:45:34 -03:00
parent debc2efd75
commit 56f867d9b7
3 changed files with 181 additions and 161 deletions

View 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;
gint find_connection(gconstpointer a, gconstpointer b)
static struct network_peer *find_peer(GSList *list, const char *path)
{
const struct network_conn *nc = a;
const char *path = b;
GSList *l;
return strcmp(nc->path, path);
for (l = list; l; l = l->next) {
struct network_peer *peer = l->data;
if (!strcmp(peer->path, path))
return peer;
}
return NULL;
}
static struct network_conn *find_connection(GSList *list, uint16_t id)
{
GSList *l;
for (l = list; l; l = l->next) {
struct network_conn *nc = l->data;
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;
g_dbus_unregister_interface(connection, path, interface);
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);
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;
}

View File

@ -33,7 +33,6 @@
#include <gdbus.h>
#include "plugin.h"
#include "device.h"
#include "logging.h"
#include "manager.h"

View 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)