/** * Causes all or part of a full-duplex connection of this PCB to be shut down. * This doesn't deallocate the PCB! * * @param pcb PCB to shutdown * @param shut_rx shut down receive side if this is != 0 * @param shut_tx shut down send side if this is != 0 * @return ERR_OK if shutdown succeeded (or the PCB has already been shut down) * another err_t on error. */ err_t tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx) { if (pcb->state == LISTEN) { return ERR_CONN; } if (shut_rx) { /* shut down the receive side: free buffered data... */ if (pcb->refused_data != NULL) { pbuf_free(pcb->refused_data); pcb->refused_data = NULL; } /* ... and set a flag not to receive any more data */ pcb->flags |= TF_RXCLOSED; } if (shut_tx) { /* This can't happen twice since if it succeeds, the pcb's state is changed. Only close in these states as the others directly deallocate the PCB */ switch (pcb->state) { case SYN_RCVD: case ESTABLISHED: case CLOSE_WAIT: return tcp_close_shutdown(pcb, 0); default: /* don't shut down other states */ break; } } /* @todo: return another err_t if not in correct state or already shut? */ return ERR_OK; }
/** * Closes the connection held by the PCB. * * Listening pcbs are freed and may not be referenced any more. * Connection pcbs are freed if not yet connected and may not be referenced * any more. If a connection is established (at least SYN received or in * a closing state), the connection is closed, and put in a closing state. * The pcb is then automatically freed in tcp_slowtmr(). It is therefore * unsafe to reference it (unless an error is returned). * * @param pcb the tcp_pcb to close * @return ERR_OK if connection has been closed * another err_t if closing failed and pcb is not freed */ err_t tcp_close(struct tcp_pcb *pcb) { #if TCP_DEBUG LWIP_DEBUGF(TCP_DEBUG, ("tcp_close: closing in ")); tcp_debug_print_state(pcb->state); #endif /* TCP_DEBUG */ if (pcb->state != LISTEN) { /* Set a flag not to receive any more data... */ pcb->flags |= TF_RXCLOSED; } /* ... and close */ return tcp_close_shutdown(pcb, 1); }
/** * Causes all or part of a full-duplex connection of this PCB to be shut down. * This doesn't deallocate the PCB! * * @param pcb PCB to shutdown * @param shut_rx shut down receive side if this is != 0 * @param shut_tx shut down send side if this is != 0 * @return ERR_OK if shutdown succeeded (or the PCB has already been shut down) * another err_t on error. */ err_t tcp_shutdown(struct tcp_pcb *pcb, int shut_rx, int shut_tx) { if (get_tcp_state(pcb) == LISTEN) { return ERR_CONN; } if (shut_rx) { /* shut down the receive side: set a flag not to receive any more data... */ pcb->flags |= TF_RXCLOSED; if (shut_tx) { /* shutting down the tx AND rx side is the same as closing for the raw API */ return tcp_close_shutdown(pcb, 1); } /* ... and free buffered data */ if (pcb->refused_data != NULL) { pbuf_free(pcb->refused_data); pcb->refused_data = NULL; } } if (shut_tx) { /* This can't happen twice since if it succeeds, the pcb's state is changed. Only close in these states as the others directly deallocate the PCB */ switch (get_tcp_state(pcb)) { case SYN_RCVD: case ESTABLISHED: case CLOSE_WAIT: return tcp_close_shutdown(pcb, 0); default: /* Not (yet?) connected, cannot shutdown the TX side as that would bring us into CLOSED state, where the PCB is deallocated. */ return ERR_CONN; } } /* @todo: return another err_t if not in correct state or already shut? */ return ERR_OK; }