X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=src%2Futcp.c;h=20dd0aba049757ca30833779ec772c63ba685310;hb=refs%2Fheads%2Ffeature%2Fmetaconnection-address;hp=f81150bf7ee7ec06a1aa9d0e88c2ab5751eb743a;hpb=93dfd8a6689a3f176d460bd757a466b61b29181d;p=meshlink diff --git a/src/utcp.c b/src/utcp.c index f81150bf..20dd0aba 100644 --- a/src/utcp.c +++ b/src/utcp.c @@ -17,16 +17,7 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include -#include -#include +#include "system.h" #include #include "utcp_priv.h" @@ -423,7 +414,6 @@ static int compare(const void *va, const void *vb) { const struct utcp_connection *b = *(struct utcp_connection **)vb; assert(a && b); - assert(a->src && b->src); int c = (int)a->src - (int)b->src; @@ -660,6 +650,7 @@ void utcp_accept(struct utcp_connection *c, utcp_recv_t recv, void *priv) { debug(c, "accepted %p %p\n", c, recv, priv); c->recv = recv; c->priv = priv; + c->do_poll = true; set_state(c, ESTABLISHED); } @@ -1302,7 +1293,7 @@ ssize_t utcp_recv(struct utcp *utcp, const void *data, size_t len) { if(hdr.ctl & SYN && !(hdr.ctl & ACK) && utcp->accept) { // If we don't want to accept it, send a RST back - if((utcp->pre_accept && !utcp->pre_accept(utcp, hdr.dst))) { + if((utcp->listen && !utcp->listen(utcp, hdr.dst))) { len = 1; goto reset; } @@ -1377,7 +1368,7 @@ synack: if(c->state == CLOSED) { debug(c, "got packet for closed connection\n"); - return 0; + goto reset; } // It is for an existing connection. @@ -1465,17 +1456,6 @@ synack: } } - if(hdr.ctl & ACK && (seqdiff(hdr.ack, c->snd.last) > 0 || seqdiff(hdr.ack, c->snd.una) < 0)) { - debug(c, "packet ack seqno out of range, %u <= %u < %u\n", c->snd.una, hdr.ack, c->snd.una + c->sndbuf.used); - - // Ignore unacceptable RST packets. - if(hdr.ctl & RST) { - return 0; - } - - goto reset; - } - // 2. Handle RST packets if(hdr.ctl & RST) { @@ -1565,6 +1545,11 @@ synack: // 3. Advance snd.una + if(seqdiff(hdr.ack, c->snd.last) > 0 || seqdiff(hdr.ack, c->snd.una) < 0) { + debug(c, "packet ack seqno out of range, %u <= %u < %u\n", c->snd.una, hdr.ack, c->snd.una + c->sndbuf.used); + goto reset; + } + advanced = seqdiff(hdr.ack, c->snd.una); if(advanced) { @@ -1728,6 +1713,7 @@ skip_ack: c->snd.last++; set_state(c, FIN_WAIT_1); } else { + c->do_poll = true; set_state(c, ESTABLISHED); } @@ -1786,8 +1772,15 @@ skip_ack: return 0; case ESTABLISHED: + break; + case FIN_WAIT_1: case FIN_WAIT_2: + if(c->reapable) { + // We already closed the connection and are not interested in more data. + goto reset; + } + break; case CLOSE_WAIT: @@ -2009,7 +2002,7 @@ static bool reset_connection(struct utcp_connection *c) { hdr.src = c->src; hdr.dst = c->dst; hdr.seq = c->snd.nxt; - hdr.ack = 0; + hdr.ack = c->rcv.nxt; hdr.wnd = 0; hdr.ctl = RST; @@ -2052,11 +2045,6 @@ void utcp_abort_all_connections(struct utcp *utcp) { } int utcp_close(struct utcp_connection *c) { - if(c->rcvbuf.used) { - fprintf(stderr, "UTCP channel closed with stuff in receive buffer\n"); - return reset_connection(c) ? 0 : -1; - } - if(utcp_shutdown(c, SHUT_RDWR) && errno != ENOTCONN) { return -1; } @@ -2167,7 +2155,7 @@ bool utcp_is_active(struct utcp *utcp) { return false; } -struct utcp *utcp_init(utcp_accept_t accept, utcp_pre_accept_t pre_accept, utcp_send_t send, void *priv) { +struct utcp *utcp_init(utcp_accept_t accept, utcp_listen_t listen, utcp_send_t send, void *priv) { if(!send) { errno = EFAULT; return NULL; @@ -2193,7 +2181,7 @@ struct utcp *utcp_init(utcp_accept_t accept, utcp_pre_accept_t pre_accept, utcp_ } utcp->accept = accept; - utcp->pre_accept = pre_accept; + utcp->listen = listen; utcp->send = send; utcp->priv = priv; utcp->timeout = DEFAULT_USER_TIMEOUT; // sec @@ -2410,10 +2398,10 @@ void utcp_set_poll_cb(struct utcp_connection *c, utcp_poll_t poll) { } } -void utcp_set_accept_cb(struct utcp *utcp, utcp_accept_t accept, utcp_pre_accept_t pre_accept) { +void utcp_set_accept_cb(struct utcp *utcp, utcp_accept_t accept, utcp_listen_t listen) { if(utcp) { utcp->accept = accept; - utcp->pre_accept = pre_accept; + utcp->listen = listen; } }