Re: [PATCH] bluetooth: Add bluetooth server support (based on Zhenhua code)

2011-01-18 Thread Marcel Holtmann
Hi Fred,

> Add bluetooth_ref()/bluetooth_unref() to support reference count in
> bluetooth utils.

didn't you had this as separate patch already? I think we should keep
that as a separate patch.

> ---
>  Makefile.am |2 +-
>  plugins/bluetooth.c |  396 --
>  plugins/bluetooth.h |   11 ++
>  3 files changed, 392 insertions(+), 17 deletions(-)
> 
> diff --git a/Makefile.am b/Makefile.am
> index da59be7..fb3f750 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -312,7 +312,7 @@ builtin_sources += plugins/nokiacdma.c
>  
>  if BLUETOOTH
>  builtin_modules += bluetooth
> -builtin_sources += plugins/bluetooth.c plugins/bluetooth.h
> +builtin_sources += $(btio_sources) plugins/bluetooth.c plugins/bluetooth.h
>  
>  builtin_modules += hfp
>  builtin_sources += plugins/hfp.c plugins/bluetooth.h

Please do it like this:

builtin_sources += $(btio_sources)
builtin_cflags += @BLUEZ_CFLAGS@
builtin_libadd += @BLUEZ_LIBS@

> +struct client {
> + GIOChannel  *io;
> + guint   watch;
> +};

Why do you need both. Normally only the watch is enough?

> +struct server {
> + gchar   *name;

Don't bother with gchar. Just use char.

> + guint8  channel;
> + gchar   *sdp_record;
> + GIOChannel  *io;
> + gchar   *adapter;
> + guint   handle;
> + ConnectFunc connect_cb;
> + gpointeruser_data;
> +
> + struct client   client;

Is it not simpler to just fold client_watch directly into it?

> +};
>  
>  void bluetooth_create_path(const char *dev_addr, const char *adapter_addr,
>   char *buf, int size)
> @@ -370,6 +393,246 @@ static gboolean property_changed(DBusConnection 
> *connection, DBusMessage *msg,
>   return TRUE;
>  }
>  
> +static void disconnect(struct server *server)
> +{
> + struct client *client = &server->client;
> +
> + if (!client->io)
> + return;
> +
> + g_io_channel_unref(client->io);
> + client->io = NULL;
> +
> + if (client->watch > 0) {
> + g_source_remove(client->watch);
> + client->watch = 0;
> + }
> +
> + return;

Don't bother with return for functions returning void.

> +}
> +
> +static void server_stop(gpointer data, gpointer user_data)
> +{
> + struct server *server = data;
> +
> + disconnect(server);
> +
> + if (server->handle) {

We do prefer service->handle > 0 for these cases.

> + DBusMessage *msg;
> +
> + msg = dbus_message_new_method_call(BLUEZ_SERVICE,
> + server->adapter,
> + BLUEZ_SERVICE_INTERFACE,
> + "RemoveRecord");
> + dbus_message_append_args(msg, DBUS_TYPE_UINT32, &server->handle,
> + DBUS_TYPE_INVALID);
> + g_dbus_send_message(connection, msg);
> +
> + server->handle = 0;
> + }
> +
> + if (server->io) {

And here please do server->io != NULL.

> + g_io_channel_shutdown(server->io, TRUE, NULL);
> + g_io_channel_unref(server->io);
> + server->io = NULL;
> + }
> +
> + g_free(server->adapter);
> + server->adapter = NULL;
> +}
> +
> +static gboolean client_event(GIOChannel *chan, GIOCondition cond, gpointer 
> data)
> +{
> + struct server *server = data;
> +
> + disconnect(server);
> +
> + return FALSE;
> +}
> +
> +static void cancel_authorization(struct server *server)
> +{
> + DBusMessage *msg;
> +
> + if (!server->adapter)
> + return;
> +
> + msg = dbus_message_new_method_call(BLUEZ_SERVICE, server->adapter,
> + BLUEZ_SERVICE_INTERFACE,
> + "CancelAuthorization");

Check that msg allocation succeeded before calling send.

> +
> + g_dbus_send_message(connection, msg);
> +}
> +
> +static void auth_cb(DBusPendingCall *call, gpointer user_data)
> +{
> + struct server *server = user_data;
> + struct client *client = &server->client;
> + GIOChannel *io = client->io;
> + DBusMessage *reply = dbus_pending_call_steal_reply(call);
> + DBusError derr;
> + GError *err = NULL;
> +
> + dbus_error_init(&derr);
> +
> + if (dbus_set_error_from_message(&derr, reply)) {
> + ofono_error("RequestAuthorization error: %s, %s",
> + derr.name, derr.message);
> +
> + if (dbus_error_has_name(&derr, DBUS_ERROR_NO_REPLY))
> + cancel_authorization(server);
> +
> + dbus_error_free(&derr);
> + goto failed;
> + }
> +
> + ofono_info("RequestAuthorization succeeded");
> +
> + if (!bt_io_accept(io, server->connect_cb, server->user_data,
> + NULL, &err)) {
> +

[PATCH] bluetooth: Add bluetooth server support (based on Zhenhua code)

2011-01-18 Thread Frédéric Danis
It watches Bluetooth adapter property changes and adds SDP record to
listen client connection request (refactored to support both DUN and
HFP GW servers).
Add bluetooth_ref()/bluetooth_unref() to support reference count in
bluetooth utils.
---
 Makefile.am |2 +-
 plugins/bluetooth.c |  396 --
 plugins/bluetooth.h |   11 ++
 3 files changed, 392 insertions(+), 17 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index da59be7..fb3f750 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -312,7 +312,7 @@ builtin_sources += plugins/nokiacdma.c
 
 if BLUETOOTH
 builtin_modules += bluetooth
-builtin_sources += plugins/bluetooth.c plugins/bluetooth.h
+builtin_sources += $(btio_sources) plugins/bluetooth.c plugins/bluetooth.h
 
 builtin_modules += hfp
 builtin_sources += plugins/hfp.c plugins/bluetooth.h
diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c
index 602c6da..fd6f541 100644
--- a/plugins/bluetooth.c
+++ b/plugins/bluetooth.c
@@ -35,11 +35,34 @@
 
 #include 
 
+#include 
 #include "bluetooth.h"
 
 static DBusConnection *connection;
 static GHashTable *uuid_hash = NULL;
 static GHashTable *adapter_address_hash = NULL;
+static GSList *server_list = NULL;
+static gint ref_count;
+
+#define TIMEOUT (60*1000) /* Timeout for user response (miliseconds) */
+
+struct client {
+   GIOChannel  *io;
+   guint   watch;
+};
+
+struct server {
+   gchar   *name;
+   guint8  channel;
+   gchar   *sdp_record;
+   GIOChannel  *io;
+   gchar   *adapter;
+   guint   handle;
+   ConnectFunc connect_cb;
+   gpointeruser_data;
+
+   struct client   client;
+};
 
 void bluetooth_create_path(const char *dev_addr, const char *adapter_addr,
char *buf, int size)
@@ -370,6 +393,246 @@ static gboolean property_changed(DBusConnection 
*connection, DBusMessage *msg,
return TRUE;
 }
 
+static void disconnect(struct server *server)
+{
+   struct client *client = &server->client;
+
+   if (!client->io)
+   return;
+
+   g_io_channel_unref(client->io);
+   client->io = NULL;
+
+   if (client->watch > 0) {
+   g_source_remove(client->watch);
+   client->watch = 0;
+   }
+
+   return;
+}
+
+static void server_stop(gpointer data, gpointer user_data)
+{
+   struct server *server = data;
+
+   disconnect(server);
+
+   if (server->handle) {
+   DBusMessage *msg;
+
+   msg = dbus_message_new_method_call(BLUEZ_SERVICE,
+   server->adapter,
+   BLUEZ_SERVICE_INTERFACE,
+   "RemoveRecord");
+   dbus_message_append_args(msg, DBUS_TYPE_UINT32, &server->handle,
+   DBUS_TYPE_INVALID);
+   g_dbus_send_message(connection, msg);
+
+   server->handle = 0;
+   }
+
+   if (server->io) {
+   g_io_channel_shutdown(server->io, TRUE, NULL);
+   g_io_channel_unref(server->io);
+   server->io = NULL;
+   }
+
+   g_free(server->adapter);
+   server->adapter = NULL;
+}
+
+static gboolean client_event(GIOChannel *chan, GIOCondition cond, gpointer 
data)
+{
+   struct server *server = data;
+
+   disconnect(server);
+
+   return FALSE;
+}
+
+static void cancel_authorization(struct server *server)
+{
+   DBusMessage *msg;
+
+   if (!server->adapter)
+   return;
+
+   msg = dbus_message_new_method_call(BLUEZ_SERVICE, server->adapter,
+   BLUEZ_SERVICE_INTERFACE,
+   "CancelAuthorization");
+
+   g_dbus_send_message(connection, msg);
+}
+
+static void auth_cb(DBusPendingCall *call, gpointer user_data)
+{
+   struct server *server = user_data;
+   struct client *client = &server->client;
+   GIOChannel *io = client->io;
+   DBusMessage *reply = dbus_pending_call_steal_reply(call);
+   DBusError derr;
+   GError *err = NULL;
+
+   dbus_error_init(&derr);
+
+   if (dbus_set_error_from_message(&derr, reply)) {
+   ofono_error("RequestAuthorization error: %s, %s",
+   derr.name, derr.message);
+
+   if (dbus_error_has_name(&derr, DBUS_ERROR_NO_REPLY))
+   cancel_authorization(server);
+
+   dbus_error_free(&derr);
+   goto failed;
+   }
+
+   ofono_info("RequestAuthorization succeeded");
+
+   if (!bt_io_accept(io, server->connect_cb, server->user_data,
+   NULL, &err)) {
+   ofono_error("%s", err->message);
+   g_error_free(err);
+   goto failed;
+   }
+
+