From 1ed9c137140a4896cb0aa07f48dcb7182c8271d3 Mon Sep 17 00:00:00 2001 From: SS Roop Date: Fri, 15 Feb 2019 10:57:32 +0530 Subject: [PATCH] Add utcp_abort_all_connections function. This adds a function to abort all open connections without invalidating the utcp_connection_t handles. Its main purposes is when the application knows communication with the peer is definitely not possible/desired anymore. A RST packet will be sent to each connection's remote end, and the receive callback will be invoked to indicate an error on each connection. --- utcp.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++------------ utcp.h | 2 ++ 2 files changed, 52 insertions(+), 12 deletions(-) diff --git a/utcp.c b/utcp.c index 7c4e563..7591e19 100644 --- a/utcp.c +++ b/utcp.c @@ -624,8 +624,9 @@ ssize_t utcp_send(struct utcp_connection *c, const void *data, size_t len) { // Don't send anything yet if the connection has not fully established yet - if (c->state == SYN_SENT || c->state == SYN_RECEIVED) + if(c->state == SYN_SENT || c->state == SYN_RECEIVED) { return len; + } ack(c, false); @@ -1356,12 +1357,14 @@ skip_ack: c->rcv.irs = hdr.seq; c->rcv.nxt = hdr.seq; + if(c->shut_wr) { c->snd.last++; set_state(c, FIN_WAIT_1); } else { set_state(c, ESTABLISHED); } + // TODO: notify application of this somehow. break; @@ -1550,8 +1553,9 @@ int utcp_shutdown(struct utcp_connection *c, int dir) { } // Only process shutting down writes once. - if (c->shut_wr) + if(c->shut_wr) { return 0; + } c->shut_wr = true; @@ -1594,18 +1598,29 @@ int utcp_shutdown(struct utcp_connection *c, int dir) { return 0; } -int utcp_close(struct utcp_connection *c) { - if(utcp_shutdown(c, SHUT_RDWR) && errno != ENOTCONN) { - return -1; +// Closes all the opened connections +void utcp_abort_all_connections(struct utcp *utcp) { + if(!utcp) { + return; } - c->recv = NULL; - c->poll = NULL; - c->reapable = true; - return 0; + for(int i = 0; i < utcp->nconnections; i++) { + struct utcp_connection *c = utcp->connections[i]; + + if(c->recv) { + errno = 0; + c->recv(c, NULL, 0); + } + + if(utcp_reset_connection(c) != -1) { + c->reapable = false; + } + } + + return; } -int utcp_abort(struct utcp_connection *c) { +int utcp_reset_connection(struct utcp_connection *c) { if(!c) { errno = EFAULT; return -1; @@ -1619,7 +1634,6 @@ int utcp_abort(struct utcp_connection *c) { c->recv = NULL; c->poll = NULL; - c->reapable = true; switch(c->state) { case CLOSED: @@ -1658,6 +1672,29 @@ int utcp_abort(struct utcp_connection *c) { return 0; } +int utcp_close(struct utcp_connection *c) { + if(utcp_shutdown(c, SHUT_RDWR) && errno != ENOTCONN) { + return -1; + } + + c->recv = NULL; + c->poll = NULL; + c->reapable = true; + return 0; +} + +int utcp_abort(struct utcp_connection *c) { + int utcp_reset_return; + + utcp_reset_return = utcp_reset_connection(c); + + if(utcp_reset_return != -1) { + c->reapable = true; + } + + return utcp_reset_return; +} + /* Handle timeouts. * One call to this function will loop through all connections, * checking if something needs to be resent or not. @@ -1839,8 +1876,9 @@ size_t utcp_get_sndbuf(struct utcp_connection *c) { } size_t utcp_get_sndbuf_free(struct utcp_connection *c) { - if (!c) + if(!c) { return 0; + } switch(c->state) { case SYN_SENT: diff --git a/utcp.h b/utcp.h index f8fad0c..0cad458 100644 --- a/utcp.h +++ b/utcp.h @@ -77,6 +77,8 @@ extern void utcp_set_recv_cb(struct utcp_connection *connection, utcp_recv_t rec extern void utcp_set_poll_cb(struct utcp_connection *connection, utcp_poll_t poll); extern void utcp_set_accept_cb(struct utcp *utcp, utcp_accept_t accept, utcp_pre_accept_t pre_accept); extern bool utcp_is_active(struct utcp *utcp); +extern void utcp_abort_all_connections(struct utcp *utcp); +extern int utcp_reset_connection(struct utcp_connection *c); // Global socket options -- 2.39.2