diff --git a/src/api/sockets.c b/src/api/sockets.c index b97bdd7e..8731b9f4 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -3068,10 +3068,25 @@ lwip_getsockopt_impl(int s, int level, int optname, void *optval, socklen_t *opt #endif /* LWIP_SO_RCVTIMEO */ #if LWIP_SO_RCVBUF case SO_RCVBUF: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); - *(int *)optval = netconn_get_recvbufsize(sock->conn); +#if TCP_SO_RCVBUF + if (NETCONN_TCP == NETCONNTYPE_GROUP(netconn_type(sock->conn))) { + *(int *)optval = sock->conn->pcb.tcp->wnd_size; + } else +#endif + { + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); + *(int *)optval = netconn_get_recvbufsize(sock->conn); + } break; #endif /* LWIP_SO_RCVBUF */ + case SO_SNDBUF: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); + if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { /* only for tcp */ + done_socket(sock); + return ENOPROTOOPT; + } + *(int *)optval = TCP_SND_BUF; + break; #if LWIP_SO_LINGER case SO_LINGER: { s16_t conn_linger; @@ -3470,7 +3485,21 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_ #if LWIP_SO_RCVBUF case SO_RCVBUF: LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, optlen, int); - netconn_set_recvbufsize(sock->conn, *(const int *)optval); + +#if TCP_SO_RCVBUF + if (NETCONN_TCP == NETCONNTYPE_GROUP(netconn_type(sock->conn))) { + if (CLOSED == sock->conn->pcb.tcp->state) { + sock->conn->pcb.tcp->wnd_size = *(const int *)optval; + netconn_set_recvbufsize(sock->conn, *(const int *)optval); + } else { + done_socket(sock); + return EINVAL; + } + } else +#endif + { + netconn_set_recvbufsize(sock->conn, *(const int *)optval); + } break; #endif /* LWIP_SO_RCVBUF */ #if LWIP_SO_LINGER diff --git a/src/core/tcp.c b/src/core/tcp.c index ea95ffee..f7bd8d51 100644 --- a/src/core/tcp.c +++ b/src/core/tcp.c @@ -893,6 +893,10 @@ tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err) lpcb->netif_idx = pcb->netif_idx; lpcb->ttl = pcb->ttl; lpcb->tos = pcb->tos; +#if TCP_SO_RCVBUF + lpcb->wnd_size = pcb->wnd_size; +#endif + #if LWIP_VLAN_PCP lpcb->netif_hints.tci = pcb->netif_hints.tci; #endif /* LWIP_VLAN_PCP */ @@ -938,7 +942,7 @@ tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb) LWIP_ASSERT("tcp_update_rcv_ann_wnd: invalid pcb", pcb != NULL); new_right_edge = pcb->rcv_nxt + pcb->rcv_wnd; - if (TCP_SEQ_GEQ(new_right_edge, pcb->rcv_ann_right_edge + LWIP_MIN((TCP_WND / 2), pcb->mss))) { + if (TCP_SEQ_GEQ(new_right_edge, pcb->rcv_ann_right_edge + LWIP_MIN((TCP_WND_MAX / 2), pcb->mss))) { /* we can advertise more window */ pcb->rcv_ann_wnd = pcb->rcv_wnd; return new_right_edge - pcb->rcv_ann_right_edge; @@ -1153,7 +1157,7 @@ tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port, pcb->snd_lbb = iss - 1; /* Start with a window that does not need scaling. When window scaling is enabled and used, the window is enlarged when both sides agree on scaling. */ - pcb->rcv_wnd = pcb->rcv_ann_wnd = TCPWND_MIN16(TCP_WND); + pcb->rcv_wnd = pcb->rcv_ann_wnd = TCPWND_MIN16(TCP_WND_MAX); pcb->rcv_ann_right_edge = pcb->rcv_nxt; pcb->snd_wnd = TCP_WND; /* As initial send MSS, we use TCP_MSS but limit it to 536. @@ -1897,6 +1901,9 @@ tcp_alloc(u8_t prio) /* Start with a window that does not need scaling. When window scaling is enabled and used, the window is enlarged when both sides agree on scaling. */ pcb->rcv_wnd = pcb->rcv_ann_wnd = TCPWND_MIN16(TCP_WND); +#if TCP_SO_RCVBUF + pcb->wnd_size = TCPWND_MIN16(TCP_WND); +#endif pcb->ttl = TCP_TTL; /* As initial send MSS, we use TCP_MSS but limit it to 536. The send MSS is updated when an MSS option is received. */ diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c index 1b17e40f..2671dd88 100644 --- a/src/core/tcp_in.c +++ b/src/core/tcp_in.c @@ -693,6 +693,12 @@ tcp_listen_input(struct tcp_pcb_listen *pcb) #if LWIP_VLAN_PCP npcb->netif_hints.tci = pcb->netif_hints.tci; #endif /* LWIP_VLAN_PCP */ +#if TCP_SO_RCVBUF + npcb->wnd_size = pcb->wnd_size; + npcb->rcv_wnd = pcb->wnd_size; + npcb->rcv_ann_wnd = pcb->wnd_size; +#endif + /* inherit socket options */ npcb->so_options = pcb->so_options & SOF_INHERITED; npcb->netif_idx = pcb->netif_idx; diff --git a/src/core/tcp_out.c b/src/core/tcp_out.c index cfcc55dd..f22416d4 100644 --- a/src/core/tcp_out.c +++ b/src/core/tcp_out.c @@ -1996,7 +1996,15 @@ tcp_rst_common(const struct tcp_pcb *pcb, u32_t seqno, u32_t ackno, #if LWIP_WND_SCALE wnd = PP_HTONS(((TCP_WND >> TCP_RCV_SCALE) & 0xFFFF)); #else - wnd = PP_HTONS(TCP_WND); +#if TCP_SO_RCVBUF + /* The pcb may be NULL, use the default in this case. */ + if (NULL != pcb) { + wnd = PP_HTONS(pcb->wnd_size); + } else +#endif + { + wnd = PP_HTONS(TCP_WND); + } #endif p = tcp_output_alloc_header_common(ackno, optlen, 0, lwip_htonl(seqno), local_port, diff --git a/src/include/lwip/tcp.h b/src/include/lwip/tcp.h index 3991fd6e..cfe4fcd7 100644 --- a/src/include/lwip/tcp.h +++ b/src/include/lwip/tcp.h @@ -142,8 +142,12 @@ typedef err_t (*tcp_connected_fn)(void *arg, struct tcp_pcb *tpcb, err_t err); #define RCV_WND_SCALE(pcb, wnd) (wnd) #define SND_WND_SCALE(pcb, wnd) (wnd) #define TCPWND16(x) (x) +#if TCP_SO_RCVBUF +#define TCP_WND_MAX(pcb) (pcb->wnd_size) +#else #define TCP_WND_MAX(pcb) TCP_WND #endif +#endif /* Increments a tcpwnd_size_t and holds at max value rather than rollover */ #define TCP_WND_INC(wnd, inc) do { \ if ((tcpwnd_size_t)(wnd + inc) >= wnd) { \ @@ -216,7 +220,8 @@ typedef u16_t tcpflags_t; enum tcp_state state; /* TCP state */ \ u8_t prio; \ /* ports are in host byte order */ \ - u16_t local_port + u16_t local_port; \ + tcpwnd_size_t wnd_size /* receiver window size */ /** the TCP protocol control block for listening pcbs */