gatt: Switch from pipe2 to sockepair for Acquire* 54/198154/4 accepted/tizen/unified/20190128.061448 submit/tizen/20190122.062550 submit/tizen/20190128.005753
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Mon, 21 Jan 2019 12:23:10 +0000 (17:53 +0530)
committerDoHyun Pyun <dh79.pyun@samsung.com>
Mon, 21 Jan 2019 23:45:28 +0000 (08:45 +0900)
This enables to use sendmsg with MSG_NOSIGNAL.

Change-Id: Ie28b0bfbec3730448e7d045d978909accab0f685
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Avichal <avichal.a@samsung.com>
src/gatt-client.c
src/gatt-database.c

index ddf5ad8..d667f2c 100644 (file)
@@ -98,7 +98,7 @@ struct async_dbus_op {
        async_dbus_op_complete_t complete;
 };
 
-struct pipe_io {
+struct sock_io {
        DBusMessage *msg;
        struct io *io;
        void (*destroy)(void *data);
@@ -117,8 +117,8 @@ struct characteristic {
        char *path;
 
        unsigned int ready_id;
-       struct pipe_io *write_io;
-       struct pipe_io *notify_io;
+       struct sock_io *write_io;
+       struct sock_io *notify_io;
 
        struct async_dbus_op *read_op;
        struct async_dbus_op *write_op;
@@ -1124,19 +1124,30 @@ fail:
        return btd_error_not_supported(msg);
 }
 
-static bool chrc_pipe_read(struct io *io, void *user_data)
+static bool sock_read(struct io *io, void *user_data)
 {
        struct characteristic *chrc = user_data;
        struct bt_gatt_client *gatt = chrc->service->client->gatt;
+       struct msghdr msg;
        uint8_t buf[512];
+       struct iovec iov;
        int fd = io_get_fd(io);
        ssize_t bytes_read;
 
-       bytes_read = read(fd, buf, sizeof(buf));
-       if (bytes_read < 0)
+       iov.iov_base = buf;
+       iov.iov_len = sizeof(buf);
+
+       memset(&msg, 0, sizeof(msg));
+       msg.msg_iov = &iov;
+       msg.msg_iovlen = 1;
+
+       bytes_read = recvmsg(fd, &msg, MSG_DONTWAIT);
+       if (bytes_read < 0) {
+               error("recvmsg: %s", strerror(errno));
                return false;
+       }
 
-       if (!gatt)
+       if (!gatt || bytes_read == 0)
                return false;
 
        bt_gatt_client_write_without_response(gatt, chrc->value_handle,
@@ -1146,7 +1157,7 @@ static bool chrc_pipe_read(struct io *io, void *user_data)
        return true;
 }
 
-static void pipe_io_destroy(struct pipe_io *io)
+static void sock_io_destroy(struct sock_io *io)
 {
        if (io->destroy)
                io->destroy(io->data);
@@ -1158,20 +1169,20 @@ static void pipe_io_destroy(struct pipe_io *io)
        free(io);
 }
 
-static void characteristic_destroy_pipe(struct characteristic *chrc,
+static void destroy_sock(struct characteristic *chrc,
                                                        struct io *io)
 {
        queue_remove(chrc->service->client->ios, io);
 
        if (chrc->write_io && io == chrc->write_io->io) {
-               pipe_io_destroy(chrc->write_io);
+               sock_io_destroy(chrc->write_io);
                chrc->write_io = NULL;
                g_dbus_emit_property_changed(btd_get_dbus_connection(),
                                                chrc->path,
                                                GATT_CHARACTERISTIC_IFACE,
                                                "WriteAcquired");
        } else if (chrc->notify_io) {
-               pipe_io_destroy(chrc->notify_io);
+               sock_io_destroy(chrc->notify_io);
                chrc->notify_io = NULL;
                g_dbus_emit_property_changed(btd_get_dbus_connection(),
                                                chrc->path,
@@ -1180,22 +1191,22 @@ static void characteristic_destroy_pipe(struct characteristic *chrc,
        }
 }
 
-static bool characteristic_pipe_hup(struct io *io, void *user_data)
+static bool sock_hup(struct io *io, void *user_data)
 {
        struct characteristic *chrc = user_data;
 
        DBG("%s: io %p", chrc->path, io);
 
-       characteristic_destroy_pipe(chrc, io);
+       destroy_sock(chrc, io);
 
        return false;
 }
 
-static DBusMessage *characteristic_create_pipe(struct characteristic *chrc,
+static DBusMessage *create_sock(struct characteristic *chrc,
                                                DBusMessage *msg)
 {
        struct bt_gatt_client *gatt = chrc->service->client->gatt;
-       int pipefd[2];
+       int fds[2];
        struct io *io;
        bool dir;
        uint16_t mtu;
@@ -1204,33 +1215,34 @@ static DBusMessage *characteristic_create_pipe(struct characteristic *chrc,
        if (!gatt || !bt_gatt_client_is_ready(gatt))
                return btd_error_failed(msg, "Not connected");
 
-       if (pipe2(pipefd, O_DIRECT | O_NONBLOCK | O_CLOEXEC) < 0)
+       if (socketpair(AF_LOCAL, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC,
+                                                               0, fds) < 0)
                return btd_error_failed(msg, strerror(errno));
 
        dir = dbus_message_has_member(msg, "AcquireWrite");
 
-       io = io_new(pipefd[!dir]);
+       io = io_new(fds[!dir]);
        if (!io) {
-               close(pipefd[0]);
-               close(pipefd[1]);
+               close(fds[0]);
+               close(fds[1]);
                return btd_error_failed(msg, strerror(EIO));
        }
 
        io_set_close_on_destroy(io, true);
 
-       if (!io_set_read_handler(io, chrc_pipe_read, chrc, NULL))
+       if (!io_set_read_handler(io, sock_read, chrc, NULL))
                goto fail;
 
-       if (!io_set_disconnect_handler(io, characteristic_pipe_hup, chrc, NULL))
+       if (!io_set_disconnect_handler(io, sock_hup, chrc, NULL))
                goto fail;
 
        mtu = bt_gatt_client_get_mtu(gatt);
 
-       reply = g_dbus_create_reply(msg, DBUS_TYPE_UNIX_FD, &pipefd[dir],
+       reply = g_dbus_create_reply(msg, DBUS_TYPE_UNIX_FD, &fds[dir],
                                        DBUS_TYPE_UINT16, &mtu,
                                        DBUS_TYPE_INVALID);
 
-       close(pipefd[dir]);
+       close(fds[dir]);
 
        if (dir) {
                chrc->write_io->io = io;
@@ -1255,7 +1267,7 @@ static DBusMessage *characteristic_create_pipe(struct characteristic *chrc,
 
 fail:
        io_destroy(io);
-       close(pipefd[dir]);
+       close(fds[dir]);
        return btd_error_failed(msg, strerror(EIO));
 }
 
@@ -1267,7 +1279,7 @@ static void characteristic_ready(bool success, uint8_t ecode, void *user_data)
        chrc->ready_id = 0;
 
        if (chrc->write_io && chrc->write_io->msg) {
-               reply = characteristic_create_pipe(chrc, chrc->write_io->msg);
+               reply = create_sock(chrc, chrc->write_io->msg);
 
                g_dbus_send_message(btd_get_dbus_connection(), reply);
 
@@ -1276,7 +1288,7 @@ static void characteristic_ready(bool success, uint8_t ecode, void *user_data)
        }
 
        if (chrc->notify_io && chrc->notify_io->msg) {
-               reply = characteristic_create_pipe(chrc, chrc->notify_io->msg);
+               reply = create_sock(chrc, chrc->notify_io->msg);
 
                g_dbus_send_message(btd_get_dbus_connection(), reply);
 
@@ -1300,7 +1312,7 @@ static DBusMessage *characteristic_acquire_write(DBusConnection *conn,
        if (!(chrc->props & BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP))
                return btd_error_not_supported(msg);
 
-       chrc->write_io = new0(struct pipe_io, 1);
+       chrc->write_io = new0(struct sock_io, 1);
 
        if (!bt_gatt_client_is_ready(gatt)) {
                /* GATT not ready, wait until it becomes ready */
@@ -1312,7 +1324,7 @@ static DBusMessage *characteristic_acquire_write(DBusConnection *conn,
                return NULL;
        }
 
-       return characteristic_create_pipe(chrc, msg);
+       return create_sock(chrc, msg);
 }
 
 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
@@ -1584,21 +1596,26 @@ static void register_notify_cb(uint16_t att_ecode, void *user_data)
 static void notify_io_cb(uint16_t value_handle, const uint8_t *value,
                                        uint16_t length, void *user_data)
 {
+       struct msghdr msg;
        struct iovec iov;
        struct notify_client *client = user_data;
        struct characteristic *chrc = client->chrc;
        int err;
 
        /* Drop notification if the pipe is not ready */
-       if (!chrc->notify_io->io)
+       if (!chrc->notify_io ||  !chrc->notify_io->io)
                return;
 
        iov.iov_base = (void *) value;
        iov.iov_len = length;
 
-       err = io_send(chrc->notify_io->io, &iov, 1);
+       memset(&msg, 0, sizeof(msg));
+       msg.msg_iov = &iov;
+       msg.msg_iovlen = 1;
+
+       err = sendmsg(io_get_fd(chrc->notify_io->io), &msg, MSG_NOSIGNAL);
        if (err < 0)
-               error("io_send: %s", strerror(-err));
+               error("sendmsg: %s", strerror(errno));
 }
 
 static void register_notify_io_cb(uint16_t att_ecode, void *user_data)
@@ -1667,7 +1684,7 @@ static DBusMessage *characteristic_acquire_notify(DBusConnection *conn,
 
        queue_push_tail(chrc->notify_clients, client);
 
-       chrc->notify_io = new0(struct pipe_io, 1);
+       chrc->notify_io = new0(struct sock_io, 1);
        chrc->notify_io->data = client;
        chrc->notify_io->msg = dbus_message_ref(msg);
        chrc->notify_io->destroy = notify_io_destroy;
@@ -1754,16 +1771,17 @@ static DBusMessage *characteristic_stop_notify(DBusConnection *conn,
        const char *sender = dbus_message_get_sender(msg);
        struct notify_client *client;
 
+       if (chrc->notify_io) {
+               destroy_sock(chrc, chrc->notify_io->io);
+               return dbus_message_new_method_return(msg);
+       }
+
+
        client = queue_remove_if(chrc->notify_clients, match_notify_sender,
                                                        (void *) sender);
        if (!client)
                return btd_error_failed(msg, "No notify session started");
 
-       if (chrc->notify_io) {
-               characteristic_destroy_pipe(chrc, chrc->notify_io->io);
-               return dbus_message_new_method_return(msg);
-       }
-
        queue_remove(chrc->service->client->all_notify_clients, client);
        bt_gatt_client_unregister_notify(gatt, client->notify_id);
        update_notifying(chrc);
@@ -1879,12 +1897,12 @@ static void characteristic_free(void *data)
 
        if (chrc->write_io) {
                queue_remove(chrc->service->client->ios, chrc->write_io->io);
-               pipe_io_destroy(chrc->write_io);
+               sock_io_destroy(chrc->write_io);
        }
 
        if (chrc->notify_io) {
                queue_remove(chrc->service->client->ios, chrc->notify_io->io);
-               pipe_io_destroy(chrc->notify_io);
+               sock_io_destroy(chrc->notify_io);
        }
 
        g_free(chrc->path);
index bda6f5f..6bc6f65 100644 (file)
@@ -2333,7 +2333,7 @@ static struct pending_op *send_write(struct btd_device *device,
        return NULL;
 }
 
-static bool pipe_hup(struct io *io, void *user_data)
+static bool sock_hup(struct io *io, void *user_data)
 {
        struct external_chrc *chrc = user_data;
 
@@ -2349,7 +2349,7 @@ static bool pipe_hup(struct io *io, void *user_data)
        return false;
 }
 
-static bool pipe_io_read(struct io *io, void *user_data)
+static bool sock_io_read(struct io *io, void *user_data)
 {
        struct external_chrc *chrc = user_data;
        uint8_t buf[512];
@@ -2370,7 +2370,7 @@ static bool pipe_io_read(struct io *io, void *user_data)
        return true;
 }
 
-static struct io *pipe_io_new(int fd, void *user_data)
+static struct io *sock_io_new(int fd, void *user_data)
 {
        struct io *io;
 
@@ -2378,21 +2378,26 @@ static struct io *pipe_io_new(int fd, void *user_data)
 
        io_set_close_on_destroy(io, true);
 
-       io_set_read_handler(io, pipe_io_read, user_data, NULL);
+       io_set_read_handler(io, sock_io_read, user_data, NULL);
 
-       io_set_disconnect_handler(io, pipe_hup, user_data, NULL);
+       io_set_disconnect_handler(io, sock_hup, user_data, NULL);
 
        return io;
 }
 
-static int pipe_io_send(struct io *io, const void *data, size_t len)
+static int sock_io_send(struct io *io, const void *data, size_t len)
 {
+       struct msghdr msg;
        struct iovec iov;
 
        iov.iov_base = (void *) data;
        iov.iov_len = len;
 
-       return io_send(io, &iov, 1);
+       memset(&msg, 0, sizeof(msg));
+       msg.msg_iov = &iov;
+
+       return sendmsg(io_get_fd(io), &msg, MSG_NOSIGNAL);
+
 }
 
 static void acquire_write_reply(DBusMessage *message, void *user_data)
@@ -2421,9 +2426,9 @@ static void acquire_write_reply(DBusMessage *message, void *user_data)
 
        DBG("AcquireWrite success: fd %d MTU %u\n", fd, mtu);
 
-       chrc->write_io = pipe_io_new(fd, chrc);
+       chrc->write_io = sock_io_new(fd, chrc);
 
-       if (pipe_io_send(chrc->write_io, op->data.iov_base,
+       if (sock_io_send(chrc->write_io, op->data.iov_base,
                                op->data.iov_len) < 0)
                goto retry;
 
@@ -2509,7 +2514,7 @@ static void acquire_notify_reply(DBusMessage *message, void *user_data)
 
        DBG("AcquireNotify success: fd %d MTU %u\n", fd, mtu);
 
-       chrc->notify_io = pipe_io_new(fd, chrc);
+       chrc->notify_io = sock_io_new(fd, chrc);
 
        __sync_fetch_and_add(&chrc->ntfy_cnt, 1);
 
@@ -2954,7 +2959,7 @@ static void chrc_write_cb(struct gatt_db_attribute *attrib,
        }
 
        if (chrc->write_io) {
-               if (pipe_io_send(chrc->write_io, value, len) < 0) {
+               if (sock_io_send(chrc->write_io, value, len) < 0) {
                        error("Unable to write: %s", strerror(errno));
                        goto fail;
                }