shithub: drawterm

Download patch

ref: e61ca3be6f93135afc575df89d146e946e2b6ec4
parent: 0646450b2051b5b34f80cdf64810474b256248be
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Thu Feb 2 14:49:05 EST 2017

aan: fix ack logic, handle connection shutdown

--- a/aan.c	Fri Jan 27 19:11:00 2017
+++ b/aan.c	Thu Feb  2 14:49:05 2017
@@ -138,8 +138,8 @@
 aanreader(void *arg)
 {
 	Client *c = (Client*)arg;
-	Buf *b, *x, **l;
-	long a, m;
+	long a, m, lastacked = 0;
+	Buf *b, *x;
 	int n;
 
 Restart:
@@ -150,34 +150,42 @@
 		a = GBIT32(b->hdr.acked);
 		m = GBIT32(b->hdr.msg);
 		n = GBIT32(b->hdr.nb);
-		if(n > Bufsize)
-			break;
-
-		qlock(&c->lk);
-		l = &c->unackedhead;
-		for(x = c->unackedhead; x != nil; x = *l){
-			if(a >= GBIT32(x->hdr.msg)){
-				if((*l = x->next) == nil)
-					c->unackedtail = l;
-				free(x);
-			} else {
-				l = &x->next;
-			}
-		}
-		qunlock(&c->lk);
+		if(n == 0){
+			if(m < 0)
+				continue;
+			goto Closed;
+		} else if(n < 0 || n > Bufsize)
+			goto Closed;
 
 		if(readn(c->netfd, b->buf, n) != n)
 			break;
 		if(m < c->inmsg)
 			continue;
 		c->inmsg++;
+
+		if(lastacked != a){
+			qlock(&c->lk);
+			while((x = c->unackedhead) != nil){
+				assert(GBIT32(x->hdr.msg) == lastacked);
+				c->unackedhead = x->next;
+				free(x);
+				if(++lastacked == a)
+					break;
+			}
+			qunlock(&c->lk);
+		}
+
 		if(c->pipefd < 0)
-			return;
+			goto Closed;
 		write(c->pipefd, b->buf, n);
 	}
 	free(b);
 	reconnect(c);
 	goto Restart;
+Closed:
+	free(b);
+	if(c->pipefd >= 0)
+		write(c->pipefd, "", 0);
 }
 
 int