static void LibTCPCloseCallback(void *arg) { struct lwip_callback_msg *msg = arg; PTCP_PCB pcb = msg->Input.Close.Connection->SocketContext; /* Empty the queue even if we're already "closed" */ LibTCPEmptyQueue(msg->Input.Close.Connection); /* Check if we've already been closed */ if (msg->Input.Close.Connection->Closing) { msg->Output.Close.Error = ERR_OK; goto done; } /* Enter "closing" mode if we're doing a normal close */ if (msg->Input.Close.Callback) msg->Input.Close.Connection->Closing = TRUE; /* Check if the PCB was already "closed" but the client doesn't know it yet */ if (!msg->Input.Close.Connection->SocketContext) { msg->Output.Close.Error = ERR_OK; goto done; } /* Clear the PCB pointer and stop callbacks */ msg->Input.Close.Connection->SocketContext = NULL; tcp_arg(pcb, NULL); /* This may generate additional callbacks but we don't care, * because they're too inconsistent to rely on */ msg->Output.Close.Error = tcp_close(pcb); if (msg->Output.Close.Error) { /* Restore the PCB pointer */ msg->Input.Close.Connection->SocketContext = pcb; msg->Input.Close.Connection->Closing = FALSE; } else if (msg->Input.Close.Callback) { TCPFinEventHandler(msg->Input.Close.Connection, ERR_CLSD); } done: KeSetEvent(&msg->Event, IO_NO_INCREMENT, FALSE); }
static void LibTCPCloseCallback(void *arg) { struct lwip_callback_msg *msg = arg; PTCP_PCB pcb = msg->Input.Close.Connection->SocketContext; /* Empty the queue even if we're already "closed" */ LibTCPEmptyQueue(msg->Input.Close.Connection); if (!msg->Input.Close.Connection->SocketContext) { msg->Output.Close.Error = ERR_OK; goto done; } /* Clear the PCB pointer */ msg->Input.Close.Connection->SocketContext = NULL; switch (pcb->state) { case CLOSED: case LISTEN: case SYN_SENT: msg->Output.Close.Error = tcp_close(pcb); if (!msg->Output.Close.Error && msg->Input.Close.Callback) TCPFinEventHandler(msg->Input.Close.Connection, ERR_CLSD); break; default: /* Abort the socket */ tcp_abort(pcb); msg->Output.Close.Error = ERR_OK; break; } if (msg->Output.Close.Error) { /* Restore the PCB pointer */ msg->Input.Close.Connection->SocketContext = pcb; } done: KeSetEvent(&msg->Event, IO_NO_INCREMENT, FALSE); }