diff --git a/src/api/sockets.c b/src/api/sockets.c index 11a1a2df..765a0dad 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -387,15 +387,18 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags, { struct lwip_socket *sock; struct netbuf *buf; - u16_t buflen, copylen; + u16_t buflen, copylen, off = 0; struct ip_addr *addr; u16_t port; + u8_t done = 0; LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %d, 0x%x, ..)\n", s, mem, len, flags)); sock = get_socket(s); if (!sock) return -1; + while ( !done ) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: top while sock->lastdata=%p\n", sock->lastdata)); /* Check if there is data left from the last recv operation. */ if (sock->lastdata) { buf = sock->lastdata; @@ -410,6 +413,7 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags, /* No data was left from the previous operation, so we try to get some from the network. */ sock->lastdata = buf = netconn_recv(sock->conn); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: netconn_recv netbuf=%p\n", buf)); if (!buf) { /* We should really do some error checking here. */ @@ -420,6 +424,7 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags, } buflen = netbuf_len(buf); + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: buflen=%d len=%d off=%d sock->lastoffset=%d\n", buflen, len, off, sock->lastoffset)); buflen -= sock->lastoffset; @@ -431,7 +436,36 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags, /* copy the contents of the received buffer into the supplied memory pointer mem */ - netbuf_copy_partial(buf, mem, copylen, sock->lastoffset); + netbuf_copy_partial(buf, (u8_t*)mem + off, copylen - off, sock->lastoffset); + + off += copylen; + + if (netconn_type(sock->conn) == NETCONN_TCP) { + len -= copylen; + if ( (len <= 0) || (buf->p->flgs & PBUF_FLAG_PUSH) ) + done = 1; + } + else + done = 1; + + /* If we don't peek the incoming message... */ + if ((flags & MSG_PEEK)==0) { + /* If this is a TCP socket, check if there is data left in the + buffer. If so, it should be saved in the sock structure for next + time around. */ + if ((sock->conn->type == NETCONN_TCP) && (buflen - copylen > 0)) { + sock->lastdata = buf; + sock->lastoffset += copylen; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: lastdata now netbuf=%p\n", buf)); + } else { + sock->lastdata = NULL; + sock->lastoffset = 0; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom: deleting netbuf=%p\n", buf)); + netbuf_delete(buf); + } + } else + done = 1; + } /* while ( !done ) */ /* Check to see from where the data was.*/ if (from && fromlen) { @@ -453,7 +487,7 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags, LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s)); ip_addr_debug_print(SOCKETS_DEBUG, addr); - LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen)); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, off)); } else { #if SOCKETS_DEBUG addr = netbuf_fromaddr(buf); @@ -461,27 +495,12 @@ lwip_recvfrom(int s, void *mem, int len, unsigned int flags, LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d): addr=", s)); ip_addr_debug_print(SOCKETS_DEBUG, addr); - LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, copylen)); + LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%u len=%u\n", port, off)); #endif } - /* If we don't peek the incoming message... */ - if ((flags & MSG_PEEK)==0) { - /* If this is a TCP socket, check if there is data left in the - buffer. If so, it should be saved in the sock structure for next - time around. */ - if ((sock->conn->type == NETCONN_TCP) && (buflen - copylen > 0)) { - sock->lastdata = buf; - sock->lastoffset += copylen; - } else { - sock->lastdata = NULL; - sock->lastoffset = 0; - netbuf_delete(buf); - } - } - sock_set_errno(sock, 0); - return copylen; + return off; } int diff --git a/src/core/pbuf.c b/src/core/pbuf.c index 6dc63228..20929c0d 100644 --- a/src/core/pbuf.c +++ b/src/core/pbuf.c @@ -146,7 +146,8 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag) if (p == NULL) { return NULL; } - p->flags = PBUF_FLAG_POOL; + p->type = PBUF_TYPE_POOL; + p->flgs = 0; p->next = NULL; /* make the payload pointer point 'offset' bytes into pbuf data memory */ @@ -179,7 +180,8 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag) /* bail out unsuccesfully */ return NULL; } - q->flags = PBUF_FLAG_POOL; + q->type = PBUF_TYPE_POOL; + q->flgs = 0; q->next = NULL; /* make previous pbuf point to this pbuf */ r->next = q; @@ -214,7 +216,8 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag) p->payload = LWIP_MEM_ALIGN((void *)((u8_t *)p + SIZEOF_STRUCT_PBUF + offset)); p->len = p->tot_len = length; p->next = NULL; - p->flags = PBUF_FLAG_RAM; + p->type = PBUF_TYPE_RAM; + p->flgs = 0; LWIP_ASSERT("pbuf_alloc: pbuf->payload properly aligned", ((mem_ptr_t)p->payload % MEM_ALIGNMENT) == 0); @@ -234,7 +237,8 @@ pbuf_alloc(pbuf_layer l, u16_t length, pbuf_flag flag) p->payload = NULL; p->len = p->tot_len = length; p->next = NULL; - p->flags = ((flag == PBUF_ROM) ? PBUF_FLAG_ROM : PBUF_FLAG_REF); + p->type = ((flag == PBUF_ROM) ? PBUF_TYPE_ROM : PBUF_TYPE_REF); + p->flgs = 0; break; default: LWIP_ASSERT("pbuf_alloc: erroneous flag", 0); @@ -269,10 +273,10 @@ pbuf_realloc(struct pbuf *p, u16_t new_len) u16_t rem_len; /* remaining length */ s32_t grow; - LWIP_ASSERT("pbuf_realloc: sane p->flags", p->flags == PBUF_FLAG_POOL || - p->flags == PBUF_FLAG_ROM || - p->flags == PBUF_FLAG_RAM || - p->flags == PBUF_FLAG_REF); + LWIP_ASSERT("pbuf_realloc: sane p->type", p->type == PBUF_TYPE_POOL || + p->type == PBUF_TYPE_ROM || + p->type == PBUF_TYPE_RAM || + p->type == PBUF_TYPE_REF); /* desired length larger than current length? */ if (new_len >= p->tot_len) { @@ -302,7 +306,7 @@ pbuf_realloc(struct pbuf *p, u16_t new_len) /* shrink allocated memory for PBUF_RAM */ /* (other types merely adjust their length fields */ - if ((q->flags == PBUF_FLAG_RAM) && (rem_len != q->len)) { + if ((q->type == PBUF_TYPE_RAM) && (rem_len != q->len)) { /* reallocate and adjust the length of the pbuf that will be split */ mem_realloc(q, (u8_t *)q->payload - (u8_t *)q + rem_len); } @@ -343,7 +347,7 @@ pbuf_realloc(struct pbuf *p, u16_t new_len) u8_t pbuf_header(struct pbuf *p, s16_t header_size_increment) { - u16_t flags; + u16_t type; void *payload; u16_t increment_magnitude; @@ -361,20 +365,20 @@ pbuf_header(struct pbuf *p, s16_t header_size_increment) /* Can't assert these as some callers speculatively call pbuf_header() to see if it's OK. Will return 1 below instead. */ /* Check that we've got the correct type of pbuf to work with */ - LWIP_ASSERT("p->flags == PBUF_FLAG_RAM || p->flags == PBUF_FLAG_POOL", - p->flags == PBUF_FLAG_RAM || p->flags == PBUF_FLAG_POOL); + LWIP_ASSERT("p->type == PBUF_TYPE_RAM || p->type == PBUF_TYPE_POOL", + p->type == PBUF_TYPE_RAM || p->type == PBUF_TYPE_POOL); /* Check that we aren't going to move off the beginning of the pbuf */ LWIP_ASSERT("p->payload - increment_magnitude >= p + SIZEOF_STRUCT_PBUF", (u8_t *)p->payload - increment_magnitude >= (u8_t *)p + SIZEOF_STRUCT_PBUF); #endif } - flags = p->flags; + type = p->type; /* remember current payload pointer */ payload = p->payload; /* pbuf types containing payloads? */ - if (flags == PBUF_FLAG_RAM || flags == PBUF_FLAG_POOL) { + if (type == PBUF_TYPE_RAM || type == PBUF_TYPE_POOL) { /* set new payload pointer */ p->payload = (u8_t *)p->payload - header_size_increment; /* boundary check fails? */ @@ -388,7 +392,7 @@ pbuf_header(struct pbuf *p, s16_t header_size_increment) return 1; } /* pbuf types refering to external payloads? */ - } else if (flags == PBUF_FLAG_REF || flags == PBUF_FLAG_ROM) { + } else if (type == PBUF_TYPE_REF || type == PBUF_TYPE_ROM) { /* hide a header in the payload? */ if ((header_size_increment < 0) && (increment_magnitude <= p->len)) { /* increase payload pointer */ @@ -450,7 +454,7 @@ pbuf_header(struct pbuf *p, s16_t header_size_increment) u8_t pbuf_free(struct pbuf *p) { - u16_t flags; + u16_t type; struct pbuf *q; u8_t count; @@ -464,9 +468,9 @@ pbuf_free(struct pbuf *p) PERF_START; - LWIP_ASSERT("pbuf_free: sane flags", - p->flags == PBUF_FLAG_RAM || p->flags == PBUF_FLAG_ROM || - p->flags == PBUF_FLAG_REF || p->flags == PBUF_FLAG_POOL); + LWIP_ASSERT("pbuf_free: sane type", + p->type == PBUF_TYPE_RAM || p->type == PBUF_TYPE_ROM || + p->type == PBUF_TYPE_REF || p->type == PBUF_TYPE_POOL); count = 0; /* de-allocate all consecutive pbufs from the head of the chain that @@ -488,14 +492,14 @@ pbuf_free(struct pbuf *p) /* remember next pbuf in chain for next iteration */ q = p->next; LWIP_DEBUGF( PBUF_DEBUG | 2, ("pbuf_free: deallocating %p\n", (void *)p)); - flags = p->flags; + type = p->type; /* is this a pbuf from the pool? */ - if (flags == PBUF_FLAG_POOL) { + if (type == PBUF_TYPE_POOL) { memp_free(MEMP_PBUF_POOL, p); /* is this a ROM or RAM referencing pbuf? */ - } else if (flags == PBUF_FLAG_ROM || flags == PBUF_FLAG_REF) { + } else if (type == PBUF_TYPE_ROM || type == PBUF_TYPE_REF) { memp_free(MEMP_PBUF, p); - /* flags == PBUF_FLAG_RAM */ + /* type == PBUF_TYPE_RAM */ } else { mem_free(p); } diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c index 64e83d79..9aae63ba 100644 --- a/src/core/tcp_in.c +++ b/src/core/tcp_in.c @@ -301,6 +301,8 @@ tcp_input(struct pbuf *p, struct netif *inp) } if (recv_data != NULL) { + if(flags & TCP_PSH) + recv_data->flgs |= PBUF_FLAG_PUSH; /* Notify application that data has been received. */ TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err); } diff --git a/src/include/lwip/pbuf.h b/src/include/lwip/pbuf.h index 0cd76a1e..8b6ee742 100644 --- a/src/include/lwip/pbuf.h +++ b/src/include/lwip/pbuf.h @@ -59,11 +59,13 @@ typedef enum { /* Definitions for the pbuf flag field. These are NOT the flags that * are passed to pbuf_alloc(). */ -#define PBUF_FLAG_RAM 0x00U /* Flags that pbuf data is stored in RAM */ -#define PBUF_FLAG_ROM 0x01U /* Flags that pbuf data is stored in ROM */ -#define PBUF_FLAG_POOL 0x02U /* Flags that the pbuf comes from the pbuf pool */ -#define PBUF_FLAG_REF 0x04U /* Flags thet the pbuf payload refers to RAM */ +#define PBUF_TYPE_RAM 0x00U /* pbuf data is stored in RAM */ +#define PBUF_TYPE_ROM 0x01U /* pbuf data is stored in ROM */ +#define PBUF_TYPE_POOL 0x02U /* pbuf comes from the pbuf pool */ +#define PBUF_TYPE_REF 0x04U /* pbuf payload refers to RAM */ +/** indicates this packet's data should be immediately passed to the application */ +#define PBUF_FLAG_PUSH 0x40U /** indicates this packet was broadcast on the link */ #define PBUF_FLAG_LINK_BROADCAST 0x80U @@ -86,8 +88,11 @@ struct pbuf { /** length of this buffer */ u16_t len; - /** flags telling the type of pbuf, see PBUF_FLAG_ */ - u16_t flags; + /** type of pbuf, see PBUF_TYPE_ */ + u8_t type; + + /** misc flags */ + u8_t flgs; /** * the reference count always equals the number of pointers diff --git a/src/netif/etharp.c b/src/netif/etharp.c index 52b2931e..7b32ddf0 100644 --- a/src/netif/etharp.c +++ b/src/netif/etharp.c @@ -936,7 +936,7 @@ etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q) p = q; while (p) { LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0)); - if(p->flags != PBUF_FLAG_ROM) { + if(p->type != PBUF_TYPE_ROM) { copy_needed = 1; break; }