static err_t InternalRecvEventHandler(void *arg, PTCP_PCB pcb, struct pbuf *p, const err_t err) { PCONNECTION_ENDPOINT Connection = arg; /* Make sure the socket didn't get closed */ if (!arg) { if (p) pbuf_free(p); return ERR_OK; } if (p) { LibTCPEnqueuePacket(Connection, p); tcp_recved(pcb, p->tot_len); TCPRecvEventHandler(arg); } else if (err == ERR_OK) { /* Complete pending reads with 0 bytes to indicate a graceful closure, * but note that send is still possible in this state so we don't close the * whole socket here (by calling tcp_close()) as that would violate TCP specs */ Connection->ReceiveShutdown = TRUE; Connection->ReceiveShutdownStatus = STATUS_SUCCESS; /* If we already did a send shutdown, we're in TIME_WAIT so we can't use this PCB anymore */ if (Connection->SendShutdown) { Connection->SocketContext = NULL; tcp_arg(pcb, NULL); } /* Indicate the graceful close event */ TCPRecvEventHandler(arg); /* If the PCB is gone, clean up the connection */ if (Connection->SendShutdown) { TCPFinEventHandler(Connection, ERR_CLSD); } } return ERR_OK; }
static err_t InternalRecvEventHandler(void *arg, PTCP_PCB pcb, struct pbuf *p, const err_t err) { PCONNECTION_ENDPOINT Connection = arg; /* Make sure the socket didn't get closed */ if (!arg) { if (p) pbuf_free(p); return ERR_OK; } if (p) { LibTCPEnqueuePacket(Connection, p); tcp_recved(pcb, p->tot_len); TCPRecvEventHandler(arg); } else if (err == ERR_OK) { /* Complete pending reads with 0 bytes to indicate a graceful closure, * but note that send is still possible in this state so we don't close the * whole socket here (by calling tcp_close()) as that would violate TCP specs */ Connection->ReceiveShutdown = TRUE; Connection->ReceiveShutdownStatus = STATUS_SUCCESS; /* This code path executes for both remotely and locally initiated closures, * and we need to distinguish between them */ if (Connection->SocketContext) { /* Remotely initiated close */ TCPRecvEventHandler(arg); } else { /* Locally initated close */ TCPFinEventHandler(arg, ERR_CLSD); } } return ERR_OK; }