int nn_recv (int s, void *buf, size_t len, int flags) { int rc; struct nn_msg msg; size_t sz; void *chunk; NN_BASIC_CHECKS; if (nn_slow (!buf && len)) { errno = EFAULT; return -1; } rc = nn_sock_recv (self.socks [s], &msg, flags); if (nn_slow (rc < 0)) { errno = -rc; return -1; } if (len == NN_MSG) { chunk = nn_chunkref_getchunk (&msg.body); *(void**) buf = chunk; sz = nn_chunk_size (chunk); } else { sz = nn_chunkref_size (&msg.body); memcpy (buf, nn_chunkref_data (&msg.body), len < sz ? len : sz); } nn_msg_term (&msg); return (int) sz; }
int nn_recv (int s, void *buf, size_t len, int flags) { int rc; struct nn_msg msg; size_t sz; struct nn_chunk *ch; NN_BASIC_CHECKS; if (nn_slow (!buf && len)) { errno = EFAULT; return -1; } rc = nn_sock_recv (self.socks [s], &msg, flags); if (nn_slow (rc < 0)) { errno = -rc; return -1; } if (len == NN_MSG) { ch = nn_chunkref_getchunk (&msg.body); *(void**) buf = nn_chunk_data (ch); sz = nn_chunk_size (ch); } else { sz = nn_chunkref_size (&msg.body); memcpy (buf, nn_chunkref_data (&msg.body), len < sz ? len : sz); } nn_msg_term (&msg); #if defined NN_LATENCY_MONITOR nn_latmon_measure (NN_LATMON_RECV); #endif return (int) sz; }
int nn_recvmsg (int s, struct nn_msghdr *msghdr, int flags) { int rc; struct nn_msg msg; uint8_t *data; size_t sz; int i; struct nn_iovec *iov; void *chunk; NN_BASIC_CHECKS; if (nn_slow (!msghdr)) { errno = EINVAL; return -1; } if (nn_slow (msghdr->msg_iovlen < 0)) { errno = EMSGSIZE; return -1; } /* Get a message. */ rc = nn_sock_recv (self.socks [s], &msg, flags); if (nn_slow (rc < 0)) { errno = -rc; return -1; } if (msghdr->msg_iovlen == 1 && msghdr->msg_iov [0].iov_len == NN_MSG) { chunk = nn_chunkref_getchunk (&msg.body); *(void**) (msghdr->msg_iov [0].iov_base) = chunk; sz = nn_chunk_size (chunk); } else { /* Copy the message content into the supplied gather array. */ data = nn_chunkref_data (&msg.body); sz = nn_chunkref_size (&msg.body); for (i = 0; i != msghdr->msg_iovlen; ++i) { iov = &msghdr->msg_iov [i]; if (nn_slow (iov->iov_len == NN_MSG)) { nn_msg_term (&msg); errno = EINVAL; return -1; } if (iov->iov_len > sz) { memcpy (iov->iov_base, data, sz); break; } memcpy (iov->iov_base, data, iov->iov_len); data += iov->iov_len; sz -= iov->iov_len; } sz = nn_chunkref_size (&msg.body); } /* Retrieve the ancillary data from the message. */ if (msghdr->msg_control) { if (msghdr->msg_controllen == NN_MSG) { chunk = nn_chunkref_getchunk (&msg.hdr); *((void**) msghdr->msg_control) = chunk; } else { /* TODO: Copy the data to the supplied buffer, prefix them with size. */ nn_assert (0); } } nn_msg_term (&msg); return (int) sz; }
int nn_recvmsg (int s, struct nn_msghdr *msghdr, int flags) { int rc; struct nn_msg msg; uint8_t *data; size_t sz; int i; struct nn_iovec *iov; void *chunk; size_t hdrssz; void *ctrl; size_t ctrlsz; size_t spsz; size_t sptotalsz; struct nn_cmsghdr *chdr; NN_BASIC_CHECKS; if (nn_slow (!msghdr)) { errno = EINVAL; return -1; } if (nn_slow (msghdr->msg_iovlen < 0)) { errno = EMSGSIZE; return -1; } /* Get a message. */ rc = nn_sock_recv (self.socks [s], &msg, flags); if (nn_slow (rc < 0)) { errno = -rc; return -1; } if (msghdr->msg_iovlen == 1 && msghdr->msg_iov [0].iov_len == NN_MSG) { chunk = nn_chunkref_getchunk (&msg.body); *(void**) (msghdr->msg_iov [0].iov_base) = chunk; sz = nn_chunk_size (chunk); } else { /* Copy the message content into the supplied gather array. */ data = nn_chunkref_data (&msg.body); sz = nn_chunkref_size (&msg.body); for (i = 0; i != msghdr->msg_iovlen; ++i) { iov = &msghdr->msg_iov [i]; if (nn_slow (iov->iov_len == NN_MSG)) { nn_msg_term (&msg); errno = EINVAL; return -1; } if (iov->iov_len > sz) { memcpy (iov->iov_base, data, sz); break; } memcpy (iov->iov_base, data, iov->iov_len); data += iov->iov_len; sz -= iov->iov_len; } sz = nn_chunkref_size (&msg.body); } /* Retrieve the ancillary data from the message. */ if (msghdr->msg_control) { spsz = nn_chunkref_size (&msg.sphdr); sptotalsz = NN_CMSG_SPACE (spsz); ctrlsz = sptotalsz + nn_chunkref_size (&msg.hdrs); if (msghdr->msg_controllen == NN_MSG) { /* Allocate the buffer. */ rc = nn_chunk_alloc (ctrlsz, 0, &ctrl); errnum_assert (rc == 0, -rc); /* Set output parameters. */ *((void**) msghdr->msg_control) = ctrl; } else { /* Just use the buffer supplied by the user. */ ctrl = msghdr->msg_control; ctrlsz = msghdr->msg_controllen; } /* If SP header alone won't fit into the buffer, return no ancillary properties. */ if (ctrlsz >= sptotalsz) { /* Fill in SP_HDR ancillary property. */ chdr = (struct nn_cmsghdr*) ctrl; chdr->cmsg_len = sptotalsz; chdr->cmsg_level = PROTO_SP; chdr->cmsg_type = SP_HDR; memcpy (chdr + 1, nn_chunkref_data (&msg.sphdr), spsz); /* Fill in as many remaining properties as possible. Truncate the trailing properties if necessary. */ hdrssz = nn_chunkref_size (&msg.hdrs); if (hdrssz > ctrlsz - sptotalsz) hdrssz = ctrlsz - sptotalsz; memcpy (((char*) ctrl) + sptotalsz, nn_chunkref_data (&msg.hdrs), hdrssz); } } nn_msg_term (&msg); return (int) sz; }
int nn_recvmsg (int s, struct nn_msghdr *msghdr, int flags) { int rc; struct nn_msg msg; uint8_t *data; size_t sz; int i; struct nn_iovec *iov; void *chunk; size_t hdrssz; void *ctrl; size_t ctrlsz; size_t spsz; size_t sptotalsz; struct nn_cmsghdr *chdr; struct nn_sock *sock; rc = nn_global_hold_socket (&sock, s); if (nn_slow (rc < 0)) { errno = -rc; return -1; } if (nn_slow (!msghdr)) { rc = -EINVAL; goto fail; } if (nn_slow (msghdr->msg_iovlen < 0)) { rc = -EMSGSIZE; goto fail; } /* Get a message. */ rc = nn_sock_recv (sock, &msg, flags); if (nn_slow (rc < 0)) { goto fail; } if (msghdr->msg_iovlen == 1 && msghdr->msg_iov [0].iov_len == NN_MSG) { chunk = nn_chunkref_getchunk (&msg.body); *(void**) (msghdr->msg_iov [0].iov_base) = chunk; sz = nn_chunk_size (chunk); } else { /* Copy the message content into the supplied gather array. */ data = nn_chunkref_data (&msg.body); sz = nn_chunkref_size (&msg.body); for (i = 0; i != msghdr->msg_iovlen; ++i) { iov = &msghdr->msg_iov [i]; if (nn_slow (iov->iov_len == NN_MSG)) { nn_msg_term (&msg); rc = -EINVAL; goto fail; } if (iov->iov_len > sz) { memcpy (iov->iov_base, data, sz); break; } memcpy (iov->iov_base, data, iov->iov_len); data += iov->iov_len; sz -= iov->iov_len; } sz = nn_chunkref_size (&msg.body); } /* Retrieve the ancillary data from the message. */ if (msghdr->msg_control) { spsz = nn_chunkref_size (&msg.sphdr); sptotalsz = NN_CMSG_SPACE (spsz+sizeof (size_t)); ctrlsz = sptotalsz + nn_chunkref_size (&msg.hdrs); if (msghdr->msg_controllen == NN_MSG) { /* Allocate the buffer. */ rc = nn_chunk_alloc (ctrlsz, 0, &ctrl); errnum_assert (rc == 0, -rc); /* Set output parameters. */ *((void**) msghdr->msg_control) = ctrl; } else { /* Just use the buffer supplied by the user. */ ctrl = msghdr->msg_control; ctrlsz = msghdr->msg_controllen; } /* If SP header alone won't fit into the buffer, return no ancillary properties. */ if (ctrlsz >= sptotalsz) { char *ptr; /* Fill in SP_HDR ancillary property. */ chdr = (struct nn_cmsghdr*) ctrl; chdr->cmsg_len = sptotalsz; chdr->cmsg_level = PROTO_SP; chdr->cmsg_type = SP_HDR; ptr = (void *)chdr; ptr += sizeof (*chdr); *(size_t *)(void *)ptr = spsz; ptr += sizeof (size_t); memcpy (ptr, nn_chunkref_data (&msg.sphdr), spsz); /* Fill in as many remaining properties as possible. Truncate the trailing properties if necessary. */ hdrssz = nn_chunkref_size (&msg.hdrs); if (hdrssz > ctrlsz - sptotalsz) hdrssz = ctrlsz - sptotalsz; memcpy (((char*) ctrl) + sptotalsz, nn_chunkref_data (&msg.hdrs), hdrssz); } } nn_msg_term (&msg); /* Adjust the statistics. */ nn_sock_stat_increment (sock, NN_STAT_MESSAGES_RECEIVED, 1); nn_sock_stat_increment (sock, NN_STAT_BYTES_RECEIVED, sz); nn_global_rele_socket (sock); return (int) sz; fail: nn_global_rele_socket (sock); errno = -rc; return -1; }