]> git.meshlink.io Git - meshlink/blobdiff - src/utcp.c
Never automatically try to bind to ports >= 32768.
[meshlink] / src / utcp.c
index c21e7067b89610c17182eae3dce57b58a9dfa274..ca91bee26ef6d21c0f0f57dd743c27c0f9b14f8b 100644 (file)
@@ -470,8 +470,13 @@ static void set_buffer_storage(struct buffer *buf, char *data, size_t size) {
 
                buf->external = false;
        } else {
+               // Don't do anything if the buffer wraps
+               if(buffer_wraps(buf)) {
+                       return;
+               }
+
                // Realloc internal storage
-               size_t minsize = buf->used <= DEFAULT_SNDBUFSIZE ? DEFAULT_SNDBUFSIZE : buf->used;
+               size_t minsize = max(DEFAULT_SNDBUFSIZE, buf->offset + buf->used);
 
                if(minsize) {
                        data = realloc(buf->data, minsize);
@@ -1595,6 +1600,8 @@ synack:
                        // The peer has aborted our connection.
                        set_state(c, CLOSED);
                        errno = ECONNRESET;
+                       buffer_clear(&c->sndbuf);
+                       buffer_clear(&c->rcvbuf);
 
                        if(c->recv) {
                                c->recv(c, NULL, 0);
@@ -2067,8 +2074,8 @@ static bool reset_connection(struct utcp_connection *c) {
                return false;
        }
 
-       c->recv = NULL;
-       c->poll = NULL;
+       buffer_clear(&c->sndbuf);
+       buffer_clear(&c->rcvbuf);
 
        switch(c->state) {
        case CLOSED:
@@ -2101,6 +2108,7 @@ static bool reset_connection(struct utcp_connection *c) {
        hdr.ack = c->rcv.nxt;
        hdr.wnd = 0;
        hdr.ctl = RST;
+       hdr.aux = 0;
 
        print_packet(c, "send", &hdr, sizeof(hdr));
        c->utcp->send(c->utcp, &hdr, sizeof(hdr));
@@ -2108,16 +2116,16 @@ static bool reset_connection(struct utcp_connection *c) {
 }
 
 static void set_reapable(struct utcp_connection *c) {
-       set_buffer_storage(&c->sndbuf, NULL, DEFAULT_MTU);
-       set_buffer_storage(&c->rcvbuf, NULL, DEFAULT_MTU);
+       set_buffer_storage(&c->sndbuf, NULL, min(c->sndbuf.maxsize, DEFAULT_MAXSNDBUFSIZE));
+       set_buffer_storage(&c->rcvbuf, NULL, min(c->rcvbuf.maxsize, DEFAULT_MAXRCVBUFSIZE));
 
        c->recv = NULL;
        c->poll = NULL;
        c->reapable = true;
 }
 
-// Closes all the opened connections
-void utcp_abort_all_connections(struct utcp *utcp) {
+// Resets all connections, but does not invalidate connection handles
+void utcp_reset_all_connections(struct utcp *utcp) {
        if(!utcp) {
                errno = EINVAL;
                return;
@@ -2130,19 +2138,16 @@ void utcp_abort_all_connections(struct utcp *utcp) {
                        continue;
                }
 
-               utcp_recv_t old_recv = c->recv;
-               utcp_poll_t old_poll = c->poll;
-
-               utcp_abort(c);
+               reset_connection(c);
 
-               if(old_recv) {
+               if(c->recv) {
                        errno = 0;
-                       old_recv(c, NULL, 0);
+                       c->recv(c, NULL, 0);
                }
 
-               if(old_poll && !c->reapable) {
+               if(c->poll && !c->reapable) {
                        errno = 0;
-                       old_poll(c, 0);
+                       c->poll(c, 0);
                }
        }
 
@@ -2199,6 +2204,8 @@ struct timespec utcp_timeout(struct utcp *utcp) {
                if(timespec_isset(&c->conn_timeout) && timespec_lt(&c->conn_timeout, &now)) {
                        errno = ETIMEDOUT;
                        c->state = CLOSED;
+                       buffer_clear(&c->sndbuf);
+                       buffer_clear(&c->rcvbuf);
 
                        if(c->recv) {
                                c->recv(c, NULL, 0);
@@ -2301,6 +2308,9 @@ void utcp_exit(struct utcp *utcp) {
                struct utcp_connection *c = utcp->connections[i];
 
                if(!c->reapable) {
+                       buffer_clear(&c->sndbuf);
+                       buffer_clear(&c->rcvbuf);
+
                        if(c->recv) {
                                c->recv(c, NULL, 0);
                        }