summaryrefslogtreecommitdiff
path: root/sys/src/cmd/sshnet.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2019-04-03 13:45:54 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2019-04-03 13:45:54 +0200
commit2251ef7a32f881ae2c80989d5285db943aa2073b (patch)
tree2c4e2f59b202198f4ea2593e24fa74db96120adf /sys/src/cmd/sshnet.c
parenta278545e3c492d97d32192e20de7c62c8b0ef4a2 (diff)
sshnet: pass on open failure error message, simplify
return the error message from MSG_CHANNEL_OPEN_FAILURE in the "connect" control write. use a extra state "Finished" to distinguish server from client initiated teardown. that way we do not need to track if we send the MSG_CHANNEL_CLOSE message in closeclient(). this way we also cannot be fooled by misbehaving server. simplify hangupclient() by removing state transitions and doing them in the caller explicitely. that way we can use hangupclient() instead of dialedclient().
Diffstat (limited to 'sys/src/cmd/sshnet.c')
-rwxr-xr-xsys/src/cmd/sshnet.c81
1 files changed, 40 insertions, 41 deletions
diff --git a/sys/src/cmd/sshnet.c b/sys/src/cmd/sshnet.c
index 6c28144e5..993f16021 100755
--- a/sys/src/cmd/sshnet.c
+++ b/sys/src/cmd/sshnet.c
@@ -46,6 +46,7 @@ enum
Dialing,
Established,
Teardown,
+ Finished,
};
char *statestr[] = {
@@ -53,6 +54,7 @@ char *statestr[] = {
"Dialing",
"Established",
"Teardown",
+ "Finished",
};
struct Client
@@ -61,7 +63,6 @@ struct Client
int state;
int num;
int servernum;
- int sentclose;
char *connect;
int sendpkt;
@@ -120,7 +121,6 @@ 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)
@@ -434,23 +434,7 @@ findreq(Client *c, Req *r)
}
void
-dialedclient(Client *c)
-{
- Req *r;
-
- if(r=c->wq){
- if(r->aux != nil)
- sysfatal("more than one outstanding dial request (BUG)");
- if(c->state == Established)
- respond(r, nil);
- else
- respond(r, "connect failed");
- }
- c->wq = nil;
-}
-
-void
-hangupclient(Client *c)
+hangupclient(Client *c, char *err)
{
Req *r;
@@ -460,22 +444,17 @@ hangupclient(Client *c)
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;
+ respond(r, err);
}
- c->state = Closed;
+ matchrmsgs(c);
}
void
teardownclient(Client *c)
{
- hangupclient(c);
- if(c->sentclose++ == 0)
- sendmsg(pack(nil, "bu", MSG_CHANNEL_CLOSE, c->servernum));
+ c->state = Teardown;
+ hangupclient(c, "i/o on hungup channel");
+ sendmsg(pack(nil, "bu", MSG_CHANNEL_CLOSE, c->servernum));
}
void
@@ -485,14 +464,21 @@ closeclient(Client *c)
if(--c->ref)
return;
- if(c->state >= Established)
+ switch(c->state){
+ case Established:
teardownclient(c);
+ break;
+ case Finished:
+ c->state = Closed;
+ sendmsg(pack(nil, "bu", MSG_CHANNEL_CLOSE, c->servernum));
+ break;
+ }
while((m = c->mq) != nil){
c->mq = m->link;
free(m);
}
}
-
+
void
sshreadproc(void*)
{
@@ -813,9 +799,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->recvwin = WinPackets*MaxPacket;
c->recvacc = 0;
c->state = Dialing;
queuewreq(c, r);
@@ -1074,8 +1058,17 @@ handlemsg(Msg *m)
if(unpack(m, "_u", &chan) < 0)
break;
c = getclient(chan);
- if(c != nil && c->state >= Established)
- hangupclient(c);
+ if(c == nil)
+ break;
+ switch(c->state){
+ case Established:
+ c->state = Finished;
+ hangupclient(c, "connection closed");
+ break;
+ case Teardown:
+ c->state = Closed;
+ break;
+ }
break;
case MSG_CHANNEL_OPEN_CONFIRMATION:
if(unpack(m, "_uuuu", &chan, &n, &win, &pkt) < 0)
@@ -1089,25 +1082,31 @@ handlemsg(Msg *m)
break;
if(pkt <= 0 || pkt > MaxPacket)
pkt = MaxPacket;
+ c->eof = 0;
c->sendpkt = pkt;
c->sendwin = win;
c->servernum = n;
- c->sentclose = 0;
c->state = Established;
- dialedclient(c);
+ if(c->wq != nil){
+ respond(c->wq, nil);
+ c->wq = nil;
+ }
break;
case MSG_CHANNEL_OPEN_FAILURE:
if(unpack(m, "_u____s", &chan, &s, &n) < 0)
break;
+ s = smprint("%.*s", utfnlen(s, n), s);
if(chan == SESSIONCHAN){
- sendp(ssherrchan, smprint("%.*s", utfnlen(s, n), s));
+ sendp(ssherrchan, s);
break;
}
c = getclient(chan);
- if(c == nil || c->state != Dialing)
+ if(c == nil || c->state != Dialing){
+ free(s);
break;
+ }
c->state = Closed;
- dialedclient(c);
+ hangupclient(c, s);
break;
}
free(m);