## diffname port/sturp.c 1990/0227 ## diff -e /dev/null /n/bootesdump/1990/0227/sys/src/9/mips/sturp.c 0a #include "syslibc.h" #include "lock.h" #include "chan.h" #include "proc.h" #include "user.h" #include "errno.h" #include "lint.h" #include "mem.h" #include "mempool.h" #include "stream.h" #include "dkparam.h" #include "misc.h" enum { Nurp= 32, MSrexmit= 1000, }; typedef struct Urp Urp; /* * URP status */ struct urpstat { ulong input; /* bytes read from urp */ ulong output; /* bytes output to urp */ ulong rxmit; /* retransmit rejected urp msg */ ulong rjtrs; /* reject, trailer size */ ulong rjpks; /* reject, packet size */ ulong rjseq; /* reject, sequence number */ ulong levelb; /* unknown level b */ ulong enqsx; /* enqs sent */ ulong enqsr; /* enqs rcved */ } urpstat; struct Urp { Qlock; short state; /* flags */ /* input */ ulong iwindow; /* input window */ uchar iseq; /* last good input sequence number */ uchar lastecho; /* last echo/rej sent */ uchar trbuf[3]; /* trailer being collected */ short trx; /* # bytes in trailer being collected */ /* output */ Queue *rq; Queue *wq; int XW; /* blocks per xmit window */ int maxblock; /* max block size */ int timeout; /* a timeout has occurred */ int WS; /* start of current window */ int WACK; /* first non-acknowledged message */ int WNX; /* next message to be sent */ Rendez r; /* process waiting in urpoput */ Rendez kr; /* process waiting in urpoput */ Block *xb[8]; /* the xmit window buffer */ uchar timer; /* timeout for xmit */ }; #define WINDOW(u) ((u->WS + u->XW - u->WNX)%8) #define BETWEEN(x, s, n) (s<=n ? x>=s && x=s) #define UNACKED(x, u) (BETWEEN(x, u->WACK, u->WNX) /* * Protocol control bytes */ #define SEQ 0010 /* sequence number, ends trailers */ #undef ECHO #define ECHO 0020 /* echos, data given to next queue */ #define REJ 0030 /* rejections, transmission error */ #define ACK 0040 /* acknowledgments */ #define BOT 0050 /* beginning of trailer */ #define BOTM 0051 /* beginning of trailer, more data follows */ #define BOTS 0052 /* seq update algorithm on this trailer */ #define SOU 0053 /* start of unsequenced trailer */ #define EOU 0054 /* end of unsequenced trailer */ #define ENQ 0055 /* xmitter requests flow/error status */ #define CHECK 0056 /* xmitter requests error status */ #define INITREQ 0057 /* request initialization */ #define INIT0 0060 /* disable trailer processing */ #define INIT1 0061 /* enable trailer procesing */ #define AINIT 0062 /* response to INIT0/INIT1 */ #undef DELAY #define DELAY 0100 /* real-time printing delay */ #define BREAK 0110 /* Send/receive break (new style) */ #define REXMITING 0001 #define REXMIT 0002 #define INITING 0004 Urp urp[Nurp]; /* * predeclared */ static void urpiput(Queue*, Block*, Rendez*); static void urpoput(Queue*, Block*, Rendez*); static void urpopen(Queue*, Stream*); static void urpclose(Queue *); static void rcvack(Urp*, int); static void flushinput(Urp*); static void sendctl(Queue*, int); static void queuectl(Urp*, int); static void initoutput(Urp*, int); static void initinput(Urp*, int); Qinfo urpinfo = { urpiput, urpoput, urpopen, urpclose, "urp" }; int urpopen(Queue *q, Stream *s) { Urp *up; int i; /* * find a free urp structure */ for(up = urp; up < &urp[Nurp]; up++){ qlock(up); if(up->state == 0) break; qunlock(up); } if(up == &urp[Nurp]) error(0, Egreg); q->ptr = = q->other->ptr = up; up->rq = q; up->wq = WR(q); q->put = urpciput; qunlock(up); initinput(up, 0); initoutput(up, 0); } /* * Shut it down. */ static int allacked(void *a) { Urp *up; up = (Urp *)a; return up->WACK == up->WNX; } urpclose(Queue *q) { Block *bp; Urp *up; int i; up = (Urp *)q->ptr; up->state |= LCLOSE; /* * wait for output to get acked */ while(!urpdone(up)) sleep(&up->r, urpdone, up); up->state = 0; } /* * upstream control messages */ static void urpctliput(Urp *up, Queue *q, Block *bp) { switch(bp->type){ case M_HANGUP: /* * ack all outstanding messages */ lock(up); up->state &= ~(INITING); up->state |= RCLOSE; unlock(up); if(up->WSWNX) urprack(up, ECHO+((up->WNX-1)&07)); } PUTNEXT(q, bp); } /* * character mode input. the last character in EVERY block is * a control character. */ void urpciput(Queue *q, Block *bp, Rendez *rp) { Urp *up; int i, full; Block *nbp; up = (Urp *)q->ptr; if(bp->type != M_DATA){ urpctliput(up, q, bp); return; } /* * get the control character */ if(bp->wptr > bp->rptr) ctl = *(--bp->wptr); else ctl = 0; /* * send the block upstream */ if(bp->wptr > bp->rptr) PUTNEXT(q, bp); else freeb(bp); /* * handle the control character */ switch(ctl){ case 0: break; case ENQ: urpstat.enqsr++; queuectl(up, up->lastecho); queuectl(up, ACK+up->iseq); flushinput(up); break; case CHECK: queuectl(up, ACK+up->iseq); break; case AINIT: up->state &= ~INITING; flushinput(up); wakeup(&cp->kr); break; case INIT0: case INIT1: queuectl(up, AINIT); if(*bp->rptr == INIT1) q->put = urpbiput; initinput(up, 0); break; case INITREQ: initoutput(up, 0); break; case BREAK: break; case ACK+0: case ACK+1: case ACK+2: case ACK+3: case ACK+4: case ACK+5: case ACK+6: case ACK+7: case ECHO+0: case ECHO+1: case ECHO+2: case ECHO+3: case ECHO+4: case ECHO+5: case ECHO+6: case ECHO+7: rcvack(up, ctl); break; case SEQ+0: case SEQ+1: case SEQ+2: case SEQ+3: case SEQ+4: case SEQ+5: case SEQ+6: case SEQ+7: /* * acknowledge receipt */ ctl = ctl & 07; if(q->next->len < Streamhi){ queuectl(up, ECHO+ctl); up->lastecho = ECHO+ctl; wakeup(&cp->kr); } up->iseq = ctl; break; } } /* * block mode input. the last character in EVERY block is a control character. */ void urpbiput(Queue *q, Block *bp, Rendez *rp) { Urp *up; int i, full; Block *nbp; up = (Urp *)q->ptr; if(bp->type != M_DATA){ urpctliput(up, q, bp); return; } /* * get the control character */ if(bp->wptr > bp->rptr) ctl = *(--bp->wptr); else ctl = 0; /* * take care of any block count(trx) */ while(bp->wptr > bp->rptr && up->trx){ switch (up->trx) { case 1: case 2: up->trbuf[up->trx++] = *bp->rptr++; continue; default: up->trx = 0; case 0: break; } } /* * queue the block */ if(bp->wptr > bp->rptr){ if(q->len > up->iwindow){ flushinput(up); freeb(bp); return; } putq(q, bp); } else freeb(bp); /* * handle the control character */ switch(ctl){ case 0: break; case ENQ: urpstat.enqsr++; queuectl(up, up->lastecho); queuectl(up, ACK+up->iseq); flushinput(up); break; case CHECK: queuectl(WR(q)->next, ACK+up->iseq); break; case AINIT: up->state &= ~INITING; flushinput(up); wakeup(&cp->kr); break; case INIT0: case INIT1: queuectl(up, AINIT); if(*bp->rptr == INIT0) q->put = urpciput; initinput(up, 0); break; case INITREQ: initoutput(up, 0); break; case BREAK: break; case BOT: case BOTS: case BOTM: up->trx = 1; up->trbuf[0] = ctl; break; case REJ+0: case REJ+1: case REJ+2: case REJ+3: case REJ+4: case REJ+5: case REJ+6: case REJ+7: rcvack(up, ctl); break; case ACK+0: case ACK+1: case ACK+2: case ACK+3: case ACK+4: case ACK+5: case ACK+6: case ACK+7: case ECHO+0: case ECHO+1: case ECHO+2: case ECHO+3: case ECHO+4: case ECHO+5: case ECHO+6: case ECHO+7: rcvack(up, ctl); break; /* * this case is extremely ugliferous */ case SEQ+0: case SEQ+1: case SEQ+2: case SEQ+3: case SEQ+4: case SEQ+5: case SEQ+6: case SEQ+7: i = ctl & 07; if(up->trx != 3){ urpstat.rjtrs++; flushinput(up); break; } else if(q->len != up->trbuf[1] + (up->trbuf[2]<<8)){ urpstat.rjpks++; flushinput(up); break; } else if(i != ((up->iseq+1)&07))) { urpstat.rjseq++; flushinput(up); break; } /* * send data upstream */ if(q->first) { q->first->flags |= S_DELIM; while(bp = getq(q)) PUTNEXT(q, nbp); } else { bp = allocb(0); bp->flag |= S_DELIM; PUTNEXT(q, bp); { up->trx = 0; /* * acknowledge receipt */ ctl = ctl & 07; if(q->next->len < Streamhi){ queuectl(up, ECHO+ctl); up->lastecho = ECHO+ctl; wakeup(&cp->kr); } up->iseq = ctl; break; } } /* * downstream control */ static void urpctloput(Urp *up, Queue *q, Block *bp) { int fields[2]; int n; int inwin=0, outwin=0; switch(bp->type){ case M_CTL: if(streamparse("init", bp)){ switch(getfields(bp->rptr, fields, 2, ' ')){ case 2: inwin = strtoul(fields[1], 0, 0); case 1: outwin = strtoul(fields[0], 0, 0); } initinput(up, inwin); initoutput(up, outwin); freeb(bp); return; } } PUTNEXT(q, bp); } /* * accept data from writer */ urpoput(Queue *q, Block *bp) { Urp *up; up = (Urp *)q->ptr; if(bp->type != M_DATA){ urpctloput(up, q, bp); return; } urpstat.output + = bp->wptr - bp->rptr; for(;;){ } } /* * wait for an AINIT */ void urpopenwait(Urp *up, Queue *q) { while((up->state&ISOPENING) && !(up->state&RCLOSE)) { proc->state = Waiting; up->proc = proc; putctl1(q->next, M_RDATA, INIT1); if((up->state&ISOPENING) == 0){ up->proc = 0; if(proc->state == Waiting){ proc->state = Running; return; } } sched(); up->proc = 0; } } /* * wait till transmission is complete */ void urpxmitwait(Urp *up, Queue *q) { Block *bp; int debug; debug = (q->flag&QDEBUG); up->timeout = 0; while(!EMPTY(q) || up->WSWNX){ /* * clean up if the channel closed */ if (up->state & RCLOSE) { while(bp = getq(q)) freeb(bp); up->WACK = up->WS = up->WNX; } /* * free acked blocks */ urpfreeacked(up); /* * retransmit if requested */ if(up->state&REXMIT) urprexmit(up, q); /* * fill up the window */ if(!EMPTY(q) && WINDOW(up)) urpfillwindow(up, q); /* * ask other end for its status */ if(up->timeout){ urpstat.enqsx++; putctl1(q->next, M_RDATA, ENQ); up->timeout = 0; } lock(up->olock); if((up->state&RCLOSE) == 0 && up->WS! = up->WNX) { proc->state = Waiting; up->proc = proc; unlock(up->olock); sched(); } else unlock(up->olock); } urpfreeacked(up); up->WS = up->WACK = up->WF = up->WNX = up->WNX&07; } /* * fill up the urp output window */ void urpfillwindow(Urp *up, Queue *q) { Block *bp, *xbp; int debug; debug = (q->flag&QDEBUG); /* * now process any thing that fits in the flow control window */ while (WINDOW(up)) { bp = getq(q); if (bp == NULL) break; /* force MAXBLOCK length segments */ if (bp->rptr+up->maxblock < bp->wptr) { xbp = allocb(0); if (xbp == NULL) { putbq(q, bp); break; } xbp->rptr = bp->rptr; bp->rptr + = up->maxblock; xbp->wptr = bp->rptr; putbq(q, bp); bp = xbp; } /* * put new block in the block array. if something is already * there, it should be because we haven't gotten around to freeing * it yet. If not, complain. */ if (up->xb[up->WNX&07]) { urpfreeacked(up); if (up->xb[up->WNX&07]) { uprint(up, "urpfillwindow: overlap"); freeb(up->xb[up->WNX&07]); } } up->xb[up->WNX&07] = bp; up->WNX++; urpxmit(q, bp, up->WNX-1); } } /* * Send out a message, with trailer. */ void urpxmit(Queue *q, Block *bp, int seqno) { Urp *up = (Urp *)q->ptr; int size; Block *xbp; int debug; if (bp == NULL) { print("null bp in urpxmit\n"); return; } debug = (q->flag&QDEBUG); size = bp->wptr - bp->rptr; seqno & = 07; /* send ptr to block, if non-empty */ if (size) { if ((xbp = allocb(0)) == NULL){ print("can't xmit\n"); return; } xbp->rptr = bp->rptr; xbp->wptr = bp->wptr; xbp->type = bp->type; PUTNEXT(q, xbp); } /* send trailer */ if ((xbp = allocb(3)) == NULL){ print("can't xmit2\n"); return; } xbp->type = M_RDATA; *xbp->wptr++ = (bp->class&S_DELIM) ? BOT: BOTM; *xbp->wptr++ = size; *xbp->wptr++ = size >> 8; PUTNEXT(q, xbp); putctl1(q->next, M_RDATA, SEQ + seqno); up->timer = DKPTIME; } void urprexmit(Urp *up, Queue *q) { int i; for (i = up->WACK; iWNX; i++) { urpxmit(q, up->xb[i&07], i); urpstat.rxmit++; } up->state & = ~REXMIT; } /* * receive an acknowledgement */ static void rcvack(Urp *up, int msg) { int seqno; int next; seqno = msg&07; next = (seqno+1) & 0x7 lock(up); if(BETWEEN(seqno, up->WACK, up->WNX)) up->WACK = next; switch(msg & 0370){ case ECHO: up->timer = MSrexmit; /* push off ENQ timeout */ if(BETWEEN(seqno, up->WS, up->WNX)){ up->WS = next; wakeup(&up->r); } break; case REJ: case ACK: if(up->WACK == next){ up->state |= REXMIT; wakeup(&up->r); } break; } unlock(up); } /* * throw away any partially collected input */ static void flushinput(Urp *up) { Block *bp; while (bp = getq(up->rq)) freeb(bp); up->trx = 0; } /* * send a control character down stream */ static void sendctl(Queue *q, int x) { Block *bp; /* * send anything queued */ while(bp = getq(q)) PUTNEXT(q, bp); /* * send the new byte */ bp = allocb(1); *bp->wptr++ = x; PUTNEXT(q, bp); } /* * queue a control character to be sent down stream */ static void queuectl(Urp *up, int x) { Block *bp; Queue *q; q = up->wq; bp = allocb(1); *bp->wptr++ = x; putq(q, bp); wakeup(&up->r); } /* * initialize output */ static void initoutput(Urp *up, int window) { /* * ack any outstanding blocks */ if(up->WSWNX) urprack(up, ECHO+((up->WNX-1)&07)); /* * set output window */ up->maxblock = window/4; if(up->maxblock < 64) up->maxblock = 64; if(up->maxblock > Streamhi/4) up->maxblock = Streamhi/4; up->XW = 4; /* * set sequence varialbles */ up->WS = 1; up->WACK = 1; up->WNX = 1; /* * tell the other side we've inited */ up->state |= ISOPENING; up->timer = MSrexmit; sendctl(q->next, INIT1); } /* * initialize input */ static void initinput(Urp *up, int window) { /* * restart all sequence parameters */ up->trx = 0; up->iseq = 0; up->lastecho = ECHO+0; up->WF = 1; flushinput(up); } . ## diffname port/sturp.c 1990/0312 ## diff -e /n/bootesdump/1990/0227/sys/src/9/mips/sturp.c /n/bootesdump/1990/0312/sys/src/9/mips/sturp.c 807a } /* * do retransmissions etc */ static int todo(void *arg) { Urp *up; up = (Urp *)arg; return (WINDOW(up)>0 && up->wq->len>0 && !(up->state&INITING)); } static void urpkproc(void *arg) { Urp *up; up = (Urp *)arg; for(;;){ if(up->state & (HUNGUP|CLOSING)){ if(isflushed(up)) wakeup(&up->r); if(up->state & HUNGUP) break; } if((up->lastecho&Nmask)!=up->iseq && up->rq->next->lenlastecho = ECHO+up->iseq); output(up); tsleep(&up->rq->r, todo, up, MSrexmit/2); } DPRINT("urpkproc exiting %ux\n", up); up->kstarted = 0; up->state = 0; . 806d 789,791c up->state |= INITING; up->timer = NOW + MSrexmit; sendctl(up, INIT1); . 786a * free any outstanding blocks */ for(i = 0; i < 8; i++){ qlock(&up->xl[i]); if(up->xb[i]) freeb(up->xb[i]); qunlock(&up->xl[i]); } /* . 782,784c up->unechoed = 1; up->unacked = 1; up->next = 1; up->nxb = 1; . 777c up->maxblock -= 4; up->maxout = 3; . 763,767c int i; . 720,757d 703c wakeup(&up->rq->r); . 697,699c /* * start a retransmission if we aren't retransmitting * and this is the start of a window. */ if(up->unechoed==next && !(up->state & REJECTING)){ up->state |= REJECTING; up->next = next; . 695a if(IN(seqno, up->unechoed, up->next)) up->unechoed = next; /* * ... FALL THROUGH ... */ . 693a /* * the next reject at the start of a window starts a * retransmission. */ up->state &= ~REJECTING; . 689,692c if(IN(seqno, up->unechoed, up->next)) { up->unechoed = next; . 683,685c /* * release any acknowledged blocks */ if(IN(seqno, up->unacked, up->next)){ for(; up->unacked != next; up->unacked = NEXT(up->unacked)){ qlock(&up->xl[up->unacked]); if(up->xb[up->unacked]) freeb(up->xb[up->unacked]); up->xb[up->unacked] = 0; qunlock(&up->xl[up->unacked]); } } . 680,681c seqno = msg&Nmask; next = NEXT(seqno); . 664,668c up->timer = NOW + MSrexmit; if(up->wq->next->len > Streamhi) return; /* * message 1, the BOT and the data */ bp = up->xb[bn]; m = allocb(1); m->rptr = m->lim - 1; m->wptr = m->lim; *m->rptr = (bp->flags & S_DELIM) ? BOT : BOTM; nbp = m->next = allocb(0); nbp->rptr = bp->rptr; nbp->wptr = bp->wptr; nbp->flags |= S_DELIM; PUTNEXT(up->wq, m); /* * message 2, the block length and the SEQ */ m = allocb(3); m->rptr = m->lim - 3; m->wptr = m->lim; n = BLEN(bp); m->rptr[0] = SEQ | bn; m->rptr[1] = n; m->rptr[2] = n<<8; m->flags |= S_DELIM; PUTNEXT(up->wq, m); . 662c Block *bp, *m, *nbp; int n; . 659,660c /* * send a block. */ static void sendblock(Urp *up, int bn) . 630,656c bp = allocb(1); bp->wptr = bp->lim; bp->rptr = bp->lim-1; *bp->rptr = ctl; bp->flags |= S_DELIM; PUTNEXT(up->wq, bp); . 627,628c if(up->wq->next->len > Streamhi) . 622,625c Block *bp; . 619,620c static void sendctl(Urp *up, int ctl) . 617c * send a control byte, put the byte at the end of the allocated * space in case a lower layer needs header room. . 613a if(bp) putbq(q, bp); /* print("output w(%d) up->xb[%d](%ux) up->nxb(%d) up->state(%ux)\n", WINDOW(up), up->next, up->xb[up->next], up->nxb, up->state); /**/ /* * if a retransmit time has elapsed since a transmit, send an ENQ */ if(up->unechoed != up->next && NOW > up->timer){ print("sENQ\n"); up->timer = NOW + MSrexmit; up->state &= ~REJECTING; sendctl(up, ENQ); qunlock(&up->xmit); poperror(); return; } /* * if there's a window open, push some blocks out */ while(WINDOW(up)>0 && up->xb[up->next]!=0 && canqlock(&up->xl[up->next])){ if(up->xb[up->next]) sendblock(up, up->next); qunlock(&up->xl[up->next]); up->next = NEXT(up->next); } qunlock(&up->xmit); poperror(); . 598,612d 581,596c q = up->wq; for(bp = getq(q); bp && up->xb[up->nxb]==0; up->nxb = NEXT(up->nxb)){ if(BLEN(bp) > up->maxblock){ nbp = up->xb[up->nxb] = allocb(0); nbp->rptr = bp->rptr; nbp->wptr = bp->rptr = bp->rptr + up->maxblock; } else { up->xb[up->nxb] = bp; bp = getq(q); . 579c * fill the transmit buffers . 567,577d 563,565d 532,561c qunlock(&up->xmit); poperror(); return; . 522,530c /* * if still initing and it's time to rexmit, send an INIT1 */ now = NOW; if(up->state & INITING){ if(now > up->timer){ sendctl(up, INIT1); up->timer = now + MSrexmit; . 520c if(waserror()){ print("urp output error\n"); qunlock(&up->xmit); nexterror(); } . 511,518c if(!canqlock(&up->xmit)) return; . 495,509c Block *bp, *nbp; ulong now; Queue *q; int n; . 492,493c static void output(Urp *up) . 490c * start output . 483,486c urpstat.output += BLEN(bp); putq(q, bp); output(up); . 471a static void . 470c * accept data from a writer . 460c /* initinput(up, inwin); */ DPRINT("initoutput %d\n", outwin); . 454c switch(getfields((char *)bp->rptr, fields, 2, ' ')){ . 447c char *fields[2]; . 436c up->iseq = i; . 432,434c sendctl(up, ECHO+i); up->lastecho = ECHO+i; wakeup(&up->rq->r); . 430d 424c } . 422c bp->flags |= S_DELIM; . 419c PUTNEXT(q, bp); . 417c if(up->trbuf[0] != BOTM) q->last->flags |= S_DELIM; . 409a print("sREJ\n"); sendctl(up, up->lastecho = REJ+up->iseq); . 407c } else if(i != ((up->iseq+1)&Nmask)) { . 405a print("sREJ\n"); sendctl(up, up->lastecho = REJ+up->iseq); . 401a print("sREJ\n"); sendctl(up, up->lastecho = REJ+up->iseq); . 398c i = ctl & Nmask; . 394c * if the seuence number is the next expected * and te trailer length == 3 * and the block count matches the bytes received * then send the bytes upstream. . 382a print("rREJ\n"); . 361,362c sendctl(up, AINIT); if(ctl == INIT0) . 356c wakeup(&up->rq->r); . 350c sendctl(up, ACK+up->iseq); . 344,345c sendctl(up, up->lastecho); sendctl(up, ACK+up->iseq); . 342a print("rENQ\n"); . 332d 329d 326,327c if(BLEN(bp) > 0){ putq(q, bp); q->last->flags &= ~S_DELIM; if(q->len > 4*1024){ . 324c * queue the block(s) . 318d 310c while(up->trx){ if(BLEN(bp)<=0) break; . 302,305c ctl = *bp->rptr++; . 290,291c int i; int ctl; . 287c urpiput(Queue *q, Block *bp) . 284c * block mode input. * * the first byte in every message is a ctl byte (which belongs at the end). * * Simplifying assumption: one put == one message && the control byte * is in the first block. If this isn't true, strange bytes will be * used as control bytes. . 269,278c i = ctl & Nmask; if(q->next->len < Streamhi) sendctl(up, up->lastecho = ECHO+i); up->iseq = i; . 259a case REJ+0: case REJ+1: case REJ+2: case REJ+3: case REJ+4: case REJ+5: case REJ+6: case REJ+7: rcvack(up, ctl); break; . 247,249c sendctl(up, AINIT); if(ctl == INIT1) q->put = urpiput; . 242c wakeup(&up->rq->r); . 236c sendctl(up, ACK+up->iseq); . 230,232c sendctl(up, up->lastecho); sendctl(up, ACK+up->iseq); . 227d 216c if(BLEN(bp)>0 && q->next->lenrptr++; if(ctl < 0) return; . 196,197c int i; int ctl; . 193c urpciput(Queue *q, Block *bp) . 189,190c * character mode input. * * the first byte in every message is a ctl byte (which belongs at the end). . 175,183c up->state |= HUNGUP; wakeup(&up->r); wakeup(&up->rq->r); break; . 162,164c up->state |= CLOSING; sleep(&up->r, isflushed, up); /* * ack all outstanding messages */ qlock(&up->xmit); up->state |= HUNGUP; i = up->next - 1; if(i < 0) i = 7; rcvack(up, ECHO+i); qunlock(&up->xmit); DPRINT("urpclose(%ux)\n", up); /* * kill off the kernel process */ wakeup(&up->rq->r); DPRINT("urpclosed(%ux)\n", up); . 160c * wait for all outstanding messages to drain, tell kernel * process we're closing. . 157d 149a static int isdead(void *a) { Urp *up; up = (Urp *)a; return up->kstarted == 0; } static void . 148c return (up->state&HUNGUP) || (up->unechoed==up->next && up->wq->len==0); . 143c isflushed(void *a) . 140c * Shut down the connection and kill off the kernel process . 136a /* * start the ack/(re)xmit process */ if(up->kstarted == 0){ up->kstarted = 1; sprint(name, "**urp%d**", up - urp); kproc(name, urpkproc, up); } . 132,133c up->wq = q->other; up->state = OPEN; . 130c q->ptr = q->other->ptr = up; . 116a char name[128]; . 112c static void . 110c Qinfo urpinfo = { urpciput, urpoput, urpopen, urpclose, "urp" }; . 108a static void urpkproc(void *arg); . 105,106c static void sendctl(Urp*, int); . 102a static void output(Urp*); static void sendblock(Urp*, int); . 99,100c static void urpciput(Queue*, Block*); static void urpiput(Queue*, Block*); static void urpoput(Queue*, Block*); . 90,92c #define REJECTING 0x1 #define INITING 0x2 #define HUNGUP 0x4 #define OPEN 0x8 #define CLOSING 0x10 . 63,65c #define WINDOW(u) ((u->unechoed + u->maxout - u->next)%8) #define IN(x, f, n) (f<=n ? x>=f && x=f) #define NEXT(x) (((x)+1)&Nmask) . 61c QLock xl[8]; ulong timer; /* timeout for xmit */ int kstarted; . 54,59c int next; /* next block to send */ int unechoed; /* first unechoed block */ int unacked; /* first unacked block */ int nxb; /* next xb to use */ . 50,52c QLock xmit; /* output lock, only one process at a time */ Queue *wq; /* output queue */ int maxout; /* maximum outstanding unacked blocks */ . 42c Queue *rq; /* input queue */ . 38a Rendez r; /* process waiting for close */ . 37c QLock; . 20a #define NOW (MACHP(0)->ticks*MS2HZ) . 18a #define DPRINT if(0) . 16a Nmask= 0x7, . 1,12c #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "errno.h" . ## diffname port/sturp.c 1990/0315 ## diff -e /n/bootesdump/1990/0312/sys/src/9/mips/sturp.c /n/bootesdump/1990/0315/sys/src/9/mips/sturp.c 825a DPRINT("urpkproc started\n"); . 782a up->xb[i] = 0; . 458c print("sREJ3 %d %d\n", i, up->iseq); . 452c print("sREJ2 %d\n", up->iseq); . 446c print("sREJ1 %d\n", up->iseq); . 382c print("rENQ %uo %uo\n", up->lastecho, ACK+up->iseq); . 125a DPRINT("urpopen\n"); . ## diffname port/sturp.c 1990/0321 ## diff -e /n/bootesdump/1990/0315/sys/src/9/mips/sturp.c /n/bootesdump/1990/0321/sys/src/9/mips/sturp.c 843d 838,839c sendack(up); . 829d 805a up->blocks = 0; . 640a * send a reject */ static void sendrej(Urp *up) { flushinput(up); qlock(&up->ack); if((up->lastecho&~Nmask) == ECHO){ DPRINT("REJ %d\n", up->iseq); sendctl(up, up->lastecho = REJ|up->iseq); } qunlock(&up->ack); } /* * send an acknowledge */ static void sendack(Urp *up) { Block *bp; /* * check the precondition for acking */ if(up->rq->next->len>=Streamhi || (up->lastecho&Nmask)==up->iseq) return; if(!canqlock(&up->ack)) return; /* * check again now that we've locked */ if(up->rq->next->len>=Streamhi || (up->lastecho&Nmask)==up->iseq){ qunlock(&up->ack); return; } /* * send the ack */ sendctl(up, up->lastecho = ECHO|up->iseq); qunlock(&up->ack); } /* . 599c DPRINT("sENQ\n"); . 513d 488a if(q->next->len < Streamhi) sendctl(up, up->lastecho = ECHO|i); qunlock(&up->ack); . 483,487c qlock(&up->ack); . 459,461c sendrej(up); . 453,455c sendrej(up); . 447,449c sendrej(up); . 425c DPRINT("rREJ\n"); . 384c DPRINT("rENQ %d %uo %uo\n", up->blocks, up->lastecho, ACK+up->iseq); up->blocks = 0; . 315a qunlock(&up->ack); . 311a qlock(&up->ack); . 209d 203d 126,127d 112a static void sendack(Urp*); static void sendrej(Urp*); . 47a int blocks; . 42c QLock ack; /* ack lock */ . ## diffname port/sturp.c 1990/0331 ## diff -e /n/bootesdump/1990/0321/sys/src/9/mips/sturp.c /n/bootesdump/1990/0331/sys/src/9/mips/sturp.c 66c #define WINDOW(u) ((u)->unechoed>(u)->next ? (u)->unechoed+(u)->maxout-(u)->next-8 :\ (u)->unechoed+(u)->maxout-(u)->next) . ## diffname port/sturp.c 1990/0403 ## diff -e /n/bootesdump/1990/0331/sys/src/9/mips/sturp.c /n/bootesdump/1990/0403/sys/src/9/mips/sturp.c 885a up->kstarted = 0; . 884d 872a if(waserror()){ up->state = 0; up->kstarted = 0; wakeup(&up->r); return; } . 807,808d 692c if(QFULL(up->wq->next)) . 670c if(QFULL(up->rq->next) || (up->lastecho&Nmask)==up->iseq){ . 661c if(QFULL(up->rq->next) || (up->lastecho&Nmask)==up->iseq) . 625c if(QFULL(up->wq->next)) . 582c bp = 0; . 575c for(bp = getq(q); q->first && up->xb[up->nxb]==0; up->nxb = NEXT(up->nxb)){ if(bp == 0) bp = getq(q); . 482c if(!QFULL(q->next)) . 314c if(!QFULL(q->next)) . 256c if(BLEN(bp)>0 && !QFULL(q->next)) . 209a if(up->kstarted == 0) up->state = 0; . ## diffname port/sturp.c 1990/0406 ## diff -e /n/bootesdump/1990/0403/sys/src/9/mips/sturp.c /n/bootesdump/1990/0406/sys/src/9/mips/sturp.c 590,591d 588a if(bp) putbq(q, bp); . 578,587c if(up->xb[up->nxb]==0) { for(bp=getq(q); bp && up->xb[up->nxb]==0; up->nxb=NEXT(up->nxb)){ if(BLEN(bp) > up->maxblock){ nbp = up->xb[up->nxb] = allocb(0); nbp->rptr = bp->rptr; nbp->wptr = bp->rptr = bp->rptr + up->maxblock; } else { up->xb[up->nxb] = bp; bp = getq(q); } . ## diffname port/sturp.c 1990/0424 ## diff -e /n/bootesdump/1990/0406/sys/src/9/mips/sturp.c /n/bootesdump/1990/0424/sys/src/9/mips/sturp.c 475c if(up->trbuf[0] != BOTM) bp->flags |= S_DELIM; . 374d 372a bp->flags &= ~S_DELIM; . ## diffname port/sturp.c 1990/0505 ## diff -e /n/bootesdump/1990/0424/sys/src/9/mips/sturp.c /n/bootesdump/1990/0505/sys/src/9/mips/sturp.c 193c tsleep(&up->r, isflushed, up, 60*1000); . ## diffname port/sturp.c 1990/0509 ## diff -e /n/bootesdump/1990/0505/sys/src/9/mips/sturp.c /n/bootesdump/1990/0509/sys/src/9/mips/sturp.c 209c for(i = 0; i < 7; i++) if(up->xb[i]){ freeb(up->xb[i]); up->xb[i] = 0; } qunlock(&up->xmit); . 207c * free all staged but unsent messages . 204d 199a wakeup(&up->rq->r); qlock(&up->xmit); /* * ack all outstanding messages */ . 198d 196c * kill off the kernel process . 193c tsleep(&up->r, isflushed, up, 2*60*1000); . 190a * * if 2 minutes elapse, give it up . 169c return (up->state&HUNGUP) || (up->unechoed==up->nxb && up->wq->len==0); . ## diffname port/sturp.c 1990/0511 ## diff -e /n/bootesdump/1990/0509/sys/src/9/mips/sturp.c /n/bootesdump/1990/0511/sys/src/9/mips/sturp.c 906a DPRINT("urpkproc %ux\n", up); . 901c if(up->state == 0){ DPRINT("urpkproc: %ux->state == 0\n", up); break; } if(!QFULL(up->rq->next)) sendack(up); . 888a print("urpkproc error %ux\n", up); . 833a up->rexmit = 0; . 789c up->rexmit = 1; . 757,761c i = up->unacked; qlock(&up->xl[i]); if(up->xb[i]) freeb(up->xb[i]); up->xb[i] = 0; qunlock(&up->xl[i]); . 747a int i; . 627a poperror(); . 623,626c if(up->rexmit){ up->rexmit = 0; up->next = up->unechoed; } while(WINDOW(up)>0 && up->xb[up->next]!=0){ i = up->next; qlock(&up->xl[i]); if(waserror()){ qunlock(&up->xl[i]); nexterror(); } sendblock(up, i); qunlock(&up->xl[i]); . 610,611c if(up->unechoed!=up->next && NOW>up->timer){ . 561a int i; . 473a } else if(q->next->len > (3*Streamhi)/2 || q->next->nb > (3*Streambhi)/2) { flushinput(up); break; . 223a } . 222c if(up->kstarted == 0){ DPRINT("urpclose %ux\n", up); . 171,178d 62a int rexmit; . 51d ## diffname port/sturp.c 1990/0601 ## diff -e /n/bootesdump/1990/0511/sys/src/9/mips/sturp.c /n/bootesdump/1990/0601/sys/src/9/mips/sturp.c 266c } else . 264c if(BLEN(bp)>0 && q->next->len<2*Streamhi && q->next->nb<2*Streambhi){ bp->flags |= S_DELIM; . ## diffname port/sturp.c 1990/0629 ## diff -e /n/bootesdump/1990/0601/sys/src/9/mips/sturp.c /n/bootesdump/1990/0629/sys/src/9/mips/sturp.c 925a } /* * urp got very confused, complain */ static void urpvomit(char *msg, Urp* up) { print("urpvomit: %s %ux next %d unechoed %d unacked %d nxb %d\n", msg, up, up->next, up->unechoed, up->unacked, up->nxb); print("\txb: %ux %ux %ux %ux %ux %ux %ux %ux\n", up->xb[0], up->xb[1], up->xb[2], up->xb[3], up->xb[4], up->xb[5], up->xb[6], up->xb[7]); print("\tiseq: %uo lastecho: %uo trx: %d trbuf: %uo %uo %uo\n", up->iseq, up->lastecho, up->trx, up->trbuf[0], up->trbuf[1], up->trbuf[2]); print("\tupq: %ux %d %d\n", up->rq->next->first, up->rq->next->nb, up->rq->next->len); } int urpdump(void) { Urp *up; for(up = urp; up < &urp[Nurp]; up++) if(up->rq) urpvomit("", up); . 770a else urpvomit("rcvack", up); . 724a if(bp == 0){ urpvomit("sendblock", up); return; } . 622,626c while(WINDOW(up)>0 && up->next!=up->nxb){ . 620a * * the lock is to synchronize with acknowledges that free * blocks. . 610c if(up->rexmit){ /* * if a retransmit is requested, move next back to * the unacked blocks */ up->rexmit = 0; up->next = up->unacked; } else if(up->unacked!=up->next && NOW>up->timer){ /* * if a retransmit time has elapsed since a transmit, * send an ENQ */ . 608c * retransmit cruft . 604,606c . 599a up->nxb = i; . 590,591c i = NEXT(up->nxb); if(i != up->unechoed) { for(bp = getq(q); bp && i!=up->unechoed; i = NEXT(i)){ if(up->xb[up->nxb] != 0) urpvomit("output", up); . 587c * fill the transmit buffers, `nxb' can never overtake `unechoed' . 119a static void urpvomit(char*, Urp*); . 68c #define IN(x, f, n) (f<=n ? (x>=f && x=f)) . ## diffname port/sturp.c 1990/0702 ## diff -e /n/bootesdump/1990/0629/sys/src/9/mips/sturp.c /n/bootesdump/1990/0702/sys/src/9/mips/sturp.c 962a lock(up->rq->next); for(bp = up->rq->next->first; bp; bp = bp->next){ print("%d%c:\t", bp->wptr - bp->rptr, (bp->flags&S_DELIM)?'D':' '); for(cp = bp->rptr; cpwptr && cprptr+10; cp++) print(" %uo", *cp); print("\n"); } unlock(up->rq->next); . 961c print("\tupq: %ux %d %d\n", &up->rq->next->r, up->rq->next->nb, . 952a Block *bp; uchar *cp; . ## diffname port/sturp.c 1990/0707 ## diff -e /n/bootesdump/1990/0702/sys/src/9/mips/sturp.c /n/bootesdump/1990/0707/sys/src/9/mips/sturp.c 966,974d 953,955d ## diffname port/sturp.c 1990/0717 ## diff -e /n/bootesdump/1990/0707/sys/src/9/mips/sturp.c /n/bootesdump/1990/0717/sys/src/9/mips/sturp.c 970c for(up = urp; up < &urp[conf.nurp]; up++) . 179a if(up == 0) return; . 141a } . 140c if(up == &urp[conf.nurp]){ q->ptr = 0; WR(q)->ptr = 0; . 134c for(up = urp; up < &urp[conf.nurp]; up++){ . 123a void urpreset(void) { newqinfo(&urpinfo); urp = (Urp *)ialloc(conf.nurp*sizeof(Urp), 0); } . 100c Urp *urp; . 10d ## diffname port/sturp.c 1990/0721 ## diff -e /n/bootesdump/1990/0717/sys/src/9/mips/sturp.c /n/bootesdump/1990/0721/sys/src/9/mips/sturp.c 928a q = up->wq; . 926c Urp *up; Queue *q; . 690a Queue *q = up->wq; . 538a if(streamparse("debug", bp)){ switch(getfields((char *)bp->rptr, fields, 2, ' ')){ case 1: if (strcmp(fields[0], "on") == 0) { q->flag |= QDEBUG; q->other->flag |= QDEBUG; } if (strcmp(fields[0], "off") == 0) { q->flag &= ~QDEBUG; q->other->flag &= ~QDEBUG; } } freeb(bp); return; } . 485a DPRINT("rSEQ%d accept %d\n", i, q->len); . 461,462c * if the sequence number is the next expected * and the trailer length == 3 . 442a case BOTS: DPRINT("rBOT%d...", ctl-BOT); . 441d 14c #define DPRINT /*if(q->flag&QDEBUG)kprint*/ . ## diffname port/sturp.c 1990/0722 ## diff -e /n/bootesdump/1990/0721/sys/src/9/mips/sturp.c /n/bootesdump/1990/0722/sys/src/9/mips/sturp.c 165c sprint(name, "urp%d", up - urp); . ## diffname port/sturp.c 1990/0725 ## diff -e /n/bootesdump/1990/0722/sys/src/9/mips/sturp.c /n/bootesdump/1990/0725/sys/src/9/mips/sturp.c 974a } /* * timer to wakeup urpkproc's for retransmissions */ static void urptimer(Alarm *a) { Urp *up; Urp *last; Queue *q; urptiming = 0; for(up = urp, last = &urp[conf.nurp]; up < last; up++){ if(up->state==0) continue; if(up->unacked!=up->next && NOW>up->timer){ q = up->rq; if(q) wakeup(&q->r); } } . 970c sleep(&up->rq->r, todo, up); . 591a /* * start the urptimer if it isn't already */ if(urptiming==0){ if(canlock(&urptlock)){ if(urptiming == 0) urptiming = alarm(500, urptimer, 0); unlock(&urptlock); } } . 167a /* * start the urptimer if it isn't already */ if(urptiming==0){ if(canlock(&urptlock)){ if(urptiming == 0) urptiming = alarm(500, urptimer, 0); unlock(&urptlock); } } . 118a static void urptimer(Alarm*); . 70a * Alarm for urptiming */ Alarm *urptiming; Lock urptlock; /* . ## diffname port/sturp.c 1990/0726 ## diff -e /n/bootesdump/1990/0725/sys/src/9/mips/sturp.c /n/bootesdump/1990/0726/sys/src/9/mips/sturp.c 1015a cancel(a); . ## diffname port/sturp.c 1990/0728 ## diff -e /n/bootesdump/1990/0726/sys/src/9/mips/sturp.c /n/bootesdump/1990/0728/sys/src/9/mips/sturp.c 1017c alarm(500, urptimer, 0); . 1002a wakeup(&up->r); poperror(); . 1001d 995d 986,993c if(up->state & HUNGUP) . 980d 976c up->kstarted = 1; . 973c Urp *up; . 707a out: . 685,687c goto out; . 639,641c goto out; . 610,620d 244,247c /* * wait for kernel process to die */ while(up->kstarted) sleep(&up->r, isdead, up); up->state = 0; . 220c * tell kernel process to die . 191a isdead(void *a) { Urp *up; up = (Urp *)a; return up->kstarted==0; } static int . 170,185c sprint(name, "urp%d", up - urp); kproc(name, urpkproc, up); . 134a alarm(500, urptimer, 0); . 71,76d ## diffname port/sturp.c 1990/0731 ## diff -e /n/bootesdump/1990/0728/sys/src/9/mips/sturp.c /n/bootesdump/1990/0731/sys/src/9/mips/sturp.c 991c if((up->unacked!=up->next || (up->state&INITING)) && NOW>up->timer){ . ## diffname port/sturp.c 1990/0804 ## diff -e /n/bootesdump/1990/0731/sys/src/9/mips/sturp.c /n/bootesdump/1990/0804/sys/src/9/mips/sturp.c 991,995c if(up->rq && todo(up)) wakeup(&up->rq->r); . 973d 946c return (up->state&INITING) ? NOW>up->timer /* time to INIT1 */ : ((up->unacked!=up->next && NOW>up->timer) /* time to ENQ */ || (!QFULL(up->rq->next) && up->iseq!=(up->lastecho&7))); /* time to ECHO */ . ## diffname port/sturp.c 1990/0814 ## diff -e /n/bootesdump/1990/0804/sys/src/9/mips/sturp.c /n/bootesdump/1990/0814/sys/src/9/mips/sturp.c 949a || WINDOW(up)>0 && up->next!=up->nxb . 777d 774,775c if(bp == 0) . ## diffname port/sturp.c 1990/0911 ## diff -e /n/bootesdump/1990/0814/sys/src/9/mips/sturp.c /n/bootesdump/1990/0911/sys/src/9/mips/sturp.c 127d 124c static void . 122c Qinfo urpinfo = { urpciput, urpoput, urpopen, urpclose, "urp", urpreset }; . 103a static void urpreset(void); . 14c #define DPRINT if(q->flag&QDEBUG)print . ## diffname port/sturp.c 1990/0930 ## diff -e /n/bootesdump/1990/0911/sys/src/9/mips/sturp.c /n/bootesdump/1990/0930/sys/src/9/mips/sturp.c 947c : ((up->unechoed!=up->next && NOW>up->timer) /* time to ENQ */ . 656c } else if(up->unechoed!=up->next && NOW>up->timer){ . ## diffname port/sturp.c 1990/1004 ## diff -e /n/bootesdump/1990/0930/sys/src/9/mips/sturp.c /n/bootesdump/1990/1004/sys/src/9/mips/sturp.c 993,994c if(up->rq && canlock(up)){ if(up->rq && NOW>up->timer && ((up->state&INITING) || up->unechoed!=up->next)) wakeup(&up->rq->r); unlock(up); } . 986d 948,949c || (WINDOW(up)>0 && (up->next!=up->nxb || up->wq->first)) /* open xmit window */ || (up->iseq!=(up->lastecho&7) && !QFULL(up->rq->next))); /* time to ECHO */ . 797c PUTNEXT(q, m); DPRINT("sb %d\n", bn); . 784c PUTNEXT(q, m); . 767c if(QFULL(q->next)) . 765a q = up->wq; . 764a Queue *q; . 706c PUTNEXT(q, bp); DPRINT("sCTL %ulx\n", ctl); . 699c q = up->wq; if(QFULL(q->next)) . 697a Queue *q; . 467a DPRINT("rACK %ux\n", ctl); . 239a up->rq = 0; unlock(up); . 238a lock(up); . 158c unlock(up); . 146c unlock(up); . 143c lock(up); . 36c Lock; . ## diffname port/sturp.c 1990/11151 ## diff -e /n/bootesdump/1990/1004/sys/src/9/mips/sturp.c /n/bootesdump/1990/11151/sys/src/9/mips/sturp.c 123c Qinfo urpinfo = { urpciput, urpoput, urpopen, urpclose, "urp", urpreset }; . ## diffname port/sturp.c 1990/11211 ## diff -e /n/bootesdump/1990/11151/sys/src/9/mips/sturp.c /n/bootesdump/1990/11211/sys/src/9/mips/sturp.c 159c error(Egreg); . ## diffname port/sturp.c 1990/1206 ## diff -e /n/bootesdump/1990/11211/sys/src/9/mips/sturp.c /n/bootesdump/1990/1206/sys/src/9/mips/sturp.c 1015a tsleep(&urpkr, return0, 0, 1000); . 984,1014c for(up = urp; up < eup; up++){ if(up->state==0 || (up->state&HUNGUP)) break; if(!canqlock(up)) continue; if(up->state==0 || (up->state&HUNGUP)) break; if(up->iseq!=(up->lastecho&7) && !QFULL(up->rq->next)) sendack(up); output(up); qunlock(up); . 977,982c eup = urp + conf.nurp; . 974,975c if(waserror()) ; . 972c Urp *up, *eup; . 953,968d 876c wakeup(&urpkr); . 443c wakeup(&urpkr); . 322c wakeup(&urpkr); . 263d 249,250c qunlock(up); . 241,247c qlock(up); . 220d 215,218d 181,188d 169,174d 166c qunlock(up); . 154c qunlock(up); . 151c qlock(up); . 146a if(!urpkstarted){ qlock(&urpkl); if(!urpkstarted){ urpkstarted = 1; kproc("urpkproc", urpkproc, 0); } qunlock(&urpkl); } . 137d 120d 99,100d 64a Urp *urp; Rendez urpkr; QLock urpkl; int urpkstarted; . 62,63d 38c Rendez r; /* process waiting for output to finish */ . 36c QLock; . ## diffname port/sturp.c 1990/1210 ## diff -e /n/bootesdump/1990/1210/sys/src/9/mips/sturp.c /n/bootesdump/1990/1210/sys/src/9/port/sturp.c 955a poperror(); . 950,951c if(waserror()){ qunlock(up); continue; } if(up->state==0 || (up->state&HUNGUP)){ qunlock(up); poperror(); continue; } . 947c continue; . 209c if(!waserror()){ tsleep(&up->r, isflushed, up, 2*60*1000); poperror(); } . ## diffname port/sturp.c 1990/1212 ## diff -e /n/bootesdump/1990/1210/sys/src/9/port/sturp.c /n/bootesdump/1990/1212/sys/src/9/port/sturp.c 171a q->rp = &urpkr; . ## diffname port/sturp.c 1990/1214 ## diff -e /n/bootesdump/1990/1212/sys/src/9/port/sturp.c /n/bootesdump/1990/1214/sys/src/9/port/sturp.c 543a USED(inwin); . ## diffname port/sturp.c 1991/0426 ## diff -e /n/bootesdump/1990/1214/sys/src/9/port/sturp.c /n/bootesdump/1991/0426/sys/src/9/port/sturp.c 863a wakeup(&up->r); . ## diffname port/sturp.c 1991/0605 ## diff -e /n/bootesdump/1991/0426/sys/src/9/port/sturp.c /n/bootesdump/1991/0605/sys/src/9/port/sturp.c 366a if(up == 0) return; . 267a if(up == 0) return; . 160,163c if(up->state == 0){ qlock(up); if(up->state == 0) break; qunlock(up); } . ## diffname port/sturp.c 1991/0626 ## diff -e /n/bootesdump/1991/0605/sys/src/9/port/sturp.c /n/bootesdump/1991/0626/sys/src/9/port/sturp.c 14c #define DPRINT if(q->flag&QDEBUG)kprint . ## diffname port/sturp.c 1991/0705 ## diff -e /n/bootesdump/1991/0626/sys/src/9/port/sturp.c /n/bootesdump/1991/0705/sys/src/9/port/sturp.c 14c #define DPRINT if(q->flag&QDEBUG)print . ## diffname port/sturp.c 1991/1115 ## diff -e /n/bootesdump/1991/0705/sys/src/9/port/sturp.c /n/bootesdump/1991/1115/sys/src/9/port/sturp.c 170c errors("out of urp structures"); . ## diffname port/sturp.c 1991/1122 ## diff -e /n/bootesdump/1991/1115/sys/src/9/port/sturp.c /n/bootesdump/1991/1122/sys/src/9/port/sturp.c 1006a } void urpfillstats(Chan *c, char *buf, int len) { char b[256]; USED(c); sprint(b, "in: %d\nout: %d\nrexmit: %d\nrjtrs: %d\nrjpks: %d\nrjseq: %d\nenqsx: %d\nenqsr: %d\n", urpstat.input, urpstat.output, urpstat.rexmit, urpstat.rjtrs, urpstat.rjpks, urpstat.rjseq, urpstat.enqsr, urpstat.enqsr); strncpy(buf, b, len); . 667a urpstat.enqsx++; . 658a urpstat.rexmit++; . 510a } . 509c while(bp = getq(q)){ urpstat.input += BLEN(bp); . 288a urpstat.input += BLEN(bp); . 26c ulong rexmit; /* retransmit rejected urp msg */ . ## diffname port/sturp.c 1991/1216 ## diff -e /n/bootesdump/1991/1122/sys/src/9/port/sturp.c /n/bootesdump/1991/1216/sys/src/9/port/sturp.c 956a USED(arg); . ## diffname port/sturp.c 1992/0111 ## diff -e /n/bootesdump/1991/1216/sys/src/9/port/sturp.c /n/bootesdump/1992/0111/sys/src/9/port/sturp.c 7c #include "../port/error.h" . ## diffname port/sturp.c 1992/0114 ## diff -e /n/bootesdump/1992/0111/sys/src/9/port/sturp.c /n/bootesdump/1992/0114/sys/src/9/port/sturp.c 170c exhausted("urp structures"); . ## diffname port/sturp.c 1992/0205 ## diff -e /n/bootesdump/1992/0114/sys/src/9/port/sturp.c /n/bootesdump/1992/0205/sys/src/9/port/sturp.c 1024c urpstat.rjpks, urpstat.rjseq, urpstat.enqsx, urpstat.enqsr); . 932a { Queue *q = up->wq; DPRINT("initoutput (%d): ", up->timer); } . 813c DPRINT("sb %d (%d)\n", bn, up->timer); . 765a { Queue *q = up->wq; DPRINT("sendack: "); } . 719a PUTNEXT(q, bp); . 718d 669a DPRINT("OUTPUT timer (%d, %d): ", NOW, up->timer); . 624a q = up->wq; DPRINT("INITING timer (%d, %d): ", now, up->timer); . 502c DPRINT("accept %d\n", q->len); . 483a DPRINT("rSEQ%d...", ctl-SEQ); . 472c DPRINT("%s%d\n", (ctl&ECHO)?"rECHO":"rACK", ctl&7); . 464c DPRINT("rREJ%d\n", ctl-REJ); . 457c DPRINT("rBOT%c...", " MS"[ctl-BOT]); . 447a DPRINT("rINITREQ\n"); . 440a DPRINT("rINIT%d\n", ctl-INIT0); . 433a DPRINT("rAINIT\n"); . 429a DPRINT("rCHECK\n"); . 344a DPRINT("rSEQ%d(c)\n", ctl-SEQ); . 339a DPRINT("%s%d(c)\n", (ctl&ECHO)?"rECHO":"rACK", ctl&7); . 332a DPRINT("rREJ%d(c)\n", ctl-REJ); . 324a DPRINT("rINITREQ(c)\n"); . 317a DPRINT("rINIT%d(c)\n", ctl-INIT0); . 310a DPRINT("rAINIT(c)\n"); . 306a DPRINT("rCHECK(c)\n"); . 300a DPRINT("rENQ(c)\n"); . 172c /* q->flag |= QDEBUG; q->other->flag |= QDEBUG; */ . ## diffname port/sturp.c 1992/0206 ## diff -e /n/bootesdump/1992/0205/sys/src/9/port/sturp.c /n/bootesdump/1992/0206/sys/src/9/port/sturp.c 505a DPRINT("rej %d rcvd %d xpctd\n", q->len, up->trbuf[1] + (up->trbuf[2]<<8)); . ## diffname port/sturp.c 1992/0208 ## diff -e /n/bootesdump/1992/0206/sys/src/9/port/sturp.c /n/bootesdump/1992/0208/sys/src/9/port/sturp.c 515,516c }else if(q->next->len > (3*Streamhi)/2 || q->next->nb > (3*Streambhi)/2){ DPRINT("next->len=%d, next->nb=%d\n", q->next->len, q->next->nb); . 511c }else if(i != ((up->iseq+1)&Nmask)){ . 505,507c }else if(q->len != len){ . 499c len = up->trbuf[1] + (up->trbuf[2]<<8); DPRINT("rSEQ%d(%d,%d,%d)...", ctl-SEQ, up->trx, len, q->len); . 379c int i, len; . 14c #define DPRINT if(q->flag&QDEBUG)kprint . ## diffname port/sturp.c 1992/0321 ## diff -e /n/bootesdump/1992/0208/sys/src/9/port/sturp.c /n/bootesdump/1992/0321/sys/src/9/port/sturp.c 2c #include "../port/lib.h" . ## diffname port/sturp.c 1992/0408 ## diff -e /n/bootesdump/1992/0321/sys/src/9/port/sturp.c /n/bootesdump/1992/0408/sys/src/9/port/sturp.c 1008c tsleep(&urpkr, return0, 0, 500); . 897,898c tryoutput(up); if(up->state & CLOSING) wakeup(&up->r); . 722a * try output, this is called by an input process */ void tryoutput(Urp *up) { if(!waserror()){ output(up); poperror(); } } /* . 449c tryoutput(up); . 373a * * There's no input lock. The channel could be closed while we're * processing a message. . 319c tryoutput(up); . 122a static void tryoutput(Urp*); . ## diffname port/sturp.c 1992/0409 ## diff -e /n/bootesdump/1992/0408/sys/src/9/port/sturp.c /n/bootesdump/1992/0409/sys/src/9/port/sturp.c 946c up->maxout = 4; . ## diffname port/sturp.c 1992/0520 ## diff -e /n/bootesdump/1992/0409/sys/src/9/port/sturp.c /n/bootesdump/1992/0520/sys/src/9/port/sturp.c 1054a return 0; . ## diffname port/sturp.c 1992/0622 ## diff -e /n/bootesdump/1992/0520/sys/src/9/port/sturp.c /n/bootesdump/1992/0622/sys/src/9/port/sturp.c 138c urp = (Urp *)xalloc(conf.nurp*sizeof(Urp)); . ## diffname port/sturp.c 1992/0623 ## diff -e /n/bootesdump/1992/0622/sys/src/9/port/sturp.c /n/bootesdump/1992/0623/sys/src/9/port/sturp.c 1045,1055d 1005c for(up = urpalloc.urp; up; up = up->list){ . 1003d 996c Urp *up; . 173,176d 168,171c if(up == 0){ /* * none available, create a new one, they are never freed */ up = smalloc(sizeof(Urp)); qlock(up); lock(&urpalloc); up->list = urpalloc.urp; urpalloc.urp = up; unlock(&urpalloc); . 160c for(up = urpalloc.urp; up; up = up->list){ . 158c * find an unused urp structure . 138d 64a /* list of allocated urp structures (never freed) */ struct { Lock; Urp *urp; } urpalloc; . 63d 36a Urp *list; /* list of all urp structures */ . ## diffname port/sturp.c 1992/0711 ## diff -e /n/bootesdump/1992/0623/sys/src/9/port/sturp.c /n/bootesdump/1992/0711/sys/src/9/port/sturp.c 989c initinput(Urp *up) . 790,791d 638d 578,585c outwin = strtoul((char*)bp->rptr, 0, 0); . 572,573c int outwin; . 470c initinput(up); . 337c initinput(up); . 209d 191c initinput(up); . 153a USED(s); . 151,152d 127c static void initinput(Urp*); . ## diffname port/sturp.c 1992/1026 ## diff -e /n/bootesdump/1992/0711/sys/src/9/port/sturp.c /n/bootesdump/1992/1026/sys/src/9/port/sturp.c 573a if(streamparse("break", bp)){ sendctl(up, BREAK); freeb(bp); return; } . ## diffname port/sturp.c 1992/1027 ## diff -e /n/bootesdump/1992/1026/sys/src/9/port/sturp.c /n/bootesdump/1992/1027/sys/src/9/port/sturp.c 838c if(bp->type == M_CTL){ PUTNEXT(q, nbp); m->flags |= S_DELIM; PUTNEXT(q, m); } else { m->next = nbp; PUTNEXT(q, m); } . 836a nbp->base = bp->base; nbp->lim = bp->lim; . 834c nbp = allocb(0); . 575,576c /* * send a break as part of the data stream */ urpstat.output++; bp->wptr = bp->lim; bp->rptr = bp->wptr - 1; *bp->rptr = BREAK; putq(q, bp); output(up); . ## diffname port/sturp.c 1993/0116 ## diff -e /n/bootesdump/1992/1027/sys/src/9/port/sturp.c /n/bootesdump/1993/0116/sys/src/9/port/sturp.c 893,894d 244a qunlock(&up->xl[i]); } . 240c for(i = 0; i < 7; i++){ qlock(&up->xl[i]); . ## diffname port/sturp.c 1993/0418 ## diff -e /n/bootesdump/1993/0116/sys/src/9/port/sturp.c /n/bootesdump/1993/0418/sys/src/9/port/sturp.c 868c m->rptr[2] = n>>8; . ## diffname port/sturp.c 1993/0501 ## diff -e /n/bootesdump/1993/0418/sys/src/9/port/sturp.c /n/fornaxdump/1993/0501/sys/src/brazil/port/sturp.c 1057,1060c urp->iseq, urp->lastecho, urp->trx, urp->trbuf[0], urp->trbuf[1], urp->trbuf[2]); print("\tupq: %ux %d %d\n", &urp->rq->next->r, urp->rq->next->nb, urp->rq->next->len); . 1054,1055c urp->xb[0], urp->xb[1], urp->xb[2], urp->xb[3], urp->xb[4], urp->xb[5], urp->xb[6], urp->xb[7]); . 1052c msg, urp, urp->next, urp->unechoed, urp->unacked, urp->nxb); . 1049c urpvomit(char *msg, Urp* urp) . 1035,1038c if(urp->iseq!=(urp->lastecho&7) && !QFULL(urp->rq->next)) sendack(urp); output(urp); qunlock(urp); . 1030,1031c if(urp->state==0 || (urp->state&HUNGUP)){ qunlock(urp); . 1027c qunlock(urp); . 1024c if(!canqlock(urp)) . 1021,1022c for(urp = urpalloc.urp; urp; urp = urp->list){ if(urp->state==0 || (urp->state&HUNGUP)) . 1013c Urp *urp; . 1003,1007c urp->blocks = 0; urp->trx = 0; urp->iseq = 0; urp->lastecho = ECHO+0; flushinput(urp); . 998c initinput(Urp *urp) . 988,991c urp->state |= INITING; urp->timer = NOW + MSrexmit; { Queue *q = urp->wq; DPRINT("initoutput (%d): ", urp->timer); } sendctl(urp, INIT1); . 978,982c qlock(&urp->xl[i]); if(urp->xb[i]) freeb(urp->xb[i]); urp->xb[i] = 0; qunlock(&urp->xl[i]); . 968,972c urp->unechoed = 1; urp->unacked = 1; urp->next = 1; urp->nxb = 1; urp->rexmit = 0; . 959,963c urp->maxblock = window/4; if(urp->maxblock < 64) urp->maxblock = 64; urp->maxblock -= 4; urp->maxout = 4; . 952c initoutput(Urp *urp, int window) . 945c urp->trx = 0; . 943c while (bp = getq(urp->rq)) . 939c flushinput(Urp *urp) . 930,932c tryoutput(urp); if(urp->state & CLOSING) wakeup(&urp->r); . 923,925c if(urp->unechoed==next && !(urp->state & REJECTING)){ urp->state |= REJECTING; urp->rexmit = 1; . 913,914c if(IN(seqno, urp->unechoed, urp->next)) urp->unechoed = next; . 910c urp->state &= ~REJECTING; . 903,904c if(IN(seqno, urp->unechoed, urp->next)) { urp->unechoed = next; . 890,897c if(IN(seqno, urp->unacked, urp->next)){ for(; urp->unacked != next; urp->unacked = NEXT(urp->unacked)){ i = urp->unacked; qlock(&urp->xl[i]); if(urp->xb[i]) freeb(urp->xb[i]); else urpvomit("rcvack", urp); urp->xb[i] = 0; qunlock(&urp->xl[i]); . 878c rcvack(Urp *urp, int msg) . 871c DPRINT("sb %d (%d)\n", bn, urp->timer); . 868c m->rptr[2] = n<<8; . 837c bp = urp->xb[bn]; . 829,830c q = urp->wq; urp->timer = NOW + MSrexmit; . 827a Block *bp, *m, *nbp; . 825d 823c sendblock(Urp *urp, int bn) . 814,816c { Queue *q = urp->wq; DPRINT("sendack: "); } sendctl(urp, urp->lastecho = ECHO|urp->iseq); qunlock(&urp->ack); . 806,807c if(QFULL(urp->rq->next) || (urp->lastecho&Nmask)==urp->iseq){ qunlock(&urp->ack); . 800c if(!canqlock(&urp->ack)) . 797c if(QFULL(urp->rq->next) || (urp->lastecho&Nmask)==urp->iseq) . 792c sendack(Urp *urp) . 785c qunlock(&urp->ack); . 778,783c Queue *q = urp->wq; flushinput(urp); qlock(&urp->ack); if((urp->lastecho&~Nmask) == ECHO){ DPRINT("REJ %d\n", urp->iseq); sendctl(urp, urp->lastecho = REJ|urp->iseq); . 776c sendrej(Urp *urp) . 760c q = urp->wq; . 755c sendctl(Urp *urp, int ctl) . 745c output(urp); . 742c tryoutput(Urp *urp) . 734c qunlock(&urp->xmit); . 728,730c sendblock(urp, i); qunlock(&urp->xl[i]); urp->next = NEXT(urp->next); . 725c qunlock(&urp->xl[i]); . 721,723c while(WINDOW(urp)>0 && urp->next!=urp->nxb){ i = urp->next; qlock(&urp->xl[i]); . 711c sendctl(urp, ENQ); . 707,709c DPRINT("OUTPUT timer (%d, %d): ", NOW, urp->timer); urp->timer = NOW + MSrexmit; urp->state &= ~REJECTING; . 700,702c urp->rexmit = 0; urp->next = urp->unacked; } else if(urp->unechoed!=urp->next && NOW>urp->timer){ . 694c if(urp->rexmit){ . 685c urp->nxb = i; . 682c urp->xb[urp->nxb] = bp; . 680c nbp->wptr = bp->rptr = bp->rptr + urp->maxblock; . 671,678c q = urp->wq; i = NEXT(urp->nxb); if(i != urp->unechoed) { for(bp = getq(q); bp && i!=urp->unechoed; i = NEXT(i)){ if(urp->xb[urp->nxb] != 0) urpvomit("output", urp); if(BLEN(bp) > urp->maxblock){ nbp = urp->xb[urp->nxb] = allocb(0); . 658,663c if(urp->state & INITING){ if(now > urp->timer){ q = urp->wq; DPRINT("INITING timer (%d, %d): ", now, urp->timer); sendctl(urp, INIT1); urp->timer = now + MSrexmit; . 650c qunlock(&urp->xmit); . 645c if(!canqlock(&urp->xmit)) . 638c output(Urp *urp) . 631c output(urp); . 625c urpctloput(urp, q, bp); . 622c urp = (Urp *)q->ptr; . 620c Urp *urp; . 591c initoutput(urp, outwin); . 586c output(urp); . 570c urpctloput(Urp *urp, Queue *q, Block *bp) . 560,561c sendctl(urp, urp->lastecho = ECHO|i); qunlock(&urp->ack); . 557,558c qlock(&urp->ack); urp->iseq = i; . 552c urp->trx = 0; . 548c if(urp->trbuf[0] != BOTM) . 540c if(urp->trbuf[0] != BOTM) . 531c flushinput(urp); . 525c sendrej(urp); . 523c }else if(i != ((urp->iseq+1)&Nmask)){ . 521c sendrej(urp); . 517c sendrej(urp); . 515c if(urp->trx != 3){ . 512,513c len = urp->trbuf[1] + (urp->trbuf[2]<<8); DPRINT("rSEQ%d(%d,%d,%d)...", ctl-SEQ, urp->trx, len, q->len); . 501c rcvack(urp, ctl); . 493c rcvack(urp, ctl); . 486,487c urp->trx = 1; urp->trbuf[0] = ctl; . 476c initoutput(urp, 0); . 471c initinput(urp); . 468c sendctl(urp, AINIT); . 460,462c urp->state &= ~INITING; flushinput(urp); tryoutput(urp); . 455c sendctl(urp, ACK+urp->iseq); . 448,450c sendctl(urp, urp->lastecho); sendctl(urp, ACK+urp->iseq); flushinput(urp); . 445,446c DPRINT("rENQ %d %uo %uo\n", urp->blocks, urp->lastecho, ACK+urp->iseq); urp->blocks = 0; . 432c flushinput(urp); . 420c urp->trx = 0; . 417c urp->trbuf[urp->trx++] = *bp->rptr++; . 414c switch (urp->trx) { . 411c while(urp->trx){ . 399c urpctliput(urp, q, bp); . 395,396c urp = (Urp *)q->ptr; if(urp == 0) . 391c Urp *urp; . 369,371c sendctl(urp, urp->lastecho = ECHO+i); urp->iseq = i; qunlock(&urp->ack); . 366c qlock(&urp->ack); . 360c rcvack(urp, ctl); . 352c rcvack(urp, ctl); . 343c initoutput(urp, 0); . 338c initinput(urp); . 335c sendctl(urp, AINIT); . 327,329c urp->state &= ~INITING; flushinput(urp); tryoutput(urp); . 322c sendctl(urp, ACK+urp->iseq); . 316,317c sendctl(urp, urp->lastecho); sendctl(urp, ACK+urp->iseq); . 286c urpctliput(urp, q, bp); . 282,283c urp = (Urp *)q->ptr; if(urp == 0) . 278c Urp *urp; . 263,264c urp->state |= HUNGUP; wakeup(&urp->r); . 259c urpctliput(Urp *urp, Queue *q, Block *bp) . 250,252c qlock(urp); urp->state = 0; qunlock(urp); . 246,248c qunlock(&urp->xmit); . 240,244c for(i = 0; i < 7; i++) if(urp->xb[i]){ freeb(urp->xb[i]); urp->xb[i] = 0; . 235c rcvack(urp, ECHO+i); . 232c i = urp->next - 1; . 228c qlock(&urp->xmit); . 226c urp->state |= HUNGUP; . 223c tsleep(&urp->r, isflushed, urp, 2*60*1000); . 221c urp->state |= CLOSING; . 211,212c urp = (Urp *)q->ptr; if(urp == 0) . 208c Urp *urp; . 202,203c urp = (Urp *)a; return (urp->state&HUNGUP) || (urp->unechoed==urp->nxb && urp->wq->len==0); . 200c Urp *urp; . 186,191c urp->rq = q; urp->wq = q->other; urp->state = OPEN; qunlock(urp); initinput(urp); initoutput(urp, 0); . 184c q->ptr = q->other->ptr = urp; . 180,181c urp->list = urpalloc.urp; urpalloc.urp = urp; . 177,178c urp = smalloc(sizeof(Urp)); qlock(urp); . 173c if(urp == 0){ . 170c qunlock(urp); . 165,168c for(urp = urpalloc.urp; urp; urp = urp->list){ if(urp->state == 0){ qlock(urp); if(urp->state == 0) . 150c Urp *urp; . ## diffname port/sturp.c 1993/0804 # deleted ## diff -e /n/fornaxdump/1993/0501/sys/src/brazil/port/sturp.c /n/fornaxdump/1993/0804/sys/src/brazil/port/sturp.c 1,1072d