@@ -612,14 +612,18 @@ static void attach_ready_cb(void *user_data, int status, struct mesh_node *node)
{
struct l_dbus_message *reply;
struct l_dbus_message *pending_msg;
+ const char *method;
pending_msg = l_queue_remove_if(pending_queue, simple_match, user_data);
if (!pending_msg)
return;
+ method = l_dbus_message_get_member(pending_msg);
+
if (status == MESH_ERROR_NONE) {
reply = l_dbus_message_new_method_return(pending_msg);
- node_build_attach_reply(node, reply);
+ node_build_attach_reply(node, reply,
+ !strcmp(method, "AttachFD"));
} else
reply = dbus_error(pending_msg, status, "Attach failed");
@@ -635,7 +639,7 @@ static struct l_dbus_message *attach_call(struct l_dbus *dbus,
const char *app_path, *sender;
struct l_dbus_message *pending_msg;
- l_debug("Attach");
+ l_debug("%s", l_dbus_message_get_member(msg));
if (!l_dbus_message_get_arguments(msg, "ot", &app_path, &token))
return dbus_error(msg, MESH_ERROR_INVALID_ARGS, NULL);
@@ -846,6 +850,10 @@ static void setup_network_interface(struct l_dbus_interface *iface)
"oa(ya(qa{sv}))", "ot", "node",
"configuration", "app", "token");
+ l_dbus_interface_method(iface, "AttachFD", 0, attach_call,
+ "oa(ya(qa{sv}))h", "ot", "node",
+ "configuration", "fd", "app", "token");
+
l_dbus_interface_method(iface, "Leave", 0, leave_call, "", "t",
"token");
@@ -21,6 +21,8 @@
#include <config.h>
#endif
+#include <sys/types.h>
+#include <sys/socket.h>
#include <sys/time.h>
#include <ell/ell.h>
@@ -44,6 +46,33 @@
#define VIRTUAL_BASE 0x10000
+enum fd_msg_type {
+ DEV_KEY_MSG = 0,
+ APP_KEY_MSG = 1,
+};
+
+struct fd_msg {
+
+ uint8_t element;
+ uint16_t src;
+
+ enum fd_msg_type type :8;
+ union {
+ struct {
+ uint16_t net_idx;
+ uint8_t remote;
+ } dev;
+
+ struct {
+ uint16_t app_idx;
+ uint16_t dst;
+ uint8_t label[16];
+ } app;
+ };
+
+ uint8_t data[];
+} __attribute__((packed));
+
struct mesh_model {
const struct mesh_model_ops *cbs;
void *user_data;
@@ -782,7 +811,50 @@ static int add_sub(struct mesh_net *net, struct mesh_model *mod,
return MESH_STATUS_SUCCESS;
}
-static void send_dev_key_msg_rcvd(struct mesh_node *node, uint8_t ele_idx,
+static struct fd_msg *fd_msg_new(uint8_t ele_idx, uint16_t src, uint16_t size, const uint8_t *data, enum fd_msg_type type)
+{
+ size_t msg_len = sizeof(struct fd_msg) + size;
+ struct fd_msg *msg = l_malloc(msg_len);
+
+ msg->element = ele_idx;
+ msg->src = src;
+ msg->type = type;
+
+ memcpy(msg->data, data, size);
+
+ return msg;
+}
+
+static void fd_msg_send(struct l_io *io, struct fd_msg *msg, size_t size)
+{
+ struct iovec iov = {
+ .iov_base = msg,
+ .iov_len = sizeof(struct fd_msg) + size,
+ };
+ struct msghdr hdr = {
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ };
+
+ (void)sendmsg(l_io_get_fd(io), &hdr, MSG_NOSIGNAL);
+
+ l_free(msg);
+}
+
+static void send_fd_dev_key_msg_rcvd(struct l_io *io, uint8_t ele_idx,
+ uint16_t src, uint16_t app_idx,
+ uint16_t net_idx, uint16_t size,
+ const uint8_t *data)
+{
+ struct fd_msg *msg = fd_msg_new(ele_idx, src, size, data, DEV_KEY_MSG);
+
+ msg->dev.net_idx = net_idx;
+ msg->dev.remote = (app_idx != APP_IDX_DEV_LOCAL);
+
+ fd_msg_send(io, msg, size);
+}
+
+static void send_dbus_dev_key_msg_rcvd(struct mesh_node *node, uint8_t ele_idx,
uint16_t src, uint16_t app_idx,
uint16_t net_idx, uint16_t size,
const uint8_t *data)
@@ -818,7 +890,40 @@ static void send_dev_key_msg_rcvd(struct mesh_node *node, uint8_t ele_idx,
l_dbus_send(dbus, msg);
}
-static void send_msg_rcvd(struct mesh_node *node, uint8_t ele_idx,
+static void send_dev_key_msg_rcvd(struct mesh_node *node, uint8_t ele_idx,
+ uint16_t src, uint16_t app_idx,
+ uint16_t net_idx, uint16_t size,
+ const uint8_t *data)
+{
+ struct l_io *io = node_get_fd_io(node);
+
+ if (io)
+ send_fd_dev_key_msg_rcvd(io, ele_idx, src, app_idx, net_idx,
+ size, data);
+ else
+ send_dbus_dev_key_msg_rcvd(node, ele_idx, src, app_idx, net_idx,
+ size, data);
+}
+
+static void send_fd_msg_rcvd(struct l_io *io, uint8_t ele_idx,
+ uint16_t src, uint16_t dst,
+ const struct mesh_virtual *virt,
+ uint16_t app_idx,
+ uint16_t size, const uint8_t *data)
+{
+ struct fd_msg *msg = fd_msg_new(ele_idx, src, size, data, APP_KEY_MSG);
+
+ msg->app.app_idx = app_idx;
+ msg->app.dst = dst;
+
+ if (virt)
+ memcpy(msg->app.label, virt, sizeof(msg->app.label));
+
+ fd_msg_send(io, msg, size);
+}
+
+
+static void send_dbus_msg_rcvd(struct mesh_node *node, uint8_t ele_idx,
uint16_t src, uint16_t dst,
const struct mesh_virtual *virt,
uint16_t app_idx,
@@ -863,6 +968,22 @@ static void send_msg_rcvd(struct mesh_node *node, uint8_t ele_idx,
l_dbus_send(dbus, msg);
}
+static void send_msg_rcvd(struct mesh_node *node, uint8_t ele_idx,
+ uint16_t src, uint16_t dst,
+ const struct mesh_virtual *virt,
+ uint16_t app_idx,
+ uint16_t size, const uint8_t *data)
+{
+ struct l_io *io = node_get_fd_io(node);
+
+ if (io)
+ send_fd_msg_rcvd(io, ele_idx, src, dst, virt, app_idx,
+ size, data);
+ else
+ send_dbus_msg_rcvd(node, ele_idx, src, dst, virt, app_idx,
+ size, data);
+}
+
bool mesh_model_rx(struct mesh_node *node, bool szmict, uint32_t seq0,
uint32_t seq, uint32_t iv_index,
uint16_t net_idx, uint16_t src, uint16_t dst,
@@ -986,6 +1107,7 @@ bool mesh_model_rx(struct mesh_node *node, bool szmict, uint32_t seq0,
send_msg_rcvd(node, i, src, dst, decrypt_virt,
forward.app_idx, forward.size,
forward.data);
+
else if (decrypt_idx == APP_IDX_DEV_REMOTE ||
decrypt_idx == APP_IDX_DEV_LOCAL)
send_dev_key_msg_rcvd(node, i, src, decrypt_idx,
@@ -26,6 +26,8 @@
#include <limits.h>
#include <stdio.h>
#include <sys/time.h>
+#include <sys/socket.h>
+#include <unistd.h>
#include <ell/ell.h>
@@ -105,6 +107,7 @@ struct mesh_node {
uint8_t proxy;
uint8_t friend;
uint8_t beacon;
+ struct l_io *fd_io;
};
struct node_import {
@@ -260,6 +263,7 @@ static void set_defaults(struct mesh_node *node)
MESH_MODE_UNSUPPORTED;
node->ttl = TTL_MASK;
node->seq_number = DEFAULT_SEQUENCE_NUMBER;
+ node->fd_io = NULL;
}
static struct mesh_node *node_new(const uint8_t uuid[16])
@@ -341,6 +345,13 @@ static void free_node_resources(void *data)
mesh_agent_remove(node->agent);
mesh_config_release(node->cfg);
mesh_net_free(node->net);
+
+ if (node->fd_io)
+ {
+ l_io_destroy(node->fd_io);
+ node->fd_io = NULL;
+ }
+
l_free(node->storage_dir);
l_free(node);
}
@@ -745,6 +756,11 @@ uint16_t node_get_crpl(struct mesh_node *node)
return node->comp.crpl;
}
+struct l_io *node_get_fd_io(struct mesh_node *node)
+{
+ return node->fd_io;
+}
+
uint8_t node_relay_mode_get(struct mesh_node *node, uint8_t *count,
uint16_t *interval)
{
@@ -1650,6 +1666,53 @@ static void send_managed_objects_request(const char *destination,
req, l_free, DEFAULT_DBUS_TIMEOUT);
}
+static void fd_io_hup(struct l_io *io, void *user_data)
+{
+ struct mesh_node *node = user_data;
+
+ node->fd_io = NULL;
+
+ l_io_destroy(io);
+}
+
+static struct l_io *fd_io_new(struct mesh_node *node, int *fd)
+{
+ struct l_io *io;
+ int fds[2];
+
+ if (socketpair(AF_LOCAL, SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC,
+ 0, fds) < 0)
+ {
+ return NULL;
+ }
+
+ io = l_io_new(fds[0]);
+ if (!io)
+ {
+ goto fail;
+ }
+
+ l_io_set_close_on_destroy(io, true);
+
+ if (!l_io_set_disconnect_handler(io, fd_io_hup, node, NULL))
+ {
+ goto fail;
+ }
+
+ *fd = fds[1];
+
+ return io;
+
+fail:
+ if (io)
+ l_io_destroy(io);
+
+ close(fds[0]);
+ close(fds[1]);
+
+ return NULL;
+}
+
/* Establish relationship between application and mesh node */
void node_attach(const char *app_root, const char *sender, uint64_t token,
node_ready_func_t cb, void *user_data)
@@ -1770,8 +1833,16 @@ static void build_element_config(void *a, void *b)
l_dbus_message_builder_leave_struct(builder);
}
+static void append_fd(struct l_dbus_message_builder *builder, ...)
+{
+ va_list args;
+ va_start(args, builder);
+ l_dbus_message_builder_append_from_valist(builder, "h", args);
+ va_end(args);
+}
+
void node_build_attach_reply(struct mesh_node *node,
- struct l_dbus_message *reply)
+ struct l_dbus_message *reply, bool use_fd)
{
struct l_dbus_message_builder *builder;
@@ -1784,6 +1855,16 @@ void node_build_attach_reply(struct mesh_node *node,
l_dbus_message_builder_enter_array(builder, "(ya(qa{sv}))");
l_queue_foreach(node->elements, build_element_config, builder);
l_dbus_message_builder_leave_array(builder);
+
+ if (use_fd)
+ {
+ int fd = -1;
+ node->fd_io = fd_io_new(node, &fd);
+ append_fd(builder, fd);
+
+ close(fd);
+ }
+
l_dbus_message_builder_finalize(builder);
l_dbus_message_builder_destroy(builder);
}
@@ -23,6 +23,7 @@ struct mesh_io;
struct mesh_agent;
struct mesh_config;
struct mesh_config_node;
+struct l_io;
typedef void (*node_ready_func_t) (void *user_data, int status,
struct mesh_node *node);
@@ -77,13 +78,14 @@ uint8_t node_friend_mode_get(struct mesh_node *node);
const char *node_get_element_path(struct mesh_node *node, uint8_t ele_idx);
const char *node_get_owner(struct mesh_node *node);
const char *node_get_app_path(struct mesh_node *node);
+struct l_io *node_get_fd_io(struct mesh_node *node);
bool node_add_pending_local(struct mesh_node *node, void *info);
void node_attach_io_all(struct mesh_io *io);
void node_attach_io(struct mesh_node *node, struct mesh_io *io);
void node_attach(const char *app_root, const char *sender, uint64_t token,
node_ready_func_t cb, void *user_data);
void node_build_attach_reply(struct mesh_node *node,
- struct l_dbus_message *reply);
+ struct l_dbus_message *reply, bool use_fd);
void node_create(const char *app_root, const char *sender, const uint8_t *uuid,
node_ready_func_t cb, void *user_data);
void node_import(const char *app_root, const char *sender, const uint8_t *uuid,