From ed545c8ca7b674b5e851567f2b6630ed3e4bfac0 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sun, 14 Sep 2014 17:27:24 +0200 Subject: [PATCH] Channels can now actually be opened. It still requires both sides to call channel_open(), because otherwise utcp_init() is not called on the receiving side. --- examples/channels.c | 12 ++++------ src/meshlink.c | 53 +++++++++++++++++++++++++++++++++++++-------- src/meshlink.h | 1 - 3 files changed, 48 insertions(+), 18 deletions(-) diff --git a/examples/channels.c b/examples/channels.c index 3ad2742e..b9dd8a25 100644 --- a/examples/channels.c +++ b/examples/channels.c @@ -18,8 +18,6 @@ static void log_message(meshlink_handle_t *mesh, meshlink_log_level_t level, con } static void channel_receive(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) { - const char *msg = data; - if(!len) { if(meshlink_errno) fprintf(stderr, "Error while reading data from %s: %s\n", channel->node->name, meshlink_strerror(meshlink_errno)); @@ -32,12 +30,10 @@ static void channel_receive(meshlink_handle_t *mesh, meshlink_channel_t *channel } // TODO: we now have TCP semantics, don't expect exactly one message per receive call. - if(msg[len - 1]) { - fprintf(stderr, "Received invalid data from %s\n", channel->node->name); - return; - } - printf("%s says: %s\n", channel->node->name, msg); + printf("%s says: ", channel->node->name); + fwrite(data, len, 1, stdout); + fputc('\n', stdout); } static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) { @@ -221,7 +217,7 @@ static void parse_input(meshlink_handle_t *mesh, char *buf) { destination->priv = channel; } - if(!meshlink_channel_send(mesh, channel, msg, len + 1)) { + if(!meshlink_channel_send(mesh, channel, msg, strlen(msg))) { fprintf(stderr, "Could not send message to '%s': %s\n", destination->name, meshlink_strerror(meshlink_errno)); return; } diff --git a/src/meshlink.c b/src/meshlink.c index e59170a9..9a462c27 100644 --- a/src/meshlink.c +++ b/src/meshlink.c @@ -1905,28 +1905,45 @@ meshlink_edge_t **meshlink_get_all_edges_state(meshlink_handle_t *mesh, meshlink static bool channel_pre_accept(struct utcp *utcp, uint16_t port) { //TODO: implement - return false; -} - -static void channel_accept(struct utcp_connection *utcp_connection, uint16_t port) { - //TODO: implement + return true; } -static int channel_recv(struct utcp_connection *connection, const void *data, size_t len) { +static ssize_t channel_recv(struct utcp_connection *connection, const void *data, size_t len) { meshlink_channel_t *channel = connection->priv; + if(!channel) + abort(); node_t *n = channel->node; meshlink_handle_t *mesh = n->mesh; if(!channel->receive_cb) return -1; else { channel->receive_cb(mesh, channel, data, len); - return 0; + return len; } } -static int channel_send(struct utcp *utcp, const void *data, size_t len) { +static void channel_accept(struct utcp_connection *utcp_connection, uint16_t port) { + node_t *n = utcp_connection->utcp->priv; + if(!n) + abort(); + meshlink_handle_t *mesh = n->mesh; + if(!mesh->channel_accept_cb) + return; + meshlink_channel_t *channel = xzalloc(sizeof *channel); + channel->node = n; + channel->c = utcp_connection; + if(mesh->channel_accept_cb(mesh, channel, port, NULL, 0)) + utcp_accept(utcp_connection, channel_recv, channel); + else + free(channel); +} + +static ssize_t channel_send(struct utcp *utcp, const void *data, size_t len) { node_t *n = utcp->priv; meshlink_handle_t *mesh = n->mesh; + char hex[len * 2 + 1]; + bin2hex(data, hex, len); + logger(mesh, MESHLINK_WARNING, "channel_send(%p, %p, %zu): %s\n", utcp, data, len, hex); return meshlink_send(mesh, (meshlink_node_t *)n, data, len) ? len : -1; } @@ -1938,18 +1955,36 @@ void meshlink_set_channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t channel->receive_cb = cb; } +static void channel_receive(meshlink_handle_t *mesh, meshlink_node_t *source, const void *data, size_t len) { + node_t *n = (node_t *)source; + if(!n->utcp) + abort(); + char hex[len * 2 + 1]; + bin2hex(data, hex, len); + logger(mesh, MESHLINK_WARNING, "channel_receive(%p, %p, %zu): %s\n", n->utcp, data, len, hex); + utcp_recv(n->utcp, data, len); +} + +void meshlink_channel_init(meshlink_handle_t *mesh) { +} + meshlink_channel_t *meshlink_channel_open(meshlink_handle_t *mesh, meshlink_node_t *node, uint16_t port, meshlink_channel_receive_cb_t cb, const void *data, size_t len) { + logger(mesh, MESHLINK_WARNING, "meshlink_channel_open(%p, %s, %u, %p, %p, %zu)\n", mesh, node->name, port, cb, data, len); node_t *n = (node_t *)node; if(!n->utcp) { n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n); - if(!n->utcp) + mesh->receive_cb = channel_receive; + if(!n->utcp) { + meshlink_errno = errno == ENOMEM ? MESHLINK_ENOMEM : MESHLINK_EINTERNAL; return NULL; + } } meshlink_channel_t *channel = xzalloc(sizeof *channel); channel->node = n; channel->receive_cb = cb; channel->c = utcp_connect(n->utcp, port, channel_recv, channel); if(!channel->c) { + meshlink_errno = errno == ENOMEM ? MESHLINK_ENOMEM : MESHLINK_EINTERNAL; free(channel); return NULL; } diff --git a/src/meshlink.h b/src/meshlink.h index ff0562c4..17545ed2 100644 --- a/src/meshlink.h +++ b/src/meshlink.h @@ -256,7 +256,6 @@ typedef enum { * @param level An enum describing the severity level of the message. * @param text A pointer to a nul-terminated C string containing the textual log message. * This pointer is only valid for the duration of the callback. - * H * The application must not free() this pointer. * The application should strdup() the text if it has to be available outside the callback. */ -- 2.39.2