a0d4c5e208
when we get eof, stop the loop immidiately and do not rely on the read to eventually return an error. when convM2S() fails to decode the message, error out and stop the loop. there is no point in continuing.
187 lines
3.3 KiB
C
187 lines
3.3 KiB
C
#include "all.h"
|
|
|
|
static char *tnames[] = {
|
|
[Tversion] "version",
|
|
[Tauth] "auth",
|
|
[Tattach] "attach",
|
|
[Tflush] "flush",
|
|
[Twalk] "walk",
|
|
[Topen] "open",
|
|
[Tcreate] "create",
|
|
[Tread] "read",
|
|
[Twrite] "write",
|
|
[Tclunk] "clunk",
|
|
[Tremove] "remove",
|
|
[Tstat] "stat",
|
|
[Twstat] "wstat",
|
|
};
|
|
|
|
int messagesize = IOHDRSZ+Maxfdata;
|
|
|
|
int
|
|
xmesg(Session *s, int t)
|
|
{
|
|
int n;
|
|
|
|
if(chatty){
|
|
if(0 <= t && t < nelem(tnames) && tnames[t])
|
|
chat("T%s...", tnames[t]);
|
|
else
|
|
chat("T%d...", t);
|
|
}
|
|
s->f.type = t;
|
|
s->f.tag = ++s->tag;
|
|
if(p9debug)
|
|
fprint(2, "xmseg\tsend %F\n", &s->f);
|
|
n = convS2M(&s->f, s->data, messagesize);
|
|
if(niwrite(s->fd, s->data, n) != n){
|
|
clog("xmesg write error on %d: %r\n", s->fd);
|
|
return -1;
|
|
}
|
|
again:
|
|
n = read9pmsg(s->fd, s->data, messagesize);
|
|
if(n == 0)
|
|
return -1;
|
|
if(n < 0){
|
|
clog("xmesg read error: %r\n");
|
|
return -1;
|
|
}
|
|
if(convM2S(s->data, n, &s->f) != n){
|
|
clog("xmesg bad convM2S %d %.2x %.2x %.2x %.2x\n",
|
|
n, ((uchar*)s->data)[0], ((uchar*)s->data)[1],
|
|
((uchar*)s->data)[2], ((uchar*)s->data)[3]);
|
|
return -1;
|
|
}
|
|
if(p9debug)
|
|
fprint(2, "\trecv %F\n", &s->f);
|
|
if(s->f.tag != s->tag){
|
|
clog("xmesg tag %d for %d\n", s->f.tag, s->tag);
|
|
goto again;
|
|
}
|
|
if(s->f.type == Rerror){
|
|
if(t == Tclunk)
|
|
clog("xmesg clunk: %s", s->f.ename);
|
|
chat("xmesg %d error %s...", t, s->f.ename);
|
|
return -1;
|
|
}
|
|
if(s->f.type != t+1){
|
|
clog("xmesg type mismatch: %d, expected %d\n", s->f.type, t+1);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
clunkfid(Session *s, Fid *f)
|
|
{
|
|
putfid(s, f);
|
|
if(s == 0 || f == 0)
|
|
return 0;
|
|
s->f.fid = f - s->fids;
|
|
return xmesg(s, Tclunk);
|
|
}
|
|
|
|
#define UNLINK(p) ((p)->prev->next = (p)->next, (p)->next->prev = (p)->prev)
|
|
|
|
#define LINK(h, p) ((p)->next = (h)->next, (p)->prev = (h), \
|
|
(h)->next->prev = (p), (h)->next = (p))
|
|
|
|
#define TOFRONT(h, p) ((h)->next != (p) ? (UNLINK(p), LINK(h,p)) : 0)
|
|
|
|
Fid *
|
|
newfid(Session *s)
|
|
{
|
|
Fid *f, *fN;
|
|
|
|
chat("newfid..");
|
|
if(s->list.prev == 0){
|
|
chat("init..");
|
|
s->list.prev = &s->list;
|
|
s->list.next = &s->list;
|
|
s->free = s->fids;
|
|
if(0 && chatty)
|
|
fN = &s->fids[25];
|
|
else
|
|
fN = &s->fids[nelem(s->fids)];
|
|
for(f=s->fids; f<fN; f++){
|
|
f->owner = 0;
|
|
f->prev = 0;
|
|
f->next = f+1;
|
|
}
|
|
(f-1)->next = 0;
|
|
}
|
|
if(s->free){
|
|
f = s->free;
|
|
s->free = f->next;
|
|
LINK(&s->list, f);
|
|
}else{
|
|
for(f=s->list.prev; f!=&s->list; f=f->prev)
|
|
if(f->owner)
|
|
break;
|
|
if(f == &s->list){
|
|
clog("fid leak");
|
|
return 0;
|
|
}
|
|
setfid(s, f);
|
|
if(xmesg(s, Tclunk) < 0){
|
|
clog("clunk failed, no fids?");
|
|
/*return 0;*/
|
|
}
|
|
*(f->owner) = 0;
|
|
f->owner = 0;
|
|
}
|
|
chat("%zd...", f - s->fids);
|
|
f->tstale = nfstime + staletime;
|
|
return f;
|
|
}
|
|
|
|
void
|
|
setfid(Session *s, Fid *f)
|
|
{
|
|
/*
|
|
* TOFRONT(&s->list, f);
|
|
*/
|
|
if(s->list.next != f){
|
|
UNLINK(f);
|
|
LINK(&s->list, f);
|
|
}
|
|
|
|
f->tstale = nfstime + staletime;
|
|
s->f.fid = f - s->fids;
|
|
}
|
|
|
|
void
|
|
putfid(Session *s, Fid *f)
|
|
{
|
|
chat("putfid %zd...", f-s->fids);
|
|
if(s == 0 || f == 0){
|
|
clog("putfid(0x%p, 0x%p) %s", s, f, (s ? s->service : "?"));
|
|
return;
|
|
}
|
|
UNLINK(f);
|
|
if(f->owner)
|
|
*(f->owner) = 0;
|
|
f->owner = 0;
|
|
f->prev = 0;
|
|
f->next = s->free;
|
|
s->free = f;
|
|
}
|
|
|
|
void
|
|
fidtimer(Session *s, long now)
|
|
{
|
|
Fid *f, *t;
|
|
int n;
|
|
|
|
f = s->list.next;
|
|
n = 0;
|
|
while(f != &s->list){
|
|
t = f;
|
|
f = f->next;
|
|
if(t->owner && now >= t->tstale)
|
|
++n, clunkfid(s, t);
|
|
}
|
|
if(n > 0)
|
|
chat("fidtimer %s\n", s->service);
|
|
}
|