diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c index 9db5724d..0a0d91a0 100644 --- a/src/core/tcp_in.c +++ b/src/core/tcp_in.c @@ -346,7 +346,13 @@ tcp_input(struct pbuf *p, struct netif *inp) } if (recv_data != NULL) { - if(flags & TCP_PSH) { + if (pcb->flags & TF_RXCLOSED) { + /* received data although already closed -> abort (send RST) to + notify the remote host that not all data has been processed */ + tcp_abort(pcb); + goto aborted; + } + if (flags & TCP_PSH) { recv_data->flags |= PBUF_FLAG_PUSH; } @@ -371,7 +377,7 @@ tcp_input(struct pbuf *p, struct netif *inp) if (pcb->rcv_wnd != TCP_WND) { pcb->rcv_wnd++; } - TCP_EVENT_RECV(pcb, NULL, ERR_OK, err); + TCP_EVENT_CLOSED(pcb, err); if (err == ERR_ABRT) { goto aborted; } @@ -391,7 +397,7 @@ tcp_input(struct pbuf *p, struct netif *inp) Below this line, 'pcb' may not be dereferenced! */ aborted: tcp_input_pcb = NULL; - + recv_data = NULL; /* give up our reference to inseg.p */ if (inseg.p != NULL) diff --git a/src/include/lwip/tcp_impl.h b/src/include/lwip/tcp_impl.h index fd1c5882..c9a989d9 100644 --- a/src/include/lwip/tcp_impl.h +++ b/src/include/lwip/tcp_impl.h @@ -199,6 +199,8 @@ PACK_STRUCT_END LWIP_EVENT_SENT, NULL, space, ERR_OK) #define TCP_EVENT_RECV(pcb,p,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ LWIP_EVENT_RECV, (p), 0, (err)) +#define TCP_EVENT_CLOSED(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ + LWIP_EVENT_RECV, NULL, 0, ERR_OK) #define TCP_EVENT_CONNECTED(pcb,err,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ LWIP_EVENT_CONNECTED, NULL, 0, (err)) #define TCP_EVENT_POLL(pcb,ret) ret = lwip_tcp_event((pcb)->callback_arg, (pcb),\ @@ -222,13 +224,22 @@ PACK_STRUCT_END else (ret) = ERR_OK; \ } while (0) -#define TCP_EVENT_RECV(pcb,p,err,ret) \ - do { \ - if(((pcb)->recv != NULL) && (!((pcb)->flags & TF_RXCLOSED))) { \ - (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err)); \ - } else { \ - (ret) = tcp_recv_null(NULL, (pcb), (p), (err)); \ - } \ +#define TCP_EVENT_RECV(pcb,p,err,ret) \ + do { \ + if((pcb)->recv != NULL) { \ + (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),(p),(err));\ + } else { \ + (ret) = tcp_recv_null(NULL, (pcb), (p), (err)); \ + } \ + } while (0) + +#define TCP_EVENT_CLOSED(pcb,ret) \ + do { \ + if(((pcb)->recv != NULL)) { \ + (ret) = (pcb)->recv((pcb)->callback_arg,(pcb),NULL,ERR_OK);\ + } else { \ + (ret) = ERR_OK; \ + } \ } while (0) #define TCP_EVENT_CONNECTED(pcb,err,ret) \