if(n->status.destroyed) {
meshlink_channel_close(mesh, channel);
- } else if(channel->receive_cb) {
- channel->receive_cb(mesh, channel, data, len);
+ return len;
+ }
+
+ const char *p = data;
+ size_t left = len;
+
+ while(channel->aio_receive) {
+ meshlink_aio_buffer_t *aio = channel->aio_receive;
+ size_t todo = aio->len - aio->done;
+
+ if(todo > left) {
+ todo = left;
+ }
+
+ memcpy((char *)aio->data + aio->done, p, todo);
+ aio->done += todo;
+
+ if(aio->done == aio->len) {
+ channel->aio_receive = aio->next;
+
+ if(aio->cb) {
+ aio->cb(mesh, channel, aio->data, aio->len, aio->priv);
+ }
+
+ free(aio);
+ }
+
+ p += todo;
+ left -= todo;
+
+ if(!left && len) {
+ return len;
+ }
+ }
+
+ if(channel->receive_cb) {
+ channel->receive_cb(mesh, channel, p, left);
}
return len;
node_t *n = channel->node;
meshlink_handle_t *mesh = n->mesh;
- meshlink_aio_buffer_t *aio = channel->aio;
+ meshlink_aio_buffer_t *aio = channel->aio_send;
if(aio) {
/* We at least one AIO buffer. Send as much as possible form the first buffer. */
/* If the buffer is now completely sent, call the callback and dispose of it. */
if(aio->done >= aio->len) {
- channel->aio = aio->next;
+ channel->aio_send = aio->next;
if(aio->cb) {
aio->cb(mesh, channel, aio->data, aio->len, aio->priv);
void meshlink_set_channel_poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, meshlink_channel_poll_cb_t cb) {
(void)mesh;
channel->poll_cb = cb;
- utcp_set_poll_cb(channel->c, (cb || channel->aio) ? channel_poll : NULL);
+ utcp_set_poll_cb(channel->c, (cb || channel->aio_send) ? channel_poll : NULL);
}
void meshlink_set_channel_accept_cb(meshlink_handle_t *mesh, meshlink_channel_accept_cb_t cb) {
utcp_close(channel->c);
/* Clean up any outstanding AIO buffers. */
- for(meshlink_aio_buffer_t *aio = channel->aio, *next; aio; aio = next) {
+ for(meshlink_aio_buffer_t *aio = channel->aio_send, *next; aio; aio = next) {
+ next = aio->next;
+
+ if(aio->cb) {
+ aio->cb(mesh, channel, aio->data, aio->len, aio->priv);
+ }
+
+ free(aio);
+ }
+
+ for(meshlink_aio_buffer_t *aio = channel->aio_receive, *next; aio; aio = next) {
next = aio->next;
if(aio->cb) {
pthread_mutex_lock(&mesh->mesh_mutex);
/* Disallow direct calls to utcp_send() while we still have AIO active. */
- if(channel->aio) {
+ if(channel->aio_send) {
retval = 0;
} else {
retval = utcp_send(channel->c, data, len);
pthread_mutex_lock(&mesh->mesh_mutex);
/* Append the AIO buffer descriptor to the end of the chain */
- meshlink_aio_buffer_t **p = &channel->aio;
+ meshlink_aio_buffer_t **p = &channel->aio_send;
while(*p) {
p = &(*p)->next;
return true;
}
+bool meshlink_channel_aio_receive(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len, meshlink_aio_cb_t cb, void *priv) {
+ if(!mesh || !channel) {
+ meshlink_errno = MESHLINK_EINVAL;
+ return false;
+ }
+
+ if(!len || !data) {
+ meshlink_errno = MESHLINK_EINVAL;
+ return false;
+ }
+
+ meshlink_aio_buffer_t *aio = xzalloc(sizeof(*aio));
+ aio->data = data;
+ aio->len = len;
+ aio->cb = cb;
+ aio->priv = priv;
+
+ pthread_mutex_lock(&mesh->mesh_mutex);
+
+ /* Append the AIO buffer descriptor to the end of the chain */
+ meshlink_aio_buffer_t **p = &channel->aio_receive;
+
+ while(*p) {
+ p = &(*p)->next;
+ }
+
+ *p = aio;
+
+ pthread_mutex_unlock(&mesh->mesh_mutex);
+
+ return true;
+}
+
uint32_t meshlink_channel_get_flags(meshlink_handle_t *mesh, meshlink_channel_t *channel) {
if(!mesh || !channel) {
meshlink_errno = MESHLINK_EINVAL;