changelog shortlog tags branches files raw gz bz2 help

Mercurial > hg > plan9front / changeset: sshnet: fix eof and close handling, use proper packet size, cleanup

changeset 7127: 2a70b2df336c
parent 7126: 9b9537ba3d35
child 7128: d9ebec7d14e8
author: cinap_lenrek@felloff.net
date: Wed, 03 Apr 2019 10:49:47 +0200
files: sys/src/cmd/sshnet.c
description: sshnet: fix eof and close handling, use proper packet size, cleanup
     1.1--- a/sys/src/cmd/sshnet.c
     1.2+++ b/sys/src/cmd/sshnet.c
     1.3@@ -61,6 +61,7 @@ struct Client
     1.4 	int state;
     1.5 	int num;
     1.6 	int servernum;
     1.7+	int sentclose;
     1.8 	char *connect;
     1.9 
    1.10 	int sendpkt;
    1.11@@ -68,6 +69,8 @@ struct Client
    1.12 	int recvwin;
    1.13 	int recvacc;
    1.14 
    1.15+	int eof;
    1.16+
    1.17 	Req *wq;
    1.18 	Req **ewq;
    1.19 
    1.20@@ -91,7 +94,8 @@ enum {
    1.21 	MSG_CHANNEL_SUCCESS,
    1.22 	MSG_CHANNEL_FAILURE,
    1.23 
    1.24-	MaxPacket = 1<<15,
    1.25+	Overhead = 256,
    1.26+	MaxPacket = (1<<15)-256,	/* 32K is maxatomic for pipe */
    1.27 	WinPackets = 8,
    1.28 
    1.29 	SESSIONCHAN = 1<<24,
    1.30@@ -104,7 +108,7 @@ struct Msg
    1.31 	uchar	*rp;
    1.32 	uchar	*wp;
    1.33 	uchar	*ep;
    1.34-	uchar	buf[MaxPacket];
    1.35+	uchar	buf[MaxPacket + Overhead];
    1.36 };
    1.37 
    1.38 #define PUT4(p, u) (p)[0] = (u)>>24, (p)[1] = (u)>>16, (p)[2] = (u)>>8, (p)[3] = (u)
    1.39@@ -116,6 +120,7 @@ char *mtpt;
    1.40 int sshfd;
    1.41 int localport;
    1.42 char localip[] = "::";
    1.43+char Ehangup[] = "hangup on network connection";
    1.44 
    1.45 int
    1.46 vpack(uchar *p, int n, char *fmt, va_list a)
    1.47@@ -341,12 +346,10 @@ matchrmsgs(Client *c)
    1.48 	Msg *m;
    1.49 	int n, rm;
    1.50 
    1.51-	while(c->rq != nil && c->mq != nil){
    1.52-		r = c->rq;
    1.53+	while((r = c->rq) != nil && (m = c->mq) != nil){
    1.54 		c->rq = r->aux;
    1.55-
    1.56+		r->aux = nil;
    1.57 		rm = 0;
    1.58-		m = c->mq;
    1.59 		n = r->ifcall.count;
    1.60 		if(n >= m->wp - m->rp){
    1.61 			n = m->wp - m->rp;
    1.62@@ -362,6 +365,15 @@ matchrmsgs(Client *c)
    1.63 		respond(r, nil);
    1.64 		adjustwin(c, n);
    1.65 	}
    1.66+
    1.67+	if(c->eof){
    1.68+		while((r = c->rq) != nil){
    1.69+			c->rq = r->aux;
    1.70+			r->aux = nil;
    1.71+			r->ofcall.count = 0;
    1.72+			respond(r, nil);
    1.73+		}
    1.74+	}
    1.75 }
    1.76 
    1.77 void
    1.78@@ -438,57 +450,48 @@ dialedclient(Client *c)
    1.79 }
    1.80 
    1.81 void
    1.82-teardownclient(Client *c)
    1.83+hangupclient(Client *c)
    1.84 {
    1.85-	c->state = Teardown;
    1.86-	sendmsg(pack(nil, "bu", MSG_CHANNEL_EOF, c->servernum));
    1.87+	Req *r;
    1.88+
    1.89+	c->eof = 1;
    1.90+	c->recvwin = 0;
    1.91+	c->sendwin = 0;
    1.92+	while((r = c->wq) != nil){
    1.93+		c->wq = r->aux;
    1.94+		r->aux = nil;
    1.95+		respond(r, Ehangup);
    1.96+	}
    1.97+	if(c->state == Established){
    1.98+		c->state = Teardown;
    1.99+		matchrmsgs(c);
   1.100+		return;
   1.101+	}
   1.102+	c->state = Closed;
   1.103 }
   1.104 
   1.105 void
   1.106-hangupclient(Client *c)
   1.107+teardownclient(Client *c)
   1.108 {
   1.109-	Req *r, *next;
   1.110-	Msg *m, *mnext;
   1.111-
   1.112-	c->state = Closed;
   1.113-	for(m=c->mq; m; m=mnext){
   1.114-		mnext = m->link;
   1.115-		free(m);
   1.116-	}
   1.117-	c->mq = nil;
   1.118-	for(r=c->rq; r; r=next){
   1.119-		next = r->aux;
   1.120-		respond(r, "hangup on network connection");
   1.121-	}
   1.122-	c->rq = nil;
   1.123-	for(r=c->wq; r; r=next){
   1.124-		next = r->aux;
   1.125-		respond(r, "hangup on network connection");
   1.126-	}
   1.127-	c->wq = nil;
   1.128+	hangupclient(c);
   1.129+	if(c->sentclose++ == 0)
   1.130+		sendmsg(pack(nil, "bu", MSG_CHANNEL_CLOSE, c->servernum));
   1.131 }
   1.132 
   1.133 void
   1.134 closeclient(Client *c)
   1.135 {
   1.136-	Msg *m, *next;
   1.137+	Msg *m;
   1.138 
   1.139 	if(--c->ref)
   1.140 		return;
   1.141-
   1.142-	if(c->rq != nil || c->wq != nil)
   1.143-		sysfatal("ref count reached zero with requests pending (BUG)");
   1.144-
   1.145-	for(m=c->mq; m; m=next){
   1.146-		next = m->link;
   1.147+	if(c->state >= Established)
   1.148+		teardownclient(c);
   1.149+	while((m = c->mq) != nil){
   1.150+		c->mq = m->link;
   1.151 		free(m);
   1.152 	}
   1.153-	c->mq = nil;
   1.154-
   1.155-	if(c->state != Closed)
   1.156-		teardownclient(c);
   1.157 }
   1.158-
   1.159 	
   1.160 void
   1.161 sshreadproc(void*)
   1.162@@ -810,6 +813,7 @@ ctlwrite(Req *r, Client *c)
   1.163 		nf = getfields(f[1], f, nelem(f), 0, "!");
   1.164 		if(nf != 2)
   1.165 			goto Badarg;
   1.166+		c->eof = 0;
   1.167 		c->sendwin = MaxPacket;
   1.168 		c->recvwin = WinPackets * MaxPacket;
   1.169 		c->recvacc = 0;
   1.170@@ -831,7 +835,7 @@ ctlwrite(Req *r, Client *c)
   1.171 static void
   1.172 dataread(Req *r, Client *c)
   1.173 {
   1.174-	if(c->state != Established){
   1.175+	if(c->state < Established){
   1.176 		respond(r, "not connected");
   1.177 		return;
   1.178 	}
   1.179@@ -1028,7 +1032,7 @@ fsflush(Req *r)
   1.180 static void
   1.181 handlemsg(Msg *m)
   1.182 {
   1.183-	int chan, win, pkt, n, l;
   1.184+	int chan, win, pkt, n;
   1.185 	Client *c;
   1.186 	char *s;
   1.187 
   1.188@@ -1037,7 +1041,7 @@ handlemsg(Msg *m)
   1.189 		if(unpack(m, "_uu", &chan, &n) < 0)
   1.190 			break;
   1.191 		c = getclient(chan);
   1.192-		if(c != nil && c->state==Established){
   1.193+		if(c != nil && c->state == Established){
   1.194 			c->sendwin += n;
   1.195 			procwreqs(c);
   1.196 		}
   1.197@@ -1046,7 +1050,9 @@ handlemsg(Msg *m)
   1.198 		if(unpack(m, "_us", &chan, &s, &n) < 0)
   1.199 			break;
   1.200 		c = getclient(chan);
   1.201-		if(c != nil && c->state==Established){
   1.202+		if(c != nil && c->state == Established){
   1.203+			if(c->recvwin <= 0)
   1.204+				break;
   1.205 			c->recvwin -= n;
   1.206 			m->rp = (uchar*)s;
   1.207 			queuermsg(c, m);
   1.208@@ -1058,18 +1064,17 @@ handlemsg(Msg *m)
   1.209 		if(unpack(m, "_u", &chan) < 0)
   1.210 			break;
   1.211 		c = getclient(chan);
   1.212-		if(c != nil){
   1.213-			hangupclient(c);
   1.214-			m->rp = m->wp = m->buf;
   1.215-			sendmsg(pack(m, "bu", MSG_CHANNEL_CLOSE, c->servernum));
   1.216-			return;
   1.217+		if(c != nil && c->state == Established){
   1.218+			c->eof = 1;
   1.219+			c->recvwin = 0;
   1.220+			matchrmsgs(c);
   1.221 		}
   1.222 		break;
   1.223 	case MSG_CHANNEL_CLOSE:
   1.224 		if(unpack(m, "_u", &chan) < 0)
   1.225 			break;
   1.226 		c = getclient(chan);
   1.227-		if(c != nil)
   1.228+		if(c != nil && c->state >= Established)
   1.229 			hangupclient(c);
   1.230 		break;
   1.231 	case MSG_CHANNEL_OPEN_CONFIRMATION:
   1.232@@ -1087,20 +1092,20 @@ handlemsg(Msg *m)
   1.233 		c->sendpkt = pkt;
   1.234 		c->sendwin = win;
   1.235 		c->servernum = n;
   1.236+		c->sentclose = 0;
   1.237 		c->state = Established;
   1.238 		dialedclient(c);
   1.239 		break;
   1.240 	case MSG_CHANNEL_OPEN_FAILURE:
   1.241-		if(unpack(m, "_uus", &chan, &n, &s, &l) < 0)
   1.242+		if(unpack(m, "_u____s", &chan, &s, &n) < 0)
   1.243 			break;
   1.244 		if(chan == SESSIONCHAN){
   1.245-			sendp(ssherrchan, smprint("%.*s", utfnlen(s, l), s));
   1.246+			sendp(ssherrchan, smprint("%.*s", utfnlen(s, n), s));
   1.247 			break;
   1.248 		}
   1.249 		c = getclient(chan);
   1.250 		if(c == nil || c->state != Dialing)
   1.251 			break;
   1.252-		c->servernum = n;
   1.253 		c->state = Closed;
   1.254 		dialedclient(c);
   1.255 		break;