mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-12-25 09:16:20 +00:00
My first try at 'recvmsg()', TCP only, for now...
This commit is contained in:
parent
e9e9ec23b8
commit
2c77560870
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user