From 87f41a892392b963a50883945ecc73db9264144a Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 11 Dec 1999 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1999-12-11 --- port/devsdp.c | 234 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 139 insertions(+), 95 deletions(-) diff --git a/port/devsdp.c b/port/devsdp.c index 1a6d462492483d57ba1b16631218055077ab02b8..96fa3cc8a958b0867c595c392792a822969c8b37 100644 --- a/port/devsdp.c +++ b/port/devsdp.c @@ -41,8 +41,8 @@ enum Maxconv= 256, // power of 2 Nfs= 4, // number of file systems - MaxRetries= 8, - KeepAlive = 60, // keep alive in seconds + MaxRetries= 4, + KeepAlive = 10, // keep alive in seconds SecretLength= 32, // a secret per direction SeqMax = (1<<24), SeqWindow = 32, @@ -104,6 +104,7 @@ struct OneWay // conv states enum { + CFree, CInit, CDial, CAccept, @@ -115,12 +116,15 @@ enum { struct Conv { QLock; - int id; - int ref; // number of times the conv is opened Sdp *sdp; + int id; + + int ref; // holds conv up int state; - int dataopen; + + int dataopen; // ref count of opens on Qdata + int controlopen; // ref count of opens on Qcontrol int reader; // reader proc has been started Stats lstats; @@ -137,7 +141,7 @@ struct Conv { QLock readlk; // protects readproc Proc *readproc; - Chan *chan; // packet channel + Chan *chan; // packet channel char *channame; char owner[NAMELEN]; /* protections */ @@ -268,35 +272,37 @@ static Logflag logflags[] = static Dirtab *dirtab[MaxQ]; static Sdp sdptab[Nfs]; static char *convstatename[] = { - [CInit] "Init", - [CDial] "Dial", - [CAccept] "Accept", - [COpen] "Open", + [CFree] "Free", + [CInit] "Init", + [CDial] "Dial", + [CAccept] "Accept", + [COpen] "Open", [CLocalClose] "LocalClose", [CRemoteClose] "RemoteClose", - [CClosed] "Closed", + [CClosed] "Closed", }; static int sdpgen(Chan *c, Dirtab*, int, int s, Dir *dp); static Conv *sdpclone(Sdp *sdp); -static void convsetstate(Conv *c, int state); static void sdpackproc(void *a); static void onewaycleanup(OneWay *ow); static int readready(void *a); static int controlread(); +static void convsetstate(Conv *c, int state); +static Block *readcontrol(Conv *c, int n); +static void writecontrol(Conv *c, void *p, int n, int wait); +static Block *readdata(Conv *c, int n); +static long writedata(Conv *c, Block *b); +static void convderef(Conv *c); static Block *conviput(Conv *c, Block *b, int control); static void conviconnect(Conv *c, int op, Block *b); static void convicontrol(Conv *c, int op, Block *b); static Block *convicomp(Conv *c, int op, ulong, Block *b); -static void writecontrol(Conv *c, void *p, int n, int wait); -static Block *readcontrol(Conv *c, int n); -static Block *readdata(Conv *c, int n); -static long writedata(Conv *c, Block *b); static void convoput(Conv *c, int type, int subtype, Block *b); static void convoconnect(Conv *c, int op, ulong dialid, ulong acceptid); -static void convreader(void *a); static void convopenchan(Conv *c, char *path); static void convstats(Conv *c, int local, char *buf, int n); +static void convreader(void *a); static void setalg(Conv *c, char *name, Algorithm *tab, Algorithm **); static void setsecret(OneWay *cc, char *secret); @@ -412,6 +418,7 @@ sdpstat(Chan* c, char* db) devstat(c, db, nil, 0, sdpgen); } + static Chan* sdpopen(Chan* ch, int omode) { @@ -450,6 +457,7 @@ sdpopen(Chan* ch, int omode) case Qstats: case Qrstats: c = sdp->conv[CONV(ch->qid)]; +print("open %d:%d: ref=%d\n", c->id, TYPE(ch->qid), c->ref); qlock(c); if(waserror()) { qunlock(c); @@ -458,12 +466,16 @@ sdpopen(Chan* ch, int omode) if((perm & (c->perm>>6)) != perm) if(strcmp(up->user, c->owner) != 0 || (perm & c->perm) != perm) error(Eperm); + c->ref++; if(TYPE(ch->qid) == Qdata) { - if(c->dataopen == 0) + c->dataopen++; + // kill reader if Qdata is opened for the first time + if(c->dataopen == 1) if(c->readproc != nil) postnote(c->readproc, 1, "interrupt", 0); - c->dataopen++; + } else if(TYPE(ch->qid) == Qcontrol) { + c->controlopen++; } qunlock(c); poperror(); @@ -481,32 +493,45 @@ sdpclose(Chan* ch) Sdp *sdp = sdptab + ch->dev; Conv *c; + if(!(ch->flag & COPEN)) + return; switch(TYPE(ch->qid)) { case Qlog: - if(ch->flag & COPEN) - logclose(sdp); + logclose(sdp); break; - case Qdata: case Qctl: case Qstatus: - case Qcontrol: - if(!(ch->flag & COPEN)) - break; + case Qstats: + case Qrstats: c = sdp->conv[CONV(ch->qid)]; qlock(c); - if(waserror()) { - qunlock(c); - nexterror(); - } - c->ref--; - if(TYPE(ch->qid) == Qdata) { - c->dataopen--; - if(c->dataopen == 0 && c->reader == 0) { - kproc("convreader", convreader, c); - c->reader = 1; - } + convderef(c); + qunlock(c); + break; + + case Qdata: + c = sdp->conv[CONV(ch->qid)]; + qlock(c); + c->dataopen--; + convderef(c); + if(c->dataopen == 0) + if(c->reader == 0) + if(c->chan != nil) + if(!waserror()) { + kproc("convreader", convreader, c); + c->reader = 1; + c->ref++; + poperror(); } - if(c->ref == 0) { + qunlock(c); + break; + + case Qcontrol: + c = sdp->conv[CONV(ch->qid)]; + qlock(c); + c->controlopen--; + convderef(c); + if(c->controlopen == 0 && c->ref != 0) { switch(c->state) { default: convsetstate(c, CClosed); @@ -515,8 +540,6 @@ sdpclose(Chan* ch) case COpen: convsetstate(c, CLocalClose); break; - case CLocalClose: - panic("local close already happened"); } } qunlock(c); @@ -771,8 +794,9 @@ sdpclone(Sdp *sdp) sdp->nconv++; break; } - if(canqlock(c)){ - if(c->state == CClosed && c->reader == 0 && c->ref == 0) + if(c->ref == 0 && canqlock(c)){ +print("%d: state=%d reader=%d ref=%d\n", c->id, c->state, c->reader, c->ref); + if(c->ref == 0) break; qunlock(c); } @@ -783,7 +807,9 @@ sdpclone(Sdp *sdp) if(pp >= ep) return nil; - c->ref++; + assert(c->state == CFree); + // set ref to 2 - 1 ref for open - 1 ref for channel state + c->ref = 2; c->state = CInit; c->in.window = ~0; strncpy(c->owner, up->user, sizeof(c->owner)); @@ -819,6 +845,7 @@ print("convretry: giving up\n"); return 1; } +// assumes c is locked static void convtimer(Conv *c, ulong sec) { @@ -826,12 +853,10 @@ convtimer(Conv *c, ulong sec) if(c->timeout > sec) return; - qlock(c); - if(waserror()) { - qunlock(c); - nexterror(); - } + switch(c->state) { + case CInit: + break; case CDial: if(convretry(c, 1)) convoconnect(c, ConOpenRequest, c->dialid, 0); @@ -873,11 +898,8 @@ print("sending keep alive: %ld\n", sec - c->lastrecv); break; case CRemoteClose: case CClosed: - c->timeout = ~0; break; } - poperror(); - qunlock(c); } @@ -895,10 +917,16 @@ sdpackproc(void *a) qlock(sdp); for(i=0; inconv; i++) { c = sdp->conv[i]; - if(!waserror()) { + if(c->ref == 0) + continue; + qunlock(sdp); + qlock(c); + if(c->ref > 0 && !waserror()) { convtimer(c, sec); poperror(); } + qunlock(c); + qlock(sdp); } qunlock(sdp); } @@ -949,6 +977,7 @@ print("convsetstate %s -> %s\n", convstatename[c->state], convstatename[state]); break; case COpen: assert(c->state == CDial || c->state == CAccept); + c->lastrecv = TK2SEC(m->ticks); if(c->state == CDial) { convretryinit(c); convoconnect(c, ConOpenAckAck, c->dialid, c->acceptid); @@ -971,43 +1000,58 @@ print("convsetstate %s -> %s\n", convstatename[c->state], convstatename[state]); break; case CRemoteClose: wakeup(&c->in.controlready); -// convoconnect(c, ConReset, c->dialid, c->acceptid); + wakeup(&c->out.controlready); break; case CClosed: wakeup(&c->in.controlready); wakeup(&c->out.controlready); if(c->readproc) postnote(c->readproc, 1, "interrupt", 0); -print("CClosed -> ref = %d\n", c->ref); - if(c->chan) { - cclose(c->chan); - c->chan = nil; - } - if(c->ref) - break; - if(c->channame) { - free(c->channame); - c->channame = nil; - } - c->cipher = nil; - c->auth = nil; - c->comp = nil; - strcpy(c->owner, "network"); - c->perm = 0660; - c->dialid = 0; - c->acceptid = 0; - c->timeout = ~0; - c->retries = 0; - c->drop = 0; - onewaycleanup(&c->in); - onewaycleanup(&c->out); - memset(&c->lstats, 0, sizeof(Stats)); - memset(&c->rstats, 0, sizeof(Stats)); + if(c->state != CClosed) + convderef(c); break; } c->state = state; } + +//assumes c is locked +static void +convderef(Conv *c) +{ + c->ref--; +print("convderef: %d: ref == %d\n", c->id, c->ref); + if(c->ref > 0) + return; + assert(c->ref == 0); + assert(c->dataopen == 0); + assert(c->controlopen == 0); +//print("convderef: %d: ref == 0!\n", c->id); + c->state = CFree; + if(c->chan) { + cclose(c->chan); + c->chan = nil; + } + if(c->channame) { + free(c->channame); + c->channame = nil; + } + c->cipher = nil; + c->auth = nil; + c->comp = nil; + strcpy(c->owner, "network"); + c->perm = 0660; + c->dialid = 0; + c->acceptid = 0; + c->timeout = 0; + c->retries = 0; + c->drop = 0; + onewaycleanup(&c->in); + onewaycleanup(&c->out); + memset(&c->lstats, 0, sizeof(Stats)); + memset(&c->rstats, 0, sizeof(Stats)); +} + static void onewaycleanup(OneWay *ow) { @@ -1040,7 +1084,12 @@ convopenchan(Conv *c, char *path) nexterror(); } kproc("convreader", convreader, c); + + assert(c->reader == 0 && c->ref > 0); + // after kproc in case it fails c->reader = 1; + c->ref++; + poperror(); } @@ -1215,14 +1264,14 @@ print("pad too big\n"); if(seqdiff > 0) { while(seqdiff > 0 && c->in.window != 0) { if((c->in.window & (1<<(SeqWindow-1))) == 0) { -print("missing packet: %ld\n", seq - seqdiff); +//print("missing packet: %ld\n", seq - seqdiff); c->lstats.inMissing++; } c->in.window <<= 1; seqdiff--; } if(seqdiff > 0) { -print("missing packets: %ld-%ld\n", seq - SeqWindow - seqdiff+1, seq-SeqWindow); +//print("missing packets: %ld-%ld\n", seq - SeqWindow - seqdiff+1, seq-SeqWindow); c->lstats.inMissing += seqdiff; } c->in.seq = seq; @@ -1520,30 +1569,28 @@ convoconnect(Conv *c, int op, ulong dialid, ulong acceptid) Block *b; c->lstats.outPackets++; - if(c->chan == nil) { -print("chan = nil\n"); - error("no channel attached"); - } + assert(c->chan != nil); b = allocb(9); b->wp[0] = (TConnect << 4) | op; hnputl(b->wp+1, dialid); hnputl(b->wp+5, acceptid); b->wp += 9; - convwriteblock(c, b); + if(!waserror()) { + convwriteblock(c, b); + poperror(); + } } static Block * convreadblock(Conv *c, int n) { Block *b; - Chan *ch = nil; + Chan *ch; qlock(&c->readlk); if(waserror()) { c->readproc = nil; - if(ch) - cclose(ch); qunlock(&c->readlk); nexterror(); } @@ -1554,12 +1601,11 @@ convreadblock(Conv *c, int n) } c->readproc = up; ch = c->chan; - incref(ch); + assert(c->ref > 0); qunlock(c); b = devtab[ch->type]->bread(ch, n, 0); c->readproc = nil; - cclose(ch); poperror(); qunlock(&c->readlk); @@ -1770,10 +1816,7 @@ print("convreader\n"); if(b == nil) { print("up->error = %s\n", up->error); if(strcmp(up->error, Eintr) != 0) { - if(!waserror()) { - convsetstate(c, CClosed); - poperror(); - } + convsetstate(c, CClosed); break; } } else if(!waserror()) { @@ -1783,6 +1826,7 @@ print("up->error = %s\n", up->error); } print("convreader exiting\n"); c->reader = 0; + convderef(c); qunlock(c); pexit("hangup", 1); } @@ -2025,7 +2069,7 @@ rc4decrypt(OneWay *ow, uchar *p, int n) cr->ovalid = 0; } } else if(d > 0) { -print("missing packet: %uld %ld\n", seq, d); +//print("missing packet: %uld %ld\n", seq, d); // this link is hosed if(d > RC4forward) return 0; @@ -2039,7 +2083,7 @@ print("missing packet: %uld %ld\n", seq, d); rc4(&cr->current, p, n); cr->cseq = seq+n; } else { -print("reordered packet: %uld %ld\n", seq, d); +//print("reordered packet: %uld %ld\n", seq, d); dd = seq - cr->oseq; if(!cr->ovalid || -d > RC4back || dd < 0) return 0;