Re: [PATCH] android: Move sockets handling from main to IPC code

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Syzmon,

On Mon, Dec 2, 2013 at 4:55 PM, Szymon Janc <szymon.janc@xxxxxxxxx> wrote:
> This moves IO handling to IPC code making it fully responsible for
> creating and veryfing IPC messages exchange.
> ---
>
> This should be applied on top of IPC daemon improvements.
>
>  android/ipc.c  | 273 ++++++++++++++++++++++++++++++++++++++++++---------------
>  android/ipc.h  |   4 +-
>  android/main.c | 151 +------------------------------
>  3 files changed, 207 insertions(+), 221 deletions(-)
>
> diff --git a/android/ipc.c b/android/ipc.c
> index 56f328b..1d369a8 100644
> --- a/android/ipc.c
> +++ b/android/ipc.c
> @@ -32,6 +32,10 @@
>  #include <signal.h>
>  #include <stdbool.h>
>  #include <sys/socket.h>
> +#include <sys/socket.h>
> +#include <sys/un.h>
> +#include <unistd.h>
> +#include <glib.h>
>
>  #include "hal-msg.h"
>  #include "ipc.h"
> @@ -44,19 +48,202 @@ struct service_handler {
>
>  static struct service_handler services[HAL_SERVICE_ID_MAX + 1];
>
> -static int cmd_sk = -1;
> -static int notif_sk = -1;
> +static GIOChannel *cmd_io = NULL;
> +static GIOChannel *notif_io = NULL;
>
> -void ipc_init(int command_sk, int notification_sk)
> +static void ipc_handle_msg(const void *buf, ssize_t len)
>  {
> -       cmd_sk = command_sk;
> -       notif_sk = notification_sk;
> +       const struct hal_hdr *msg = buf;
> +       const struct ipc_handler *handler;
> +
> +       if (len < (ssize_t) sizeof(*msg)) {
> +               error("IPC: message too small (%zd bytes), terminating", len);
> +               raise(SIGTERM);
> +               return;
> +       }
> +
> +       if (len != (ssize_t) (sizeof(*msg) + msg->len)) {
> +               error("IPC: message malformed (%zd bytes), terminating", len);
> +               raise(SIGTERM);
> +               return;
> +       }
> +
> +       /* if service is valid */
> +       if (msg->service_id > HAL_SERVICE_ID_MAX) {
> +               error("IPC: unknown service (0x%x), terminating",
> +                                                       msg->service_id);
> +               raise(SIGTERM);
> +               return;
> +       }
> +
> +       /* if service is registered */
> +       if (!services[msg->service_id].handler) {
> +               error("IPC: unregistered service (0x%x), terminating",
> +                                                       msg->service_id);
> +               raise(SIGTERM);
> +               return;
> +       }
> +
> +       /* if opcode is valid */
> +       if (msg->opcode == HAL_OP_STATUS ||
> +                       msg->opcode > services[msg->service_id].size) {
> +               error("IPC: invalid opcode 0x%x for service 0x%x, terminating",
> +                                               msg->opcode, msg->service_id);
> +               raise(SIGTERM);
> +               return;
> +       }
> +
> +       /* opcode is table offset + 1 */
> +       handler = &services[msg->service_id].handler[msg->opcode - 1];
> +
> +       /* if payload size is valid */
> +       if ((handler->var_len && handler->data_len > msg->len) ||
> +                       (!handler->var_len && handler->data_len != msg->len)) {
> +               error("IPC: size invalid opcode 0x%x service 0x%x, terminating",
> +                                               msg->service_id, msg->opcode);
> +               raise(SIGTERM);
> +               return;
> +       }
> +
> +       handler->handler(msg->payload, msg->len);
> +}
> +
> +static gboolean cmd_watch_cb(GIOChannel *io, GIOCondition cond,
> +                                                       gpointer user_data)
> +{
> +       char buf[BLUEZ_HAL_MTU];
> +       ssize_t ret;
> +       int fd;
> +
> +       if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
> +               info("IPC: command socket closed, terminating");
> +               goto fail;
> +       }
> +
> +       fd = g_io_channel_unix_get_fd(io);
> +
> +       ret = read(fd, buf, sizeof(buf));
> +       if (ret < 0) {
> +               error("IPC: command read failed, terminating (%s)",
> +                                                       strerror(errno));
> +               goto fail;
> +       }
> +
> +       ipc_handle_msg(buf, ret);
> +       return TRUE;
> +
> +fail:
> +       raise(SIGTERM);
> +       return FALSE;
> +}
> +
> +static gboolean notif_watch_cb(GIOChannel *io, GIOCondition cond,
> +                                                       gpointer user_data)
> +{
> +       info("IPC: notification socket closed, terminating");
> +       raise(SIGTERM);
> +
> +       return FALSE;
> +}
> +
> +static GIOChannel *connect_hal(GIOFunc connect_cb)
> +{
> +       struct sockaddr_un addr;
> +       GIOCondition cond;
> +       GIOChannel *io;
> +       int sk;
> +
> +       sk = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
> +       if (sk < 0) {
> +               error("IPC: failed to create socket: %d (%s)", errno,
> +                                                       strerror(errno));
> +               return NULL;
> +       }
> +
> +       io = g_io_channel_unix_new(sk);
> +
> +       g_io_channel_set_close_on_unref(io, TRUE);
> +       g_io_channel_set_flags(io, G_IO_FLAG_NONBLOCK, NULL);
> +
> +       memset(&addr, 0, sizeof(addr));
> +       addr.sun_family = AF_UNIX;
> +
> +       memcpy(addr.sun_path, BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH));
> +
> +       if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
> +               error("IPC: failed to connect HAL socket: %d (%s)", errno,
> +                                                       strerror(errno));
> +               g_io_channel_unref(io);
> +               return NULL;
> +       }
> +
> +       cond = G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
> +
> +       g_io_add_watch(io, cond, connect_cb, NULL);
> +
> +       return io;
> +}
> +
> +static gboolean notif_connect_cb(GIOChannel *io, GIOCondition cond,
> +                                                       gpointer user_data)
> +{
> +       DBG("");
> +
> +       if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
> +               error("IPC: notification socket connect failed, terminating");
> +               raise(SIGTERM);
> +               return FALSE;
> +       }
> +
> +       cond = G_IO_ERR | G_IO_HUP | G_IO_NVAL;
> +
> +       g_io_add_watch(io, cond, notif_watch_cb, NULL);
> +
> +       cond = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
> +
> +       g_io_add_watch(cmd_io, cond, cmd_watch_cb, NULL);
> +
> +       info("IPC: successfully connected");
> +
> +       return FALSE;
> +}
> +
> +static gboolean cmd_connect_cb(GIOChannel *io, GIOCondition cond,
> +                                                       gpointer user_data)
> +{
> +       DBG("");
> +
> +       if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
> +               error("IPC: command socket connect failed, terminating");
> +               raise(SIGTERM);
> +               return FALSE;
> +       }
> +
> +       notif_io = connect_hal(notif_connect_cb);
> +       if (!notif_io)
> +               raise(SIGTERM);
> +
> +       return FALSE;
> +}
> +
> +void ipc_init(void)
> +{
> +       cmd_io = connect_hal(cmd_connect_cb);
>  }
>
>  void ipc_cleanup(void)
>  {
> -       cmd_sk = -1;
> -       notif_sk = -1;
> +       if (cmd_io) {
> +               g_io_channel_shutdown(cmd_io, TRUE, NULL);
> +               g_io_channel_unref(cmd_io);
> +               cmd_io = NULL;
> +       }
> +
> +       if (notif_io) {
> +               g_io_channel_shutdown(notif_io, TRUE, NULL);
> +               g_io_channel_unref(notif_io);
> +               notif_io = NULL;
> +       }
>  }
>
>  static void ipc_send(int sk, uint8_t service_id, uint8_t opcode, uint16_t len,
> @@ -107,30 +294,35 @@ static void ipc_send(int sk, uint8_t service_id, uint8_t opcode, uint16_t len,
>  void ipc_send_rsp(uint8_t service_id, uint8_t opcode, uint8_t status)
>  {
>         struct hal_status s;
> +       int sk;
> +
> +       sk = g_io_channel_unix_get_fd(cmd_io);
>
>         if (status == HAL_STATUS_SUCCESS) {
> -               ipc_send(cmd_sk, service_id, opcode, 0, NULL, -1);
> +               ipc_send(sk, service_id, opcode, 0, NULL, -1);
>                 return;
>         }
>
>         s.code = status;
>
> -       ipc_send(cmd_sk, service_id, HAL_OP_STATUS, sizeof(s), &s, -1);
> +       ipc_send(sk, service_id, HAL_OP_STATUS, sizeof(s), &s, -1);
>  }
>
>  void ipc_send_rsp_full(uint8_t service_id, uint8_t opcode, uint16_t len,
>                                                         void *param, int fd)
>  {
> -       ipc_send(cmd_sk, service_id, opcode, len, param, fd);
> +       ipc_send(g_io_channel_unix_get_fd(cmd_io), service_id, opcode, len,
> +                                                               param, fd);
>  }
>
>  void ipc_send_notif(uint8_t service_id, uint8_t opcode,  uint16_t len,
>                                                                 void *param)
>  {
> -       if (notif_sk < 0)
> +       if (!notif_io)
>                 return;
>
> -       ipc_send(notif_sk, service_id, opcode, len, param, -1);
> +       ipc_send(g_io_channel_unix_get_fd(notif_io), service_id, opcode, len,
> +                                                               param, -1);
>  }
>
>  void ipc_register(uint8_t service, const struct ipc_handler *handlers,
> @@ -145,60 +337,3 @@ void ipc_unregister(uint8_t service)
>         services[service].handler = NULL;
>         services[service].size = 0;
>  }
> -
> -void ipc_handle_msg(const void *buf, ssize_t len)
> -{
> -       const struct hal_hdr *msg = buf;
> -       const struct ipc_handler *handler;
> -
> -       if (len < (ssize_t) sizeof(*msg)) {
> -               error("IPC: message too small (%zd bytes), terminating", len);
> -               raise(SIGTERM);
> -               return;
> -       }
> -
> -       if (len != (ssize_t) (sizeof(*msg) + msg->len)) {
> -               error("IPC: message malformed (%zd bytes), terminating", len);
> -               raise(SIGTERM);
> -               return;
> -       }
> -
> -       /* if service is valid */
> -       if (msg->service_id > HAL_SERVICE_ID_MAX) {
> -               error("IPC: unknown service (0x%x), terminating",
> -                                                       msg->service_id);
> -               raise(SIGTERM);
> -               return;
> -       }
> -
> -       /* if service is registered */
> -       if (!services[msg->service_id].handler) {
> -               error("IPC: unregistered service (0x%x), terminating",
> -                                                       msg->service_id);
> -               raise(SIGTERM);
> -               return;
> -       }
> -
> -       /* if opcode is valid */
> -       if (msg->opcode == HAL_OP_STATUS ||
> -                       msg->opcode > services[msg->service_id].size) {
> -               error("IPC: invalid opcode 0x%x for service 0x%x, terminating",
> -                                               msg->opcode, msg->service_id);
> -               raise(SIGTERM);
> -               return;
> -       }
> -
> -       /* opcode is table offset + 1 */
> -       handler = &services[msg->service_id].handler[msg->opcode - 1];
> -
> -       /* if payload size is valid */
> -       if ((handler->var_len && handler->data_len > msg->len) ||
> -                       (!handler->var_len && handler->data_len != msg->len)) {
> -               error("IPC: size invalid opcode 0x%x service 0x%x, terminating",
> -                                               msg->service_id, msg->opcode);
> -               raise(SIGTERM);
> -               return;
> -       }
> -
> -       handler->handler(msg->payload, msg->len);
> -}
> diff --git a/android/ipc.h b/android/ipc.h
> index 9d0c5e1..6cd102b 100644
> --- a/android/ipc.h
> +++ b/android/ipc.h
> @@ -26,7 +26,7 @@ struct ipc_handler {
>         bool var_len;
>         size_t data_len;
>  };
> -void ipc_init(int command_sk, int notification_sk);
> +void ipc_init(void);
>  void ipc_cleanup(void);
>
>  void ipc_send_rsp(uint8_t service_id, uint8_t opcode, uint8_t status);
> @@ -37,5 +37,3 @@ void ipc_send_notif(uint8_t service_id, uint8_t opcode,  uint16_t len,
>  void ipc_register(uint8_t service, const struct ipc_handler *handlers,
>                                                                 uint8_t size);
>  void ipc_unregister(uint8_t service);
> -
> -void ipc_handle_msg(const void *buf, ssize_t len);
> diff --git a/android/main.c b/android/main.c
> index c0f8901..b9655c5 100644
> --- a/android/main.c
> +++ b/android/main.c
> @@ -36,8 +36,6 @@
>  #include <unistd.h>
>
>  #include <sys/signalfd.h>
> -#include <sys/socket.h>
> -#include <sys/un.h>
>
>  #include <glib.h>
>
> @@ -69,9 +67,6 @@ static bdaddr_t adapter_bdaddr;
>
>  static GMainLoop *event_loop;
>
> -static GIOChannel *hal_cmd_io = NULL;
> -static GIOChannel *hal_notif_io = NULL;
> -
>  static bool services[HAL_SERVICE_ID_MAX + 1] = { false };
>
>  static void service_register(const void *buf, uint16_t len)
> @@ -209,127 +204,6 @@ static void stop_bluetooth(void)
>         g_timeout_add_seconds(SHUTDOWN_GRACE_SECONDS, quit_eventloop, NULL);
>  }
>
> -static gboolean cmd_watch_cb(GIOChannel *io, GIOCondition cond,
> -                                                       gpointer user_data)
> -{
> -       char buf[BLUEZ_HAL_MTU];
> -       ssize_t ret;
> -       int fd;
> -
> -       if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
> -               info("HAL command socket closed, terminating");
> -               goto fail;
> -       }
> -
> -       fd = g_io_channel_unix_get_fd(io);
> -
> -       ret = read(fd, buf, sizeof(buf));
> -       if (ret < 0) {
> -               error("HAL command read failed, terminating (%s)",
> -                                                       strerror(errno));
> -               goto fail;
> -       }
> -
> -       ipc_handle_msg(buf, ret);
> -       return TRUE;
> -
> -fail:
> -       stop_bluetooth();
> -       return FALSE;
> -}
> -
> -static gboolean notif_watch_cb(GIOChannel *io, GIOCondition cond,
> -                                                       gpointer user_data)
> -{
> -       info("HAL notification socket closed, terminating");
> -       stop_bluetooth();
> -
> -       return FALSE;
> -}
> -
> -static GIOChannel *connect_hal(GIOFunc connect_cb)
> -{
> -       struct sockaddr_un addr;
> -       GIOCondition cond;
> -       GIOChannel *io;
> -       int sk;
> -
> -       sk = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
> -       if (sk < 0) {
> -               error("Failed to create socket: %d (%s)", errno,
> -                                                       strerror(errno));
> -               return NULL;
> -       }
> -
> -       io = g_io_channel_unix_new(sk);
> -
> -       g_io_channel_set_close_on_unref(io, TRUE);
> -       g_io_channel_set_flags(io, G_IO_FLAG_NONBLOCK, NULL);
> -
> -       memset(&addr, 0, sizeof(addr));
> -       addr.sun_family = AF_UNIX;
> -
> -       memcpy(addr.sun_path, BLUEZ_HAL_SK_PATH, sizeof(BLUEZ_HAL_SK_PATH));
> -
> -       if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
> -               error("Failed to connect HAL socket: %d (%s)", errno,
> -                                                       strerror(errno));
> -               g_io_channel_unref(io);
> -               return NULL;
> -       }
> -
> -       cond = G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
> -
> -       g_io_add_watch(io, cond, connect_cb, NULL);
> -
> -       return io;
> -}
> -
> -static gboolean notif_connect_cb(GIOChannel *io, GIOCondition cond,
> -                                                       gpointer user_data)
> -{
> -       DBG("");
> -
> -       if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
> -               stop_bluetooth();
> -               return FALSE;
> -       }
> -
> -       cond = G_IO_ERR | G_IO_HUP | G_IO_NVAL;
> -
> -       g_io_add_watch(io, cond, notif_watch_cb, NULL);
> -
> -       cond = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL;
> -
> -       g_io_add_watch(hal_cmd_io, cond, cmd_watch_cb, NULL);
> -
> -       ipc_init(g_io_channel_unix_get_fd(hal_cmd_io),
> -                               g_io_channel_unix_get_fd(hal_notif_io));
> -
> -       info("Successfully connected to HAL");
> -
> -       return FALSE;
> -}
> -
> -static gboolean cmd_connect_cb(GIOChannel *io, GIOCondition cond,
> -                                                       gpointer user_data)
> -{
> -       DBG("");
> -
> -       if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
> -               stop_bluetooth();
> -               return FALSE;
> -       }
> -
> -       hal_notif_io = connect_hal(notif_connect_cb);
> -       if (!hal_notif_io) {
> -               error("Cannot connect to HAL, terminating");
> -               stop_bluetooth();
> -       }
> -
> -       return FALSE;
> -}
> -
>  static void adapter_ready(int err, const bdaddr_t *addr)
>  {
>         if (err < 0) {
> @@ -346,11 +220,7 @@ static void adapter_ready(int err, const bdaddr_t *addr)
>
>         info("Adapter initialized");
>
> -       hal_cmd_io = connect_hal(cmd_connect_cb);
> -       if (!hal_cmd_io) {
> -               error("Cannot connect to HAL, terminating");
> -               stop_bluetooth();
> -       }
> +       ipc_init();
>  }
>
>  static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
> @@ -433,23 +303,6 @@ static GOptionEntry options[] = {
>         { NULL }
>  };
>
> -static void cleanup_hal_connection(void)
> -{
> -       if (hal_cmd_io) {
> -               g_io_channel_shutdown(hal_cmd_io, TRUE, NULL);
> -               g_io_channel_unref(hal_cmd_io);
> -               hal_cmd_io = NULL;
> -       }
> -
> -       if (hal_notif_io) {
> -               g_io_channel_shutdown(hal_notif_io, TRUE, NULL);
> -               g_io_channel_unref(hal_notif_io);
> -               hal_notif_io = NULL;
> -       }
> -
> -       ipc_cleanup();
> -}
> -
>  static void cleanup_services(void)
>  {
>         int i;
> @@ -592,7 +445,7 @@ int main(int argc, char *argv[])
>
>         cleanup_services();
>
> -       cleanup_hal_connection();
> +       ipc_cleanup();
>         stop_sdp_server();
>         bt_bluetooth_cleanup();
>         g_main_loop_unref(event_loop);
> --
> 1.8.3.2
>
> --

Applied, thanks


-- 
Luiz Augusto von Dentz
--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux