My first try at 'recvmsg()', TCP only, for now...

This commit is contained in:
goldsimon 2017-03-09 21:49:55 +01:00
parent e9e9ec23b8
commit 2c77560870
2 changed files with 136 additions and 25 deletions

View File

@ -937,14 +937,18 @@ lwip_recv_tcp_done:
}
/* Convert a netbuf's address data to struct sockaddr */
static void
static int
lwip_sock_make_addr(struct netconn *conn, ip_addr_t *fromaddr, u16_t port,
struct sockaddr *from, socklen_t *fromlen)
{
int truncated = 0;
union sockaddr_aligned saddr;
LWIP_UNUSED_ARG(conn);
LWIP_ASSERT("from != NULL", from != NULL);
LWIP_ASSERT("fromlen != NULL", fromlen != NULL);
#if LWIP_IPV4 && LWIP_IPV6
/* Dual-stack: Map IPv4 addresses to IPv4 mapped IPv6 */
if (NETCONNTYPE_ISIPV6(netconn_type(conn)) && IP_IS_V4(fromaddr)) {
@ -953,17 +957,42 @@ lwip_sock_make_addr(struct netconn *conn, ip_addr_t *fromaddr, u16_t port,
}
#endif /* LWIP_IPV4 && LWIP_IPV6 */
LWIP_DEBUGF(SOCKETS_DEBUG, (" addr="));
IPADDR_PORT_TO_SOCKADDR(&saddr, fromaddr, port);
ip_addr_debug_print(SOCKETS_DEBUG, fromaddr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"", port));
if (from && fromlen)
{
if (*fromlen > saddr.sa.sa_len) {
*fromlen = saddr.sa.sa_len;
}
MEMCPY(from, &saddr, *fromlen);
if (*fromlen < saddr.sa.sa_len) {
truncated = 1;
} else if (*fromlen > saddr.sa.sa_len) {
*fromlen = saddr.sa.sa_len;
}
MEMCPY(from, &saddr, *fromlen);
return truncated;
}
static int
lwip_recv_tcp_from(struct lwip_sock *sock, struct sockaddr *from, socklen_t *fromlen, const char *dbg_fn, int dbg_s, int dbg_ret)
{
if (sock == NULL) {
return 0;
}
LWIP_UNUSED_ARG(dbg_fn);
LWIP_UNUSED_ARG(dbg_s);
LWIP_UNUSED_ARG(dbg_ret);
#if !SOCKETS_DEBUG
if (from && fromlen)
#endif /* !SOCKETS_DEBUG */
{
/* get remote addr/port from tcp_pcb */
u16_t port;
ip_addr_t tmpaddr;
netconn_getaddr(sock->conn, &tmpaddr, &port, 0);
LWIP_DEBUGF(SOCKETS_DEBUG, ("%s(%d): addr=", dbg_fn, dbg_s));
ip_addr_debug_print(SOCKETS_DEBUG, &tmpaddr);
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", port, dbg_ret));
if (from && fromlen) {
return lwip_sock_make_addr(sock->conn, &tmpaddr, port, from, fromlen);
}
}
return 0;
}
int
@ -980,18 +1009,7 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
}
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
ret = lwip_recv_tcp(sock, mem, len, flags);
#if !SOCKETS_DEBUG
if (from && fromlen)
#endif /* !SOCKETS_DEBUG */
{
/* get remote addr/port from tcp_pcb */
u16_t port;
ip_addr_t tmpaddr;
netconn_getaddr(sock->conn, &tmpaddr, &port, 0);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d):", s));
lwip_sock_make_addr(sock->conn, &tmpaddr, port, from, fromlen);
LWIP_DEBUGF(SOCKETS_DEBUG, (" len=%d\n", ret));
}
lwip_recv_tcp_from(sock, from, fromlen, "lwip_recvfrom", s, ret);
done_socket(sock);
return ret;
} else {
@ -1047,9 +1065,12 @@ lwip_recvfrom(int s, void *mem, size_t len, int flags,
if (from && fromlen)
#endif /* !SOCKETS_DEBUG */
{
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d):", s));
lwip_sock_make_addr(sock->conn, netbuf_fromaddr(buf), netbuf_fromport(buf), from, fromlen);
LWIP_DEBUGF(SOCKETS_DEBUG, (" len=%d\n", ret));
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s));
ip_addr_debug_print(SOCKETS_DEBUG, netbuf_fromaddr(buf));
LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", netbuf_fromport(buf), ret));
if (from && fromlen) {
lwip_sock_make_addr(sock->conn, netbuf_fromaddr(buf), netbuf_fromport(buf), from, fromlen);
}
}
/* If we don't peek the incoming message: zero lastdata pointer and free the netbuf */
@ -1076,6 +1097,88 @@ lwip_recv(int s, void *mem, size_t len, int flags)
return lwip_recvfrom(s, mem, len, flags, NULL, NULL);
}
int
lwip_recvmsg(int s, struct msghdr *message, int flags)
{
struct lwip_sock *sock;
int recv_flags = flags;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvmsg(%d, message=%p, flags=0x%x)\n", s, message, flags));
LWIP_ERROR("lwip_recvmsg: invalid message pointer", message != NULL, return ERR_ARG;);
LWIP_ERROR("lwip_recvmsg: unsupported flags", ((flags == 0) || (flags == MSG_PEEK)),
set_errno(EOPNOTSUPP); return -1;);
if ((message->msg_iovlen <= 0) || (message->msg_iovlen > IOV_MAX)) {
set_errno(EMSGSIZE);
return -1;
}
sock = get_socket(s);
if (!sock) {
return -1;
}
if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) {
#if LWIP_TCP
int i;
int ret;
/* check for valid vectors */
ret = 0;
for (i = 0; i < message->msg_iovlen; i++) {
if ((message->msg_iov[i].iov_base == NULL) || (message->msg_iov[i].iov_len == 0) ||
((int)(ret + message->msg_iov[i].iov_len) <= 0)) {
sock_set_errno(sock, ERR_VAL);
done_socket(sock);
return -1;
}
ret += message->msg_iov[i].iov_len;
}
message->msg_flags = 0;
/* recv the data */
ret = 0;
for (i = 0; i < message->msg_iovlen; i++) {
/* try to receive into this vector's buffer */
int recvd_local = lwip_recv_tcp(sock, message->msg_iov[i].iov_base, message->msg_iov[i].iov_len, recv_flags);
if (recvd_local > 0) {
/* sum up received bytes */
ret += recvd_local;
}
if ((recvd_local < 0) || (recvd_local < (int)message->msg_iov[i].iov_len)) {
/* returned prematurely */
if (ret <= 0) {
/* nothing received at all, propagate the error */
ret = recvd_local;
}
break;
}
/* while MSG_DONTWAIT is not supported for this function, we pass it to
lwip_recv_tcp() to prevent waiting for more data */
recv_flags |= MSG_DONTWAIT;
}
if (ret > 0) {
/* reset socket error since we have received something */
sock_set_errno(sock, 0);
}
if (message->msg_name && message->msg_namelen) {
if (lwip_recv_tcp_from(sock, (struct sockaddr*)message->msg_name,
&message->msg_namelen, "lwip_recvmsg", s, ret)) {
message->msg_flags |= MSG_CTRUNC;
}
}
done_socket(sock);
return ret;
#else /* LWIP_TCP */
sock_set_errno(sock, err_to_errno(ERR_ARG));
done_socket(sock);
return -1;
#endif /* LWIP_TCP */
}
/* else, UDP and RAW NETCONNs: TODO! */
sock_set_errno(sock, err_to_errno(ERR_ARG));
done_socket(sock);
return -1;
}
int
lwip_send(int s, const void *data, size_t size, int flags)
{

View File

@ -131,6 +131,10 @@ struct msghdr {
int msg_flags;
};
/* struct msghdr->msg_flags bit field values */
#define MSG_TRUNC 0x04
#define MSG_CTRUNC 0x08
/* Socket protocol types (TCP/UDP/RAW) */
#define SOCK_STREAM 1
#define SOCK_DGRAM 2
@ -433,6 +437,7 @@ void lwip_socket_thread_cleanup(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: destro
#define lwip_connect connect
#define lwip_listen listen
#define lwip_recv recv
#define lwip_recvmsg recvmsg
#define lwip_recvfrom recvfrom
#define lwip_send send
#define lwip_sendmsg sendmsg
@ -467,6 +472,7 @@ int lwip_recv(int s, void *mem, size_t len, int flags);
int lwip_read(int s, void *mem, size_t len);
int lwip_recvfrom(int s, void *mem, size_t len, int flags,
struct sockaddr *from, socklen_t *fromlen);
int lwip_recvmsg(int s, struct msghdr *message, int flags);
int lwip_send(int s, const void *dataptr, size_t size, int flags);
int lwip_sendmsg(int s, const struct msghdr *message, int flags);
int lwip_sendto(int s, const void *dataptr, size_t size, int flags,
@ -504,6 +510,8 @@ int lwip_fcntl(int s, int cmd, int val);
/** @ingroup socket */
#define recv(s,mem,len,flags) lwip_recv(s,mem,len,flags)
/** @ingroup socket */
#define recvmsg(s,message,flags) lwip_recvmsg(s,message,flags)
/** @ingroup socket */
#define recvfrom(s,mem,len,flags,from,fromlen) lwip_recvfrom(s,mem,len,flags,from,fromlen)
/** @ingroup socket */
#define send(s,dataptr,size,flags) lwip_send(s,dataptr,size,flags)