1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-27 23:41:18 +01:00

lwip_sock: provide implementation for sock_*_recv_buf()

This commit is contained in:
Martine S. Lenders 2020-03-24 17:47:50 +01:00
parent ba711c50bf
commit 77b89bb968
No known key found for this signature in database
GPG Key ID: CCD317364F63286F
2 changed files with 89 additions and 29 deletions

View File

@ -106,20 +106,15 @@ static uint16_t _ip6_addr_to_netif(const ip6_addr_p_t *_addr)
}
#endif
static int _parse_iphdr(const struct netbuf *buf, void *data, size_t max_len,
static int _parse_iphdr(struct netbuf *buf, void **data, void **ctx,
sock_ip_ep_t *remote)
{
uint8_t *data_ptr = buf->p->payload;
size_t data_len = buf->p->len;
uint8_t *data_ptr = buf->ptr->payload;
size_t data_len = buf->ptr->len;
assert(buf->p->next == NULL); /* TODO this might not be generally the case
* check later with larger payloads */
switch (data_ptr[0] >> 4) {
#if LWIP_IPV4
case 4:
if ((data_len - sizeof(struct ip_hdr)) > max_len) {
return -ENOBUFS;
}
if (remote != NULL) {
struct ip_hdr *iphdr = (struct ip_hdr *)data_ptr;
@ -134,9 +129,6 @@ static int _parse_iphdr(const struct netbuf *buf, void *data, size_t max_len,
#endif
#if LWIP_IPV6
case 6:
if ((data_len - sizeof(struct ip6_hdr)) > max_len) {
return -ENOBUFS;
}
if (remote != NULL) {
struct ip6_hdr *iphdr = (struct ip6_hdr *)data_ptr;
@ -150,24 +142,63 @@ static int _parse_iphdr(const struct netbuf *buf, void *data, size_t max_len,
break;
#endif
default:
netbuf_delete(buf);
return -EPROTO;
}
memcpy(data, data_ptr, data_len);
*data = data_ptr;
*ctx = buf;
return (ssize_t)data_len;
}
ssize_t sock_ip_recv(sock_ip_t *sock, void *data, size_t max_len,
uint32_t timeout, sock_ip_ep_t *remote)
{
void *pkt = NULL;
struct netbuf *ctx = NULL;
uint8_t *ptr = data;
ssize_t res, ret = 0;
bool nobufs = false;
assert((sock != NULL) && (data != NULL) && (max_len > 0));
while ((res = sock_ip_recv_buf(sock, &pkt, (void **)&ctx, timeout,
remote)) > 0) {
if (ctx->p->tot_len > (ssize_t)max_len) {
nobufs = true;
/* progress context to last element */
while (netbuf_next(ctx) == 0) {}
continue;
}
memcpy(ptr, pkt, res);
ptr += res;
ret += res;
}
return (nobufs) ? -ENOBUFS : ((res < 0) ? res : ret);
}
ssize_t sock_ip_recv_buf(sock_ip_t *sock, void **data, void **ctx,
uint32_t timeout, sock_ip_ep_t *remote)
{
struct netbuf *buf;
int res;
assert((sock != NULL) && (data != NULL) && (max_len > 0));
assert((sock != NULL) && (data != NULL) && (ctx != NULL));
buf = *ctx;
if (buf != NULL) {
if (netbuf_next(buf) == -1) {
*data = NULL;
netbuf_delete(buf);
*ctx = NULL;
return 0;
}
else {
*data = buf->ptr->payload;
return buf->ptr->len;
}
}
if ((res = lwip_sock_recv(sock->base.conn, timeout, &buf)) < 0) {
return res;
}
res = _parse_iphdr(buf, data, max_len, remote);
netbuf_delete(buf);
res = _parse_iphdr(buf, data, ctx, remote);
return res;
}

View File

@ -71,19 +71,52 @@ int sock_udp_get_remote(sock_udp_t *sock, sock_udp_ep_t *ep)
ssize_t sock_udp_recv(sock_udp_t *sock, void *data, size_t max_len,
uint32_t timeout, sock_udp_ep_t *remote)
{
uint8_t *data_ptr = data;
void *pkt = NULL;
void *ctx = NULL;
uint8_t *ptr = data;
ssize_t res, ret = 0;
bool nobufs = false;
assert((sock != NULL) && (data != NULL) && (max_len > 0));
while ((res = sock_udp_recv_buf(sock, &pkt, &ctx, timeout,
remote)) > 0) {
struct netbuf *buf = ctx;
if (buf->p->tot_len > (ssize_t)max_len) {
nobufs = true;
/* progress context to last element */
while (netbuf_next(ctx) == 0) {}
continue;
}
memcpy(ptr, pkt, res);
ptr += res;
ret += res;
}
return (nobufs) ? -ENOBUFS : ((res < 0) ? res : ret);
}
ssize_t sock_udp_recv_buf(sock_udp_t *sock, void **data, void **ctx,
uint32_t timeout, sock_udp_ep_t *remote)
{
struct netbuf *buf;
int res;
assert((sock != NULL) && (data != NULL) && (max_len > 0));
assert((sock != NULL) && (data != NULL) && (ctx != NULL));
buf = *ctx;
if (buf != NULL) {
if (netbuf_next(buf) == -1) {
*data = NULL;
netbuf_delete(buf);
*ctx = NULL;
return 0;
}
else {
*data = buf->ptr->payload;
return buf->ptr->len;
}
}
if ((res = lwip_sock_recv(sock->base.conn, timeout, &buf)) < 0) {
return res;
}
res = buf->p->tot_len;
if ((unsigned)res > max_len) {
netbuf_delete(buf);
return -ENOBUFS;
}
if (remote != NULL) {
/* convert remote */
size_t addr_len;
@ -113,13 +146,9 @@ ssize_t sock_udp_recv(sock_udp_t *sock, void *data, size_t max_len,
memcpy(&remote->addr, &buf->addr, addr_len);
remote->port = buf->port;
}
/* copy data */
for (struct pbuf *q = buf->p; q != NULL; q = q->next) {
memcpy(data_ptr, q->payload, q->len);
data_ptr += q->len;
}
netbuf_delete(buf);
return (ssize_t)res;
*data = buf->ptr->payload;
*ctx = buf;
return (ssize_t)buf->ptr->len;
}
ssize_t sock_udp_send(sock_udp_t *sock, const void *data, size_t len,