Skip to content
Permalink
Browse files

net: sockets: Add sendmsg() API

Add BSD socket sendmsg() API that can be used to send data to peer
and also pass ancillary data to lower level of the network stack.

Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
  • Loading branch information...
jukkar committed Jun 27, 2019
1 parent 390a6cf commit ec2e2f43d8a4c5df9e94c82c70613a681fb4fd32
Showing with 62 additions and 0 deletions.
  1. +21 −0 include/net/socket.h
  2. +40 −0 subsys/net/lib/sockets/sockets.c
  3. +1 −0 subsys/net/lib/sockets/sockets_internal.h
@@ -270,6 +270,21 @@ static inline ssize_t zsock_send(int sock, const void *buf, size_t len,
return zsock_sendto(sock, buf, len, flags, NULL, 0);
}

/**
* @brief Send data to an arbitrary network address
*
* @details
* @rst
* See `POSIX.1-2017 article
* <http://pubs.opengroup.org/onlinepubs/9699919799/functions/sendmsg.html>`__
* for normative description.
* This function is also exposed as ``sendmsg()``
* if :option:`CONFIG_NET_SOCKETS_POSIX_NAMES` is defined.
* @endrst
*/
__syscall ssize_t zsock_sendmsg(int sock, const struct msghdr *msg,
int flags);

/**
* @brief Receive data from an arbitrary network address
*
@@ -597,6 +612,12 @@ static inline ssize_t sendto(int sock, const void *buf, size_t len, int flags,
return zsock_sendto(sock, buf, len, flags, dest_addr, addrlen);
}

static inline ssize_t sendmsg(int sock, const struct msghdr *message,
int flags)
{
return zsock_sendmsg(sock, message, flags);
}

static inline ssize_t recvfrom(int sock, void *buf, size_t max_len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen)
{
@@ -509,6 +509,39 @@ Z_SYSCALL_HANDLER(zsock_sendto, sock, buf, len, flags, dest_addr, addrlen)
}
#endif /* CONFIG_USERSPACE */

ssize_t zsock_sendmsg_ctx(struct net_context *ctx, const struct msghdr *msg,
int flags)
{
s32_t timeout = K_FOREVER;
int status;

if ((flags & ZSOCK_MSG_DONTWAIT) || sock_is_nonblock(ctx)) {
timeout = K_NO_WAIT;
}

status = net_context_sendmsg(ctx, msg, flags, NULL, timeout, NULL);
if (status < 0) {
errno = -status;
return -1;
}

return status;
}

ssize_t z_impl_zsock_sendmsg(int sock, const struct msghdr *msg, int flags)
{
VTABLE_CALL(sendmsg, sock, msg, flags);
}

#ifdef CONFIG_USERSPACE
Z_SYSCALL_HANDLER(zsock_sendmsg, sock, msg, flags)
{
/* TODO: Create a copy of msg_buf and copy the data there */

return z_impl_zsock_sendmsg(sock, (const struct msghdr *)msg, flags);
}
#endif /* CONFIG_USERSPACE */

static int sock_get_pkt_src_addr(struct net_pkt *pkt,
enum net_ip_protocol proto,
struct sockaddr *addr,
@@ -1424,6 +1457,12 @@ static ssize_t sock_sendto_vmeth(void *obj, const void *buf, size_t len,
return zsock_sendto_ctx(obj, buf, len, flags, dest_addr, addrlen);
}

static ssize_t sock_sendmsg_vmeth(void *obj, const struct msghdr *msg,
int flags)
{
return zsock_sendmsg_ctx(obj, msg, flags);
}

static ssize_t sock_recvfrom_vmeth(void *obj, void *buf, size_t max_len,
int flags, struct sockaddr *src_addr,
socklen_t *addrlen)
@@ -1456,6 +1495,7 @@ const struct socket_op_vtable sock_fd_op_vtable = {
.listen = sock_listen_vmeth,
.accept = sock_accept_vmeth,
.sendto = sock_sendto_vmeth,
.sendmsg = sock_sendmsg_vmeth,
.recvfrom = sock_recvfrom_vmeth,
.getsockopt = sock_getsockopt_vmeth,
.setsockopt = sock_setsockopt_vmeth,
@@ -45,6 +45,7 @@ struct socket_op_vtable {
void *optval, socklen_t *optlen);
int (*setsockopt)(void *obj, int level, int optname,
const void *optval, socklen_t optlen);
ssize_t (*sendmsg)(void *obj, const struct msghdr *msg, int flags);
};

#endif /* _SOCKETS_INTERNAL_H_ */

0 comments on commit ec2e2f4

Please sign in to comment.
You can’t perform that action at this time.