sshnet: fix eof and close handling, use proper packet size, cleanup
This commit is contained in:
parent
3bb1804631
commit
a278545e3c
1 changed files with 59 additions and 54 deletions
|
@ -61,6 +61,7 @@ struct Client
|
|||
int state;
|
||||
int num;
|
||||
int servernum;
|
||||
int sentclose;
|
||||
char *connect;
|
||||
|
||||
int sendpkt;
|
||||
|
@ -68,6 +69,8 @@ struct Client
|
|||
int recvwin;
|
||||
int recvacc;
|
||||
|
||||
int eof;
|
||||
|
||||
Req *wq;
|
||||
Req **ewq;
|
||||
|
||||
|
@ -91,7 +94,8 @@ enum {
|
|||
MSG_CHANNEL_SUCCESS,
|
||||
MSG_CHANNEL_FAILURE,
|
||||
|
||||
MaxPacket = 1<<15,
|
||||
Overhead = 256,
|
||||
MaxPacket = (1<<15)-256, /* 32K is maxatomic for pipe */
|
||||
WinPackets = 8,
|
||||
|
||||
SESSIONCHAN = 1<<24,
|
||||
|
@ -104,7 +108,7 @@ struct Msg
|
|||
uchar *rp;
|
||||
uchar *wp;
|
||||
uchar *ep;
|
||||
uchar buf[MaxPacket];
|
||||
uchar buf[MaxPacket + Overhead];
|
||||
};
|
||||
|
||||
#define PUT4(p, u) (p)[0] = (u)>>24, (p)[1] = (u)>>16, (p)[2] = (u)>>8, (p)[3] = (u)
|
||||
|
@ -116,6 +120,7 @@ char *mtpt;
|
|||
int sshfd;
|
||||
int localport;
|
||||
char localip[] = "::";
|
||||
char Ehangup[] = "hangup on network connection";
|
||||
|
||||
int
|
||||
vpack(uchar *p, int n, char *fmt, va_list a)
|
||||
|
@ -341,12 +346,10 @@ matchrmsgs(Client *c)
|
|||
Msg *m;
|
||||
int n, rm;
|
||||
|
||||
while(c->rq != nil && c->mq != nil){
|
||||
r = c->rq;
|
||||
while((r = c->rq) != nil && (m = c->mq) != nil){
|
||||
c->rq = r->aux;
|
||||
|
||||
r->aux = nil;
|
||||
rm = 0;
|
||||
m = c->mq;
|
||||
n = r->ifcall.count;
|
||||
if(n >= m->wp - m->rp){
|
||||
n = m->wp - m->rp;
|
||||
|
@ -362,6 +365,15 @@ matchrmsgs(Client *c)
|
|||
respond(r, nil);
|
||||
adjustwin(c, n);
|
||||
}
|
||||
|
||||
if(c->eof){
|
||||
while((r = c->rq) != nil){
|
||||
c->rq = r->aux;
|
||||
r->aux = nil;
|
||||
r->ofcall.count = 0;
|
||||
respond(r, nil);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -438,57 +450,48 @@ dialedclient(Client *c)
|
|||
}
|
||||
|
||||
void
|
||||
teardownclient(Client *c)
|
||||
hangupclient(Client *c)
|
||||
{
|
||||
c->state = Teardown;
|
||||
sendmsg(pack(nil, "bu", MSG_CHANNEL_EOF, c->servernum));
|
||||
Req *r;
|
||||
|
||||
c->eof = 1;
|
||||
c->recvwin = 0;
|
||||
c->sendwin = 0;
|
||||
while((r = c->wq) != nil){
|
||||
c->wq = r->aux;
|
||||
r->aux = nil;
|
||||
respond(r, Ehangup);
|
||||
}
|
||||
if(c->state == Established){
|
||||
c->state = Teardown;
|
||||
matchrmsgs(c);
|
||||
return;
|
||||
}
|
||||
c->state = Closed;
|
||||
}
|
||||
|
||||
void
|
||||
hangupclient(Client *c)
|
||||
teardownclient(Client *c)
|
||||
{
|
||||
Req *r, *next;
|
||||
Msg *m, *mnext;
|
||||
|
||||
c->state = Closed;
|
||||
for(m=c->mq; m; m=mnext){
|
||||
mnext = m->link;
|
||||
free(m);
|
||||
}
|
||||
c->mq = nil;
|
||||
for(r=c->rq; r; r=next){
|
||||
next = r->aux;
|
||||
respond(r, "hangup on network connection");
|
||||
}
|
||||
c->rq = nil;
|
||||
for(r=c->wq; r; r=next){
|
||||
next = r->aux;
|
||||
respond(r, "hangup on network connection");
|
||||
}
|
||||
c->wq = nil;
|
||||
hangupclient(c);
|
||||
if(c->sentclose++ == 0)
|
||||
sendmsg(pack(nil, "bu", MSG_CHANNEL_CLOSE, c->servernum));
|
||||
}
|
||||
|
||||
void
|
||||
closeclient(Client *c)
|
||||
{
|
||||
Msg *m, *next;
|
||||
Msg *m;
|
||||
|
||||
if(--c->ref)
|
||||
return;
|
||||
|
||||
if(c->rq != nil || c->wq != nil)
|
||||
sysfatal("ref count reached zero with requests pending (BUG)");
|
||||
|
||||
for(m=c->mq; m; m=next){
|
||||
next = m->link;
|
||||
if(c->state >= Established)
|
||||
teardownclient(c);
|
||||
while((m = c->mq) != nil){
|
||||
c->mq = m->link;
|
||||
free(m);
|
||||
}
|
||||
c->mq = nil;
|
||||
|
||||
if(c->state != Closed)
|
||||
teardownclient(c);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sshreadproc(void*)
|
||||
|
@ -810,6 +813,7 @@ ctlwrite(Req *r, Client *c)
|
|||
nf = getfields(f[1], f, nelem(f), 0, "!");
|
||||
if(nf != 2)
|
||||
goto Badarg;
|
||||
c->eof = 0;
|
||||
c->sendwin = MaxPacket;
|
||||
c->recvwin = WinPackets * MaxPacket;
|
||||
c->recvacc = 0;
|
||||
|
@ -831,7 +835,7 @@ ctlwrite(Req *r, Client *c)
|
|||
static void
|
||||
dataread(Req *r, Client *c)
|
||||
{
|
||||
if(c->state != Established){
|
||||
if(c->state < Established){
|
||||
respond(r, "not connected");
|
||||
return;
|
||||
}
|
||||
|
@ -1028,7 +1032,7 @@ fsflush(Req *r)
|
|||
static void
|
||||
handlemsg(Msg *m)
|
||||
{
|
||||
int chan, win, pkt, n, l;
|
||||
int chan, win, pkt, n;
|
||||
Client *c;
|
||||
char *s;
|
||||
|
||||
|
@ -1037,7 +1041,7 @@ handlemsg(Msg *m)
|
|||
if(unpack(m, "_uu", &chan, &n) < 0)
|
||||
break;
|
||||
c = getclient(chan);
|
||||
if(c != nil && c->state==Established){
|
||||
if(c != nil && c->state == Established){
|
||||
c->sendwin += n;
|
||||
procwreqs(c);
|
||||
}
|
||||
|
@ -1046,7 +1050,9 @@ handlemsg(Msg *m)
|
|||
if(unpack(m, "_us", &chan, &s, &n) < 0)
|
||||
break;
|
||||
c = getclient(chan);
|
||||
if(c != nil && c->state==Established){
|
||||
if(c != nil && c->state == Established){
|
||||
if(c->recvwin <= 0)
|
||||
break;
|
||||
c->recvwin -= n;
|
||||
m->rp = (uchar*)s;
|
||||
queuermsg(c, m);
|
||||
|
@ -1058,18 +1064,17 @@ handlemsg(Msg *m)
|
|||
if(unpack(m, "_u", &chan) < 0)
|
||||
break;
|
||||
c = getclient(chan);
|
||||
if(c != nil){
|
||||
hangupclient(c);
|
||||
m->rp = m->wp = m->buf;
|
||||
sendmsg(pack(m, "bu", MSG_CHANNEL_CLOSE, c->servernum));
|
||||
return;
|
||||
if(c != nil && c->state == Established){
|
||||
c->eof = 1;
|
||||
c->recvwin = 0;
|
||||
matchrmsgs(c);
|
||||
}
|
||||
break;
|
||||
case MSG_CHANNEL_CLOSE:
|
||||
if(unpack(m, "_u", &chan) < 0)
|
||||
break;
|
||||
c = getclient(chan);
|
||||
if(c != nil)
|
||||
if(c != nil && c->state >= Established)
|
||||
hangupclient(c);
|
||||
break;
|
||||
case MSG_CHANNEL_OPEN_CONFIRMATION:
|
||||
|
@ -1087,20 +1092,20 @@ handlemsg(Msg *m)
|
|||
c->sendpkt = pkt;
|
||||
c->sendwin = win;
|
||||
c->servernum = n;
|
||||
c->sentclose = 0;
|
||||
c->state = Established;
|
||||
dialedclient(c);
|
||||
break;
|
||||
case MSG_CHANNEL_OPEN_FAILURE:
|
||||
if(unpack(m, "_uus", &chan, &n, &s, &l) < 0)
|
||||
if(unpack(m, "_u____s", &chan, &s, &n) < 0)
|
||||
break;
|
||||
if(chan == SESSIONCHAN){
|
||||
sendp(ssherrchan, smprint("%.*s", utfnlen(s, l), s));
|
||||
sendp(ssherrchan, smprint("%.*s", utfnlen(s, n), s));
|
||||
break;
|
||||
}
|
||||
c = getclient(chan);
|
||||
if(c == nil || c->state != Dialing)
|
||||
break;
|
||||
c->servernum = n;
|
||||
c->state = Closed;
|
||||
dialedclient(c);
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue