## diffname port/devnonet.c 1990/1210 ## diff -e /dev/null /n/bootesdump/1990/1210/sys/src/9/port/devnonet.c 0a #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "errno.h" #define DPRINT if(0) #define NOW (MACHP(0)->ticks*MS2HZ) static Noifc *noifc; enum { /* * tuning parameters */ MSrexmit = 500, /* retranmission interval in ms */ MSack = 50, /* ms to sit on an ack */ /* * relative or immutable */ Nsubdir = 5, /* entries in the nonet directory */ Nmask = Nnomsg - 1, /* mask for log(Nnomsg) bits */ }; /* predeclared */ static void hangup(Noconv*); static Block* mkhdr(Noconv*, int); static void listen(Chan*, Noifc*); static void announce(Chan*, char*); static void connect(Chan*, char*); static void rcvack(Noconv*, int); static void sendctlmsg(Noconv*, int, int); static void sendmsg(Noconv*, Nomsg*); static void startconv(Noconv*, int, char*, int); static void queueack(Noconv*, int); static void nonetiput(Queue*, Block*); static void nonetoput(Queue*, Block*); static void nonetstclose(Queue*); static void nonetstopen(Queue*, Stream*); extern Qinfo noetherinfo; extern Qinfo nonetinfo; /* * nonet directory and subdirectory */ enum { /* * per conversation */ Naddrqid, Nlistenqid, Nraddrqid, Nruserqid, Nstatsqid, Nchanqid, /* * per noifc */ Ncloneqid, }; Dirtab *nonetdir; Dirtab nosubdir[]={ "addr", {Naddrqid}, 0, 0600, "listen", {Nlistenqid}, 0, 0600, "raddr", {Nraddrqid}, 0, 0600, "ruser", {Nruserqid}, 0, 0600, "stats", {Nstatsqid}, 0, 0600, }; /* * Nonet conversation states (for Noconv.state) */ enum { Cclosed, Copen, Cannounced, Cconnected, Cconnecting, Chungup, Cclosing, }; /* * nonet file system. most of the calls use dev.c to access the nonet * directory and stream.c to access the nonet devices. * create the nonet directory. the files are `clone' and stream * directories '1' to '32' (or whatever conf.noconv is in decimal) */ void nonetreset(void) { int i; /* * allocate the interfaces */ noifc = (Noifc *)ialloc(sizeof(Noifc) * conf.nnoifc, 0); for(i = 0; i < conf.nnoconv; i++) noifc[i].conv = (Noconv *)ialloc(sizeof(Noconv) * conf.nnoconv, 0); /* * create the directory. */ nonetdir = (Dirtab *)ialloc(sizeof(Dirtab) * (conf.nnoconv+1), 0); /* * the circuits */ for(i = 0; i < conf.nnoconv; i++) { sprint(nonetdir[i].name, "%d", i); nonetdir[i].qid.path = CHDIR|STREAMQID(i, Nchanqid); nonetdir[i].qid.vers = 0; nonetdir[i].length = 0; nonetdir[i].perm = 0600; } /* * the clone device */ strcpy(nonetdir[i].name, "clone"); nonetdir[i].qid.path = Ncloneqid; nonetdir[i].qid.vers = 0; nonetdir[i].length = 0; nonetdir[i].perm = 0600; } void nonetinit(void) { } /* * find an noifc and increment its count */ Chan* nonetattach(char *spec) { Noifc *ifc; Chan *c; /* * find an noifc with the same name */ if(*spec == 0) spec = "nonet"; for(ifc = noifc; ifc < &noifc[conf.nnoifc]; ifc++){ lock(ifc); if(strcmp(spec, ifc->name)==0 && ifc->wq) { ifc->ref++; unlock(ifc); break; } unlock(ifc); } if(ifc == &noifc[conf.nnoifc]) error(Enoifc); c = devattach('n', spec); c->dev = ifc - noifc; return c; } /* * up the reference count to the noifc */ Chan* nonetclone(Chan *c, Chan *nc) { Noifc *ifc; c = devclone(c, nc); ifc = &noifc[c->dev]; lock(ifc); ifc->ref++; unlock(ifc); return c; } int nonetwalk(Chan *c, char *name) { if(c->qid.path == CHDIR) return devwalk(c, name, nonetdir, conf.nnoconv+1, devgen); else return devwalk(c, name, nosubdir, Nsubdir, streamgen); } void nonetstat(Chan *c, char *dp) { if(c->qid.path == CHDIR) devstat(c, dp, nonetdir, conf.nnoconv+1, devgen); else if(c->qid.path == Ncloneqid) devstat(c, dp, nonetdir, 1, devgen); else devstat(c, dp, nosubdir, Nsubdir, streamgen); } /* * opening a nonet device allocates a Noconv. Opening the `clone' * device is a ``macro'' for finding a free Noconv and opening * it's ctl file. */ Noconv * nonetopenclone(Chan *c, Noifc *ifc) { Noconv *cp; Noconv *ep; ep = &ifc->conv[conf.nnoconv]; for(cp = &ifc->conv[0]; cp < ep; cp++){ if(cp->state == Cclosed && canqlock(cp)){ if(cp->state != Cclosed){ qunlock(cp); continue; } c->qid.path = CHDIR|STREAMQID(cp-ifc->conv, Nchanqid); devwalk(c, "ctl", 0, 0, streamgen); streamopen(c, &nonetinfo); qunlock(cp); break; } } if(cp == ep) error(Enodev);; return cp; } Chan* nonetopen(Chan *c, int omode) { Stream *s; Noconv *cp; Noifc *ifc; int line; if(c->qid.path & CHDIR){ /* * directories are read only */ if(omode != OREAD) error(Ebadarg); } else switch(STREAMTYPE(c->qid.path)){ case Ncloneqid: /* * get an unused device and open it's control file */ ifc = &noifc[c->dev]; cp = nonetopenclone(c, ifc); break; case Nlistenqid: /* * listen for a call and open the control file for the * channel on which the call arrived. */ line = STREAMID(c->qid.path); ifc = &noifc[c->dev]; if(ifc->conv[line].state != Cannounced) error(Enoannounce); listen(c, ifc); break; case Nraddrqid: /* * read only files */ if(omode != OREAD) error(Ebadarg); break; default: /* * open whatever c points to */ streamopen(c, &nonetinfo); break; } c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; } void nonetcreate(Chan *c, char *name, int omode, ulong perm) { error(Eperm); } void nonetclose(Chan *c) { Noifc *ifc; /* * real closing happens in nonetstclose */ if(c->qid.path != CHDIR) streamclose(c); /* * let go of the multiplexor */ nonetfreeifc(&noifc[c->dev]); } long nonetread(Chan *c, void *a, long n) { int t; Noconv *cp; char stats[256]; /* * pass data/ctl reads onto the stream code */ t = STREAMTYPE(c->qid.path); if(t >= Slowqid) return streamread(c, a, n); if(c->qid.path == CHDIR) return devdirread(c, a, n, nonetdir, conf.nnoconv+1, devgen); if(c->qid.path & CHDIR) return devdirread(c, a, n, nosubdir, Nsubdir, streamgen); cp = &noifc[c->dev].conv[STREAMID(c->qid.path)]; switch(t){ case Nraddrqid: return stringread(c, a, n, cp->raddr); case Naddrqid: return stringread(c, a, n, cp->addr); case Nruserqid: return stringread(c, a, n, cp->ruser); case Nstatsqid: sprint(stats, "sent: %d\nrcved: %d\nrexmit: %d\nbad: %d\n", cp->sent, cp->rcvd, cp->rexmit, cp->bad); return stringread(c, a, n, stats); } error(Eperm); } long nonetwrite(Chan *c, void *a, long n) { int t; int m; char buf[256]; char *field[5]; t = STREAMTYPE(c->qid.path); /* * get data dispatched as quickly as possible */ if(t == Sdataqid) return streamwrite(c, a, n, 0); /* * easier to do here than in nonetoput */ if(t == Sctlqid){ strncpy(buf, a, sizeof buf); m = getfields(buf, field, 5, ' '); if(strcmp(field[0], "connect")==0){ if(m < 2) error(Ebadarg); connect(c, field[1]); } else if(strcmp(field[0], "announce")==0){ announce(c, field[1]); } else if(strcmp(field[0], "accept")==0){ /* ignore */; } else if(strcmp(field[0], "reject")==0){ /* ignore */; } else return streamwrite(c, a, n, 0); return n; } error(Eperm); } void nonetremove(Chan *c) { error(Eperm); } void nonetwstat(Chan *c, char *dp) { error(Eperm); } /* * the device stream module definition */ Qinfo nonetinfo = { nonetiput, nonetoput, nonetstopen, nonetstclose, "nonet" }; /* * store the device end of the stream so that the multiplexor can * send blocks upstream. */ static void nonetstopen(Queue *q, Stream *s) { Noifc *ifc; Noconv *cp; ifc = &noifc[s->dev]; cp = &ifc->conv[s->id]; cp->s = s; cp->ifc = ifc; cp->rq = RD(q); cp->state = Copen; RD(q)->ptr = WR(q)->ptr = (void *)cp; } /* * wait until a hangup is received. * then send a hangup message (until one is received). */ static int ishungup(void *a) { Noconv *cp; cp = (Noconv *)a; return cp->state == Chungup; } static void nonetstclose(Queue *q) { Noconv *cp; Nomsg *mp; int i; cp = (Noconv *)q->ptr; if(waserror()){ cp->rcvcircuit = -1; cp->state = Cclosed; nexterror(); } /* * send hangup messages to the other side * until it hangs up or we get tired. */ if(cp->state >= Cconnected){ sendctlmsg(cp, NO_HANGUP, 1); for(i=0; i<10 && !ishungup(cp); i++){ sendctlmsg(cp, NO_HANGUP, 1); tsleep(&cp->r, ishungup, cp, MSrexmit); } } cp->rcvcircuit = -1; cp->state = Cclosed; poperror(); } /* * send all messages up stream. this should only be control messages */ static void nonetiput(Queue *q, Block *bp) { Noconv *cp; if(bp->type == M_HANGUP){ cp = (Noconv *)q->ptr; cp->state = Chungup; } PUTNEXT(q, bp); } /* * queue a block */ static int windowopen(void *a) { Noconv *cp; cp = (Noconv *)a; return cp->out[cp->next].inuse == 0; } static int acked(void *a) { Nomsg *mp; mp = (Nomsg *)a; return mp->acked; } static void nonetoput(Queue *q, Block *bp) { Noconv *cp; int next; Nomsg *mp; cp = (Noconv *)(q->ptr); /* * do all control functions */ if(bp->type != M_DATA){ freeb(bp); error(Ebadctl); } /* * collect till we see a delim */ qlock(&cp->mlock); if(!putb(q, bp)){ qunlock(&cp->mlock); return; } mp = 0; if(waserror()){ if(mp){ if(mp->first){ freeb(mp->first); mp->first = 0; } mp->inuse = 0; } else qunlock(&cp->mlock); } /* * block till we get a buffer */ while(cp->out[cp->next].inuse) sleep(&cp->r, windowopen, cp); mp = &cp->out[cp->next]; mp->inuse = 1; cp->next = (cp->next+1)%Nnomsg; /* * stick the message in a Nomsg structure */ mp->time = NOW + MSrexmit; mp->first = q->first; mp->last = q->last; mp->len = q->len; mp->mid ^= Nnomsg; mp->acked = 0; /* * init the queue for new messages */ q->len = 0; q->first = q->last = 0; cp->sent++; qunlock(&cp->mlock); /* * wait for acknowledgement */ while(!mp->acked && cp->state!=Chungup){ sendmsg(cp, mp); tsleep(&mp->r, acked, mp, MSrexmit); } /* * free buffer */ freeb(mp->first); mp->first = 0; mp->inuse = 0; wakeup(&cp->r); poperror(); } /* * start a new conversation. start an ack/retransmit process if * none already exists for this circuit. */ void startconv(Noconv *cp, int circuit, char *raddr, int state) { int i; char name[32]; Noifc *ifc; ifc = cp->ifc; /* * allocate the prototype header */ cp->media = allocb(ifc->hsize + NO_HDRSIZE); cp->media->wptr += ifc->hsize + NO_HDRSIZE; cp->hdr = (Nohdr *)(cp->media->rptr + ifc->hsize); /* * fill in the circuit number */ cp->hdr->flag = NO_NEWCALL|NO_ACKME; cp->hdr->circuit[2] = circuit>>16; cp->hdr->circuit[1] = circuit>>8; cp->hdr->circuit[0] = circuit; /* * set the state variables */ cp->state = state; for(i = 1; i < Nnomsg; i++){ cp->in[i].mid = i; cp->in[i].acked = 0; cp->in[i].rem = 0; cp->out[i].mid = i | Nnomsg; cp->out[i].acked = 1; cp->out[i].rem = 0; cp->out[i].inuse = 0; } cp->in[0].mid = Nnomsg; cp->in[0].acked = 0; cp->in[0].rem = 0; cp->out[0].mid = 0; cp->out[0].acked = 1; cp->out[0].rem = 0; cp->first = cp->next = 1; cp->rexmit = cp->bad = cp->sent = cp->rcvd = cp->lastacked = 0; /* * used for demultiplexing */ cp->rcvcircuit = circuit ^ 1; /* * media dependent header */ (*ifc->connect)(cp, raddr); /* * status files */ strncpy(cp->raddr, raddr, sizeof(cp->raddr)); strcpy(cp->ruser, "none"); } /* * announce willingness to take calls */ static void announce(Chan *c, char *addr) { Noconv *cp; cp = (Noconv *)(c->stream->devq->ptr); if(cp->state != Copen) error(Einuse); cp->state = Cannounced; } /* * connect to the destination whose name is pointed to by bp->rptr. * * a service is separated from the destination system by a '!' */ static void connect(Chan *c, char *addr) { Noifc *ifc; Noconv *cp; char *service; char buf[2*NAMELEN+2]; cp = (Noconv *)(c->stream->devq->ptr); if(cp->state != Copen) error(Einuse); ifc = cp->ifc; service = strchr(addr, '!'); if(service){ *service++ = 0; if(strchr(service, ' ')) error(Ebadctl); if(strlen(service) > NAMELEN) error(Ebadctl); } startconv(cp, 2*(cp - ifc->conv), addr, Cconnecting); if(service){ /* * send service name and user name */ cp->hdr->flag |= NO_SERVICE; sprint(buf, "%s %s", service, u->p->pgrp->user); c->qid.path = STREAMQID(STREAMID(c->qid.path), Sdataqid); streamwrite(c, buf, strlen(buf), 1); c->qid.path = STREAMQID(STREAMID(c->qid.path), Sctlqid); } } /* * listen for a call. There can be many listeners, but only one can sleep * on the circular queue at a time. ifc->listenl lets only one at a time into * the sleep. */ static int iscall(void *a) { Noifc *ifc; ifc = (Noifc *)a; return ifc->rptr != ifc->wptr; } static void listen(Chan *c, Noifc *ifc) { Noconv *cp, *ep; Nocall call; int f; char buf[2*NAMELEN+4]; char *user; long n; call.msg = 0; if(waserror()){ if(call.msg) freeb(call.msg); qunlock(&ifc->listenl); nexterror(); } for(;;){ /* * one listener at a time */ qlock(&ifc->listenl); /* * wait for a call */ sleep(&ifc->listenr, iscall, ifc); call = ifc->call[ifc->rptr]; ifc->rptr = (ifc->rptr+1) % Nnocalls; qunlock(&ifc->listenl); /* * make sure we aren't already using this circuit */ ep = &ifc->conv[conf.nnoconv]; for(cp = &ifc->conv[0]; cp < ep; cp++){ if(cp->state>Cannounced && call.circuit==cp->rcvcircuit && strcmp(call.raddr, cp->raddr)==0) break; } if(cp != ep){ freeb(call.msg); call.msg = 0; continue; } /* * get a free channel */ cp = nonetopenclone(c, ifc); c->qid.path = STREAMQID(cp - ifc->conv, Sctlqid); /* * start the protocol and * stuff the connect message into it */ f = ((Nohdr *)(call.msg->rptr))->flag; startconv(cp, call.circuit, call.raddr, Cconnecting); print("rcving %d byte message\n", call.msg->wptr - call.msg->rptr); nonetrcvmsg(cp, call.msg); call.msg = 0; /* * if a service and remote user were specified, * grab them */ if(f & NO_SERVICE){ print("reading service\n"); c->qid.path = STREAMQID(cp - ifc->conv, Sdataqid); n = streamread(c, buf, sizeof(buf)); c->qid.path = STREAMQID(cp - ifc->conv, Sctlqid); print("read %d bytes\n", n); if(n <= 0) error(Ebadctl); buf[n] = 0; print("read %s\n", buf); user = strchr(buf, ' '); if(user){ *user++ = 0; strncpy(cp->ruser, user, NAMELEN); } else strcpy(cp->ruser, "none"); strncpy(cp->addr, buf, NAMELEN); } break; } poperror(); } /* * send a hangup signal up the stream to get all line disciplines * to cease and desist */ static void hangup(Noconv *cp) { Block *bp; Queue *q; cp->state = Chungup; bp = allocb(0); bp->type = M_HANGUP; q = cp->rq; PUTNEXT(q, bp); wakeup(&cp->r); } /* * process a message acknowledgement. if the message * has any xmit buffers queued, free them. */ static void rcvack(Noconv *cp, int mid) { Nomsg *mp; Block *bp; int i; mp = &cp->out[mid & Nmask]; /* * if already acked, ignore */ if(mp->acked || mp->mid != mid) return; /* * wakeup the sender */ mp->acked = 1; wakeup(&mp->r); cp->lastacked = mid; } /* * queue an acknowledgement to be sent. ignore it if we already have Nnomsg * acknowledgements queued. */ static void queueack(Noconv *cp, int mid) { int next; ulong now; now = NOW; next = (cp->anext + 1)&Nmask; if(next != cp->afirst){ cp->ack[cp->anext] = mid; cp->anext = next; } } /* * make a packet header */ Block * mkhdr(Noconv *cp, int rem) { Block *bp; Nohdr *hp; bp = allocb(cp->ifc->hsize + NO_HDRSIZE + cp->ifc->mintu); memcpy(bp->wptr, cp->media->rptr, cp->ifc->hsize + NO_HDRSIZE); bp->wptr += cp->ifc->hsize + NO_HDRSIZE; hp = (Nohdr *)(bp->rptr + cp->ifc->hsize); hp->remain[1] = rem>>8; hp->remain[0] = rem; hp->sum[0] = hp->sum[1] = 0; return bp; } /* * transmit a message. this involves breaking a possibly multi-block message into * a train of packets on the media. * * called by nonetoput(). the qlock(mp) synchronizes these two * processes. */ static void sendmsg(Noconv *cp, Nomsg *mp) { Noifc *ifc; Queue *wq; int msgrem; int pktrem; int n; Block *bp, *pkt, *last; uchar *rptr; ifc = cp->ifc; if(ifc == 0) return; wq = ifc->wq->next; /* * one transmitter at a time */ qlock(&cp->xlock); if(waserror()){ qunlock(&cp->xlock); return; } /* * get the next acknowledge to use if the next queue up * is not full. */ if(cp->afirst != cp->anext && cp->rq->next->len < 16*1024){ cp->hdr->ack = cp->ack[cp->afirst]; cp->afirst = (cp->afirst+1)&Nmask; } cp->hdr->mid = mp->mid; if(ifc->mintu > mp->len) { /* * short message: * copy the whole message into the header block */ last = pkt = mkhdr(cp, mp->len); for(bp = mp->first; bp; bp = bp->next){ memcpy(pkt->wptr, bp->rptr, n = BLEN(bp)); pkt->wptr += n; } memset(pkt->wptr, 0, n = ifc->mintu - mp->len); pkt->wptr += n; } else { /* * long message: * break up the message into noifc packets and send them. * once around this loop for each non-header block generated. */ msgrem = mp->len; pktrem = msgrem > ifc->maxtu ? ifc->maxtu : msgrem; bp = mp->first; if(bp) rptr = bp->rptr; last = pkt = mkhdr(cp, msgrem); while(bp){ /* * if pkt full, send and create new header block */ if(pktrem == 0){ nonetcksum(pkt, ifc->hsize); last->flags |= S_DELIM; (*wq->put)(wq, pkt); last = pkt = mkhdr(cp, -msgrem); pktrem = msgrem > ifc->maxtu ? ifc->maxtu : msgrem; } n = bp->wptr - rptr; if(n > pktrem) n = pktrem; last = last->next = allocb(0); last->rptr = rptr; last->wptr = rptr = rptr + n; msgrem -= n; pktrem -= n; if(rptr >= bp->wptr){ bp = bp->next; if(bp) rptr = bp->rptr; } } } nonetcksum(pkt, ifc->hsize); last->flags |= S_DELIM; (*wq->put)(wq, pkt); mp->time = NOW + MSrexmit; qunlock(&cp->xlock); poperror(); } /* * send a control message (hangup or acknowledgement). */ static void sendctlmsg(Noconv *cp, int flag, int new) { cp->ctl.len = 0; cp->ctl.first = 0; cp->ctl.acked = 0; if(new) cp->ctl.mid = Nnomsg^cp->out[cp->next].mid; else cp->ctl.mid = cp->lastacked; cp->hdr->flag |= flag; sendmsg(cp, &cp->ctl); } /* * receive a message (called by the multiplexor; noetheriput, nofddiiput, ...) */ void nonetrcvmsg(Noconv *cp, Block *bp) { Block *nbp; Nohdr *h; short r; int c; Nomsg *mp; int f; Queue *q; q = cp->rq; /* * grab the packet header, push the pointer past the nonet header */ h = (Nohdr *)bp->rptr; bp->rptr += NO_HDRSIZE; mp = &cp->in[h->mid & Nmask]; r = (h->remain[1]<<8) | h->remain[0]; f = h->flag; /* * if a new call request comes in on a connected channel, hang up the call */ if(h->mid==0 && (f & NO_NEWCALL) && cp->state==Cconnected){ freeb(bp); hangup(cp); return; } /* * ignore old messages and process the acknowledgement */ if(h->mid != mp->mid){ DPRINT("old msg %d instead of %d\n", h->mid, mp->mid); if(r == 0){ rcvack(cp, h->ack); if(f & NO_HANGUP) hangup(cp); } else { if(r>0) queueack(cp, h->mid); cp->bad++; } freeb(bp); return; } if(r>=0){ /* * start of message packet */ if(mp->first){ DPRINT("mp->mid==%d mp->rem==%d buf r==%d\n", mp->mid, mp->rem, r); cp->bad++; freeb(bp); return; } mp->rem = r; } else { /* * a continuation */ if(-r != mp->rem) { DPRINT("mp->mid==%d mp->rem==%d buf r==%d\n", mp->mid, mp->rem, r); cp->bad++; freeb(bp); return; } } /* * take care of packets that were padded up */ mp->rem -= BLEN(bp); if(mp->rem < 0){ if(-mp->rem <= BLEN(bp)){ bp->wptr += mp->rem; mp->rem = 0; } else panic("nonetrcvmsg: short packet"); } putb(mp, bp); /* * if the last chunk - pass it up the stream and wake any * waiting process. * * if not, strip off the delimiter. */ if(mp->rem == 0){ rcvack(cp, h->ack); if(f & NO_ACKME) queueack(cp, h->mid); mp->last->flags |= S_DELIM; PUTNEXT(q, mp->first); mp->first = mp->last = 0; mp->len = 0; cp->rcvd++; /* * cycle bufffer to next expected mid */ mp->mid ^= Nnomsg; /* * stop xmitting the NO_NEWCALL flag */ if(cp->state==Cconnecting && !(f & NO_NEWCALL)) cp->state = Cconnected; } else mp->last->flags &= ~S_DELIM; } /* * noifc */ /* * Create an ifc. */ Noifc * nonetnewifc(Queue *q, Stream *s, int maxtu, int mintu, int hsize, void (*connect)(Noconv *, char *)) { Noifc *ifc; int i; for(ifc = noifc; ifc < &noifc[conf.nnoifc]; ifc++){ if(ifc->ref == 0){ lock(ifc); if(ifc->ref) { /* someone was faster than us */ unlock(ifc); continue; } RD(q)->ptr = WR(q)->ptr = (void *)ifc; for(i = 0; i < conf.nnoconv; i++) ifc->conv[i].rcvcircuit = -1; ifc->maxtu = maxtu - hsize - NO_HDRSIZE; ifc->mintu = mintu - hsize - NO_HDRSIZE; ifc->hsize = hsize; ifc->connect = connect; ifc->name[0] = 0; ifc->wq = WR(q); ifc->ref = 1; unlock(ifc); return ifc; } } error(Enoifc); } /* * Free an noifc. */ void nonetfreeifc(Noifc *ifc) { lock(ifc); ifc->ref--; if(ifc->ref == 0) ifc->wq = 0; unlock(ifc); } /* * calculate the checksum of a list of blocks. ignore the first `offset' bytes. */ int nonetcksum(Block *bp, int offset) { Block *nbp = bp; uchar *ep, *p; int n; ulong s; Nohdr *hp; s = 0; p = bp->rptr + offset; n = bp->wptr - p; hp = (Nohdr *)p; hp->sum[0] = hp->sum[1] = 0; for(;;){ ep = p+(n&~0x7); while(p < ep) { s = s + s + p[0]; s = s + s + p[1]; s = s + s + p[2]; s = s + s + p[3]; s = s + s + p[4]; s = s + s + p[5]; s = s + s + p[6]; s = s + s + p[7]; s = (s&0xffff) + (s>>16); p += 8; } ep = p+(n&0x7); while(p < ep) { s = s + s + *p; p++; } s = (s&0xffff) + (s>>16); bp = bp->next; if(bp == 0) break; p = bp->rptr; n = BLEN(bp); } s = (s&0xffff) + (s>>16); hp->sum[1] = s>>8; hp->sum[0] = s; return s & 0xffff; } . ## diffname port/devnonet.c 1990/1214 ## diff -e /n/bootesdump/1990/1210/sys/src/9/port/devnonet.c /n/bootesdump/1990/1214/sys/src/9/port/devnonet.c 1192d 961a SET(rptr); . 871d 869d 255c nonetopenclone(c, ifc); . 239d ## diffname port/devnonet.c 1990/1229 ## diff -e /n/bootesdump/1990/1214/sys/src/9/port/devnonet.c /n/bootesdump/1990/1229/sys/src/9/port/devnonet.c 1229a } nonettoggle() { pnonet ^= 1; . 1042a DPRINT("new call on connected channel\n"); . 105c for(i = 0; i < conf.nnoifc; i++) . 18c MSrexmit = 500, /* retranmission interval in ms */ . 12a int pnonet; . 9c #define DPRINT if(pnonet)print . ## diffname port/devnonet.c 1990/1231 ## diff -e /n/bootesdump/1990/1229/sys/src/9/port/devnonet.c /n/bootesdump/1990/1231/sys/src/9/port/devnonet.c 1061c sendack(cp, h->mid); . 1015a * send an acknowledgement */ static void sendack(Noconv *cp, int ack) { cp->ackmsg.len = 0; cp->ackmsg.first = 0; cp->ackmsg.acked = ack; cp->ackmsg.mid = cp->lastacked; sendmsg(cp, &cp->ctl); } /* . 783a print("call from %d %s\n", call.circuit, call.raddr); . 707a print("request sent\n"); . 706a print("sending request\n"); . 39a static void sendack(Noconv*, int); . ## diffname port/devnonet.c 1991/0102 ## diff -e /n/bootesdump/1990/1231/sys/src/9/port/devnonet.c /n/bootesdump/1991/0102/sys/src/9/port/devnonet.c 1077,1078c if(r>0){ queueack(cp, h->mid); sendctlmsg(cp, 0, 0); } . 1020,1032d 1016c sendmsg(cp, &ctl); . 1014c ctl.mid = cp->lastacked; . 1012c ctl.mid = Nnomsg^cp->out[cp->next].mid; . 1008,1010c Nomsg ctl; ctl.len = 0; ctl.first = 0; ctl.acked = 0; . 924c * one transmitter at a time for this connection . 40d ## diffname port/devnonet.c 1991/0108 ## diff -e /n/bootesdump/1991/0102/sys/src/9/port/devnonet.c /n/bootesdump/1991/0108/sys/src/9/port/devnonet.c 1244a . 1240a /* * send acknowledges that need to be sent. this happens at 1/2 * the retransmission interval. */ static void nonetkproc(void *arg) { Noifc *ifc; Noconv *cp, *ep; cp = 0; ifc = 0; if(waserror()){ if(ifc) unlock(ifc); if(cp) qunlock(cp); } loop: for(ifc = noifc; ifc < &noifc[conf.nnoifc]; ifc++){ if(ifc->wq==0 || !canlock(ifc)) continue; ep = ifc->conv + conf.nnoconv; for(cp = ifc->conv; cp < ep; cp++){ if(cp->state==Cclosed || !canqlock(cp)) continue; if(cp->afirst != cp->anext){ DPRINT("sending ack %d\n", cp->ack[cp->afirst]); sendctlmsg(cp, 0, 0); } qunlock(cp); } unlock(ifc); } tsleep(&nonetkr, return0, 0, MSrexmit/2); goto loop; } . 1067d 1065a rcvack(cp, h->ack); . 1059c DPRINT("old msg %d instead of %d r==%d\n", h->mid, mp->mid, r); . 805d 801d 797c DPRINT("reading service\n"); . 788c DPRINT("rcving %d byte message\n", call.msg->wptr - call.msg->rptr); . 786c DPRINT("call from %d %s\n", call.circuit, call.raddr); . 709c DPRINT("request sent\n"); . 707c DPRINT("sending request\n"); . 578a if(retries++ > 100) errors("to many nonet rexmits"); . 575a retries = 0; . 513a int retries; . 470a qunlock(cp); . 468a qlock(cp); . 242a if(!kstarted){ kproc("nonetack", nonetkproc, 0); kstarted = 1; } . 166a . 91a * nonet kproc */ static int kstarted; static Rendez nonetkr; /* . 40c static void nonetkproc(void*); . 19c MSrexmit = 250, /* retranmission interval in ms */ . ## diffname port/devnonet.c 1991/0109 ## diff -e /n/bootesdump/1991/0108/sys/src/9/port/devnonet.c /n/bootesdump/1991/0109/sys/src/9/port/devnonet.c 606d 597a poperror(); . 596c errors("too many nonet rexmits"); . 557,558c } qunlock(&cp->mlock); nexterror(); . ## diffname port/devnonet.c 1991/0112 ## diff -e /n/bootesdump/1991/0109/sys/src/9/port/devnonet.c /n/bootesdump/1991/0112/sys/src/9/port/devnonet.c 784c if(cp->state>Cannounced && (call.circuit^1)==cp->rcvcircuit . ## diffname port/devnonet.c 1991/01151 ## diff -e /n/bootesdump/1991/0112/sys/src/9/port/devnonet.c /n/bootesdump/1991/01151/sys/src/9/port/devnonet.c 1297c void nonettoggle(void) . 1284a if(cp->state == Cclosed){ qunlock(cp); continue; } /* * resend the first message */ if(cp->first!=cp->next && cp->out[cp->first].time>=NOW){ if(cp->rexmit++ > 100){ print("hanging up\n"); hangup(cp); } else sendmsg(cp, &(cp->out[cp->first])); } /* * resend an acknowledge */ . 1280a /* * loop through all active conversations */ . 1277a /* * loop through all active interfaces */ . 1108c DPRINT("mp->mid==%d mp->rem==%d r==%d\n", mp->mid, mp->rem, r); . 1097,1100c DPRINT("mp->mid==%d mp->rem==%d r==%d\n", mp->mid, mp->rem, r); freeb(mp->first); mp->first = mp->last = 0; mp->len = 0; . 878a freeb(mp->first); mp->first = 0; mp->inuse = 0; /* * advance first if this is the first */ if((mid&Nmask) == cp->first){ while(cp->first != cp->next){ if(cp->out[cp->first].acked == 0) break; cp->first = (cp->first+1) % Nnomsg; } } . 877d 875a cp->rexmit = 0; . 874c * free it . 600,607d 592,598c sendmsg(cp, mp); qunlock(&cp->mlock); . 590c * send the message, the kproc will retry . 587d 556a mp->acked = 0; if(((cp->first+1)%Nnomsg) == cp->next) cp->first = cp->next; . 551a q->len = 0; q->first = q->last = 0; . 520c return mp->inuse; . ## diffname port/devnonet.c 1991/0118 ## diff -e /n/bootesdump/1991/01151/sys/src/9/port/devnonet.c /n/bootesdump/1991/0118/sys/src/9/port/devnonet.c 1309,1310c } else { mp = &(cp->out[cp->first]); sendmsg(cp, mp); } . 1305,1306c if(cp->first!=cp->next && NOW>=cp->out[cp->first].time){ if(cp->rexmit++ > 60){ . 1271a Nomsg *mp; . 1073c if(cp->state != Csuperceded){ cp->state = Csuperceded; hangup(cp); } . 1070c if(h->mid==0 && (f & NO_NEWCALL) && (cp->state==Cconnected || cp->state==Csuperceded)){ . 1018d 1016a if(cp->rexmit > 10) mp->time = NOW + 10*MSrexmit; else mp->time = NOW + (cp->rexmit+1)*MSrexmit; DPRINT("xmit %d %lud %lud\n", cp->rexmit, NOW, mp->time); . 1013a /* * round up last packet to mintu */ if(n < ifc->mintu){ n = ifc->mintu - n; last = last->next = allocb(n); memset(last->wptr, 0, n); last->wptr += n; } . 988a n = 0; . 974c /* * round up to mintu */ memset(pkt->wptr, 0, n = ifc->mintu-mp->len); . 963a /* * package n blocks into m packets. make sure * no packet is < mintu or > maxtu in length. */ . 473c if(cp->state>=Cconnected && cp->state!=Csuperceded){ . 88a Csuperceded, . ## diffname port/devnonet.c 1991/0119 ## diff -e /n/bootesdump/1991/0118/sys/src/9/port/devnonet.c /n/bootesdump/1991/0119/sys/src/9/port/devnonet.c 1347c nosendctl(cp, 0, 0); . 1338c nosend(cp, mp); . 1335c nohangup(cp); . 1294c nokproc(void *arg) . 1189a . 1184a /* * hangup (after processing message) */ if(f & NO_RESET){ DPRINT("reset with message\n"); noreset(cp); } else if(f & NO_HANGUP){ DPRINT("hangup with message\n"); nohangup(cp); } . 1183c if(cp->state==Cconnecting && !(f&NO_NEWCALL)) . 1181c * any NO_NEWCALL after this is another call . 1168c noqack(cp, h->mid); . 1166c cp->hdr->flag &= ~(NO_NEWCALL|NO_SERVICE); norack(cp, h->ack); . 1114,1115c norack(cp, h->ack); noqack(cp, h->mid); . 1109,1111c norack(cp, h->ack); if(f & NO_RESET) noreset(cp); else if(f & NO_HANGUP) nohangup(cp); . 1096,1099c noreset(cp); . 1092,1093c if((f&NO_NEWCALL) && cp->state==Cconnected){ . 1065a * * State Transition: (no NO_NEWCALL in msg) Cconnecting -> Cconnected . 1061c nosend(cp, &ctl); . 1049c nosendctl(Noconv *cp, int flag, int new) . 1039d 1006c last = pkt = nohdr(cp, -msgrem); . 996c last = pkt = nohdr(cp, msgrem); . 974c last = pkt = nohdr(cp, mp->len); . 930c nosend(Noconv *cp, Nomsg *mp) . 926c * called by nooput(). the qlock(mp) synchronizes these two . 907c nohdr(Noconv *cp, int rem) . 892c noqack(Noconv *cp, int mid) . 851c norack(Noconv *cp, int mid) . 846a * send a hangup signal up the stream to get all line disciplines * to cease and desist. The Creset state makes any subsequent close not * send hangup messages. * * State Transition: {Cconnected, Cconnecting} -> Creset */ static void noreset(Noconv *cp) { Block *bp; Queue *q; switch(cp->state){ case Cconnected: case Cconnecting: cp->state = Creset; bp = allocb(0); bp->type = M_HANGUP; q = cp->rq; PUTNEXT(q, bp); break; } wakeup(&cp->r); } /* . 838,842c switch(cp->state){ case Cconnected: case Cconnecting: cp->state = Chungup; bp = allocb(0); bp->type = M_HANGUP; q = cp->rq; PUTNEXT(q, bp); break; } . 833c nohangup(Noconv *cp) . 830a * * State Transition: {Cconnected, Cconnecting} -> Chungup . 798c nostartconv(cp, call.circuit, call.raddr, Cconnecting); . 739c nolisten(Chan *c, Noifc *ifc) . 728a * * State Transition: Cclosed -> Copen -> Cconnecting . 720d 718d 709c nostartconv(cp, 2*(cp - ifc->conv), addr, Cconnecting); . 689c noconnect(Chan *c, char *addr) . 686a * * State Transition: Copen -> Cconnecting . 673c noannounce(Chan *c, char *addr) . 670a * * State Transition: Copen -> Chungup . 650c cp->rexmit = cp->bad = cp->sent = cp->rcvd = 0; cp->lastacked = Nnomsg|(Nnomsg-1); . 607c nostartconv(Noconv *cp, int circuit, char *raddr, int state) . 597c nosend(cp, mp); . 524c nooput(Queue *q, Block *bp) . 493c noiput(Queue *q, Block *bp) . 490a * * State Transition: (on M_HANGUP) * -> Chungup . 479a break; case Chungup: /* * ack any close */ nosendctl(cp, NO_HANGUP, 1); break; . 477c nosendctl(cp, NO_HANGUP, 1); . 474,475c switch(cp->state){ case Cconnected: /* * send close till we get one back */ nosendctl(cp, NO_HANGUP, 1); . 456c noclose(Queue *q) . 453c switch(cp->state){ case Chungup: case Creset: case Cclosed: return 1; } return 0; . 445a * * State Transitions: * -> Cclosed . 429c noopen(Queue *q, Stream *s) . 426a * * State Transition: Cclosed -> Copen . 417,420c noiput, nooput, noopen, noclose, . 387c noannounce(c, field[1]); . 385c noconnect(c, field[1]); . 377c * easier to do here than in nooput . 314c * real closing happens in noclose . 279c nolisten(c, ifc); . 252c kproc("nonetack", nokproc, 0); . 88,89c Creset, . 30,44c static void nohangup(Noconv*); static void noreset(Noconv*); static Block* nohdr(Noconv*, int); static void nolisten(Chan*, Noifc*); static void noannounce(Chan*, char*); static void noconnect(Chan*, char*); static void norack(Noconv*, int); static void nosendctl(Noconv*, int, int); static void nosend(Noconv*, Nomsg*); static void nostartconv(Noconv*, int, char*, int); static void noqack(Noconv*, int); static void nokproc(void*); static void noiput(Queue*, Block*); static void nooput(Queue*, Block*); static void noclose(Queue*); static void noopen(Queue*, Stream*); . ## diffname port/devnonet.c 1991/0206 ## diff -e /n/bootesdump/1991/0119/sys/src/9/port/devnonet.c /n/bootesdump/1991/0206/sys/src/9/port/devnonet.c 1418c while(cp->afirst != cp->anext){ . 1416c * get the acknowledges out . 1412d 1409,1410c } else . 1407c norack(cp, mp->mid); . 1405a mp = &(cp->out[cp->first]); . 944a wakeup(&cp->r); . 943c cp->first = MSUCC(cp->first); . 934d 931a mp->acked = 1; . 930d 664d 621c qunlock(cp); . 619a if(waserror()){ /* throw out the message */ freeb(mp->first); mp->first = 0; mp->acked = 0; if(MSUCC(cp->first) == cp->next) cp->first = cp->next; qunlock(cp); nexterror(); } . 613c q->len = q->nb = 0; . 611c * take the message out of the queue . 601c * point the output buffer to the message . 597,598c cp->next = MSUCC(cp->next); qlock(cp); qunlock(&cp->mlock); poperror(); . 590,594c while(!windowopen(cp)) . 575,586c /* throw out the message */ while(bp = getb(q)) freeb(bp); . 573c /* * block till we get an output buffer */ . 538,545d 536c return MSUCC(cp->next) != cp->first; . 506a . 503a /* * we give up, ack any unacked messages */ for(i = cp->first; i != cp->next; i = MSUCC(i)) norack(cp, cp->out[i].mid); . 10a #define MSUCC(x) (((x)+1)%Nnomsg) . ## diffname port/devnonet.c 1991/0207 ## diff -e /n/bootesdump/1991/0206/sys/src/9/port/devnonet.c /n/bootesdump/1991/0207/sys/src/9/port/devnonet.c 1416c while(cp->afirst!=cp->anext && cp->rq->next->len<16*1024){ . 543c i = cp->next - cp->first; if(i>=0 && i<32) return 1; if(i<0 && Nnomsg+i<32) return 1; return 0; . 540a int i; . ## diffname port/devnonet.c 1991/0209 ## diff -e /n/bootesdump/1991/0207/sys/src/9/port/devnonet.c /n/bootesdump/1991/0209/sys/src/9/port/devnonet.c 1414c noreset(cp); . 1412c if(cp->rexmit++ > 15){ . 1106,1107d 1025c if(cp->afirst!=cp->anext && cp->rq->next->len<16*1024){ . 1012,1021d 492c nosendctl(cp, NO_HANGUP, 0); . ## diffname port/devnonet.c 1991/0316 ## diff -e /n/bootesdump/1991/0209/sys/src/9/port/devnonet.c /n/bootesdump/1991/0316/sys/src/9/port/devnonet.c 279c errors("channel not announced"); . ## diffname port/devnonet.c 1991/0318 ## diff -e /n/bootesdump/1991/0316/sys/src/9/port/devnonet.c /n/bootesdump/1991/0318/sys/src/9/port/devnonet.c 1094a . 1032c memmove(pkt->wptr, bp->rptr, n = BLEN(bp)); . 984a . 979c memmove(bp->wptr, cp->media->rptr, cp->ifc->hsize + NO_HDRSIZE); . ## diffname port/devnonet.c 1991/0320 ## diff -e /n/bootesdump/1991/0318/sys/src/9/port/devnonet.c /n/bootesdump/1991/0320/sys/src/9/port/devnonet.c 1150c print("new call on connected channel\n"); . 465a /* * wait until a hangup is received. * then send a hangup message (until one is received). * * State Transitions: * -> Cclosed */ . 446,451c . ## diffname port/devnonet.c 1991/0328 ## diff -e /n/bootesdump/1991/0320/sys/src/9/port/devnonet.c /n/bootesdump/1991/0328/sys/src/9/port/devnonet.c 1246,1249c if(f & NO_HANGUP){ . 1164,1166c if(f & NO_HANGUP) . 1157a * A new call request (maybe), treat it as a reset if seen on a * connected, hungup, or reset channel. * * On a connecting channel, treat as a reset if this is an * invalid message ID. */ if(f & NO_NEWCALL){ switch(cp->state){ case Cclosed: case Copen: case Cannounced: case Creset: panic("nonetrcvmsg %d %d\n", cp->rcvcircuit, cp - cp->ifc->conv); case Chungup: case Cconnected: print("Nonet call on connected/hanging-up circ %d conv %d\n", cp->rcvcircuit, cp - cp->ifc->conv); freeb(bp); noreset(cp); return; case Cconnecting: if(h->mid != mp->mid){ print("Nonet call on connecting circ %d conv %d\n", cp->rcvcircuit, cp - cp->ifc->conv); freeb(bp); noreset(cp); return; } break; } } /* . 1153a freeb(bp); . 1150,1152c if(f & NO_RESET){ print("reset received\n"); . 1148c * Obey reset even if the message id is bogus . 904c cp->rcvcircuit = -1; bp = allocb(0); . 902a case Chungup: print("resetting connection\n"); . 892c * State Transition: {Cconnected, Cconnecting, Chungup} -> Creset . 888,890c * Send a hangup signal up the stream to get all line disciplines * to cease and desist. Disassociate this conversation from a circuit * number. Any subsequent close of the conversation will * not send hangup messages. . 512a if(cp->media){ freeb(cp->media); cp->media = 0; } . 7a #include "../port/nonet.h" . ## diffname port/devnonet.c 1991/0411 ## diff -e /n/bootesdump/1991/0328/sys/src/9/port/devnonet.c /n/bootesdump/1991/0411/sys/src/9/port/devnonet.c 363c nonetwrite(Chan *c, void *a, long n, ulong offset) . 357c return stringread(c, a, n, stats, offset); . 353c return stringread(c, a, n, cp->ruser, offset); . 351c return stringread(c, a, n, cp->addr, offset); . 349c return stringread(c, a, n, cp->raddr, offset); . 328c nonetread(Chan *c, void *a, long n, ulong offset) . ## diffname port/devnonet.c 1991/0412 ## diff -e /n/bootesdump/1991/0411/sys/src/9/port/devnonet.c /n/bootesdump/1991/0412/sys/src/9/port/devnonet.c 211c devstat(c, dp, &nonetdir[conf.nnoconv], 1, devgen); . ## diffname port/devnonet.c 1991/0413 ## diff -e /n/bootesdump/1991/0412/sys/src/9/port/devnonet.c /n/bootesdump/1991/0413/sys/src/9/port/devnonet.c 1430c if(cp->state <= Copen){ . 1428c if(cp->state<=Copen || !canqlock(cp)) . 682a cp->afirst = cp->anext = 0; . 85,91c Cclosed= 0, Copen= 1, Cannounced= 2, Cconnected= 3, Cconnecting= 4, Chungup= 5, Creset= 6, . ## diffname port/devnonet.c 1991/0419 ## diff -e /n/bootesdump/1991/0413/sys/src/9/port/devnonet.c /n/bootesdump/1991/0419/sys/src/9/port/devnonet.c 204a Chan* nonetclwalk(Chan *c, char *name) { return devclwalk(c, name); } . ## diffname port/devnonet.c 1991/0427 ## diff -e /n/bootesdump/1991/0419/sys/src/9/port/devnonet.c /n/bootesdump/1991/0427/sys/src/9/port/devnonet.c 205,210d ## diffname port/devnonet.c 1991/0502 ## diff -e /n/bootesdump/1991/0427/sys/src/9/port/devnonet.c /n/bootesdump/1991/0502/sys/src/9/port/devnonet.c 1393c s &= 0xffff; switch(s){ case 0xac9f: case 0xc1a4: case 0xc41c: case 0xc46d: { int i; print("%lux s,", s); for(bp = first; bp; bp = bp->next) for(i = 0; i < BLEN(bp); i++) print(" %ux", bp->rptr[i]); } } return s; . 1357a Block *first; . 553c if(i<0 && Nnomsg+i=0 && irexmit++ > 15){ . ## diffname port/devnonet.c 1991/0606 ## diff -e /n/bootesdump/1991/0604/sys/src/9/port/devnonet.c /n/bootesdump/1991/0606/sys/src/9/port/devnonet.c 1472c nosendctl(cp, NO_NULL, 0); . 1207c if(h->mid!=mp->mid || (f&NO_NULL)){ . ## diffname port/devnonet.c 1991/0608 ## diff -e /n/bootesdump/1991/0606/sys/src/9/port/devnonet.c /n/bootesdump/1991/0608/sys/src/9/port/devnonet.c 1472c nosendctl(cp, /*NO_NULL*/0, 0); . 1463c } else . 1460c if(cp->rexmit++ > 15){ . 1268a noqack(cp, h->mid); . 1194c DPRINT("Nonet call on connecting circ %d conv %d\n", . 1187c DPRINT("Nonet call on connected/hanging-up circ %d conv %d\n", . 1184c DPRINT("nonetrcvmsg %d %d\n", cp->rcvcircuit, cp - cp->ifc->conv); freeb(bp); return; . 1165c DPRINT("reset received\n"); . 915d ## diffname port/devnonet.c 1991/0904 ## diff -e /n/bootesdump/1991/0608/sys/src/9/port/devnonet.c /n/bootesdump/1991/0904/sys/src/9/port/devnonet.c 951c if(mp->first) freeb(mp->first); . ## diffname port/devnonet.c 1991/0925 ## diff -e /n/bootesdump/1991/0904/sys/src/9/port/devnonet.c /n/bootesdump/1991/0925/sys/src/9/port/devnonet.c 638d 636d 626,634c if(!waserror()){ nosend(cp, mp); poperror(); . ## diffname port/devnonet.c 1991/0926 ## diff -e /n/bootesdump/1991/0925/sys/src/9/port/devnonet.c /n/bootesdump/1991/0926/sys/src/9/port/devnonet.c 1473,1474d 1471c tsleep(&nonetkr, return0, 0, MSrexmit/2); . 1461,1469c unlock(ifc); . 1453,1459c ep = ifc->conv + conf.nnoconv; for(cp = ifc->conv; cp < ep; cp++){ if(cp->state<=Copen || !canqlock(cp)) continue; if(cp->state <= Copen){ qunlock(cp); continue; } /* * resend the first message */ if(cp->first!=cp->next && NOW>=cp->out[cp->first].time){ mp = &(cp->out[cp->first]); if(cp->rexmit++ > 15){ norack(cp, mp->mid); noreset(cp); } else nosend(cp, mp); } /* * get the acknowledges out */ while(cp->afirst!=cp->anext && cp->rq->next->len<16*1024){ DPRINT("sending ack %d\n", cp->ack[cp->afirst]); nosendctl(cp, /*NO_NULL*/0, 0); } qunlock(cp); . 1451c * loop through all active conversations . 1445,1449c . 1441,1443c for(ifc = noifc; ifc < &noifc[conf.nnoifc]; ifc++){ if(ifc->wq==0 || !canlock(ifc)) . 1439c * loop through all active interfaces . 1430,1437c for(;;){ . 616,620d 610,612c mp->first = first; mp->last = last; mp->len = len; . 592,594c freeb(first); . 588a * take the collected message out of the queue */ first = q->first; last = q->last; len = q->len; q->len = q->nb = 0; q->first = q->last = 0; if(len == 0){ freeb(first); qunlock(&cp->mlock); return; } /* . 567c Block *first, *last; int len; . ## diffname port/devnonet.c 1991/1101 ## diff -e /n/bootesdump/1991/0926/sys/src/9/port/devnonet.c /n/bootesdump/1991/1101/sys/src/9/port/devnonet.c 1473,1474c if(cp->sendack){ DPRINT("sending ack %d\n", cp->ack); . 1271d 1031,1034c cp->sendack = 0; cp->hdr->ack = cp->ack; . 975,981c cp->ack = mid; cp->sendack = 1; . 687c cp->ack = 0; cp->sendack = 0; . 22d ## diffname port/devnonet.c 1991/1105 ## diff -e /n/bootesdump/1991/1101/sys/src/9/port/devnonet.c /n/bootesdump/1991/1105/sys/src/9/port/devnonet.c 760c sprint(buf, "%s %s", service, u->p->user); . ## diffname port/devnonet.c 1991/1112 ## diff -e /n/bootesdump/1991/1105/sys/src/9/port/devnonet.c /n/bootesdump/1991/1112/sys/src/9/port/devnonet.c 1471c nonetfreeifc(ifc); . 1436a lock(ifc); if(ifc->wq==0){ unlock(ifc); continue; } ifc->ref++; unlock(ifc); . 1435c if(ifc->wq==0) . 140c nonetdir[i].perm = 0666; . 130c nonetdir[i].perm = 0777; . 73,77c "addr", {Naddrqid}, 0, 0666, "listen", {Nlistenqid}, 0, 0666, "raddr", {Nraddrqid}, 0, 0666, "ruser", {Nruserqid}, 0, 0666, "stats", {Nstatsqid}, 0, 0666, . ## diffname port/devnonet.c 1991/1114 ## diff -e /n/bootesdump/1991/1112/sys/src/9/port/devnonet.c /n/bootesdump/1991/1114/sys/src/9/port/devnonet.c 1480c tsleep(&nonetkr, return0, 0, MSrexmit); . ## diffname port/devnonet.c 1991/1115 ## diff -e /n/bootesdump/1991/1114/sys/src/9/port/devnonet.c /n/bootesdump/1991/1115/sys/src/9/port/devnonet.c 1420a USED(arg); . 409a USED(c, dp); . 403a USED(c); . 356c return stringread(a, n, stats, offset); . 352c return stringread(a, n, cp->ruser, offset); . 350c return stringread(a, n, cp->addr, offset); . 348c return stringread(a, n, cp->raddr, offset); . 305a USED(c, name, omode, perm); . ## diffname port/devnonet.c 1991/1121 ## diff -e /n/bootesdump/1991/1115/sys/src/9/port/devnonet.c /n/bootesdump/1991/1121/sys/src/9/port/devnonet.c 1456c if(cp->state != Cconnected && cp->state != Cconnecting){ . 1295c return 0; } . 1293c return r; } else { . 1291a return -1; . 1270a r = mp->len; . 1241c return -1; . 1219c return -1; . 1191,1197d 1189c return -1; . 1182c return -1; . 1164c return -1; . 1135c int . 849,868c switch(nonetrcvmsg(cp, bp)){ case -1: print("bad call message"); streamclose(c); continue; case 0: if(f & NO_SERVICE){ streamclose(c); print("bad call message"); continue; } break; default: if(f & NO_SERVICE){ c->qid.path = STREAMQID(cp - ifc->conv, Sdataqid); n = streamread(c, buf, sizeof(buf)); c->qid.path = STREAMQID(cp - ifc->conv, Sctlqid); if(n <= 0) error(Ebadctl); buf[n] = 0; user = strchr(buf, ' '); if(user){ *user++ = 0; strncpy(cp->ruser, user, NAMELEN); } else strcpy(cp->ruser, "none"); strncpy(cp->addr, buf, NAMELEN); } break; . 846,847c bp = call.msg; . 844d 793a Block *bp; . 521,522d 511a qlock(cp); . 508d 504,505c switch(cp->state){ case Cconnecting: case Cconnected: /* * send close till we get one back */ nosendctl(cp, NO_HANGUP, 1); for(i=0; i<10 && !ishungup(cp); i++){ nosendctl(cp, NO_HANGUP, 0); tsleep(&cp->r, ishungup, cp, MSrexmit); } break; case Chungup: /* * ack any close */ nosendctl(cp, NO_HANGUP, 1); break; } poperror(); . 502c * send hangup messages to the other side * until it hangs up or we get tired. . 494,500c while(!isempty(cp)) tsleep(&cp->r, isempty, cp, MSrexmit); . 492c * wait till we have nothing to transmit . 479,490c if(!waserror()){ . 464,469c static int isempty(void *a) { Noconv *cp; cp = (Noconv *)a; switch(cp->state){ case Cconnecting: case Cconnected: return cp->first == cp->next; default: return 1; } } . 449c /* * wait until a hangup is received. * then send a hangup message (until one is received). * * State Transitions: * -> Cclosed */ . 315,318c if(c->stream) . ## diffname port/devnonet.c 1992/0111 ## diff -e /n/bootesdump/1991/1121/sys/src/9/port/devnonet.c /n/bootesdump/1992/0111/sys/src/9/port/devnonet.c 7c #include "../port/error.h" . ## diffname port/devnonet.c 1992/0113 ## diff -e /n/bootesdump/1992/0111/sys/src/9/port/devnonet.c /n/bootesdump/1992/0113/sys/src/9/port/devnonet.c 279c error(Enolisten); . 241c error(Enodev); . ## diffname port/devnonet.c 1992/0129 ## diff -e /n/bootesdump/1992/0113/sys/src/9/port/devnonet.c /n/bootesdump/1992/0129/sys/src/9/port/devnonet.c 379c if(n > sizeof buf - 1) n = sizeof buf - 1; strncpy(buf, a, n); buf[n] = '\0'; . ## diffname port/devnonet.c 1992/0219 # deleted ## diff -e /n/bootesdump/1992/0129/sys/src/9/port/devnonet.c /n/bootesdump/1992/0219/sys/src/9/port/devnonet.c 1,1513d