|
|
Plan 9 NeXT
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
enum
{
Twritehdr = 16, /* Min bytes for Twrite */
Rreadhdr = 8, /* Min bytes for Rread */
Twritecnt = 13, /* Offset in byte stream of write count */
Rreadcnt = 5, /* Offset for Readcnt */
};
static void fcalliput(Queue*, Block*);
static void fcalloput(Queue*, Block*);
static void fcallopen(Queue*, Stream*);
static void fcallclose(Queue*);
static void fcallreset(void);
Qinfo fcallinfo = { fcalliput, fcalloput, fcallopen, fcallclose, "fcall", fcallreset };
static uchar msglen[256] =
{
[Tnop] 3,
[Rnop] 3,
[Tsession] 3+CHALLEN,
[Rsession] 3+NAMELEN+DOMLEN+CHALLEN,
[Terror] 0,
[Rerror] 67,
[Tflush] 5,
[Rflush] 3,
[Tattach] 5+2*NAMELEN+TICKETLEN+AUTHENTLEN,
[Rattach] 13+AUTHENTLEN,
[Tclone] 7,
[Rclone] 5,
[Twalk] 33,
[Rwalk] 13,
[Topen] 6,
[Ropen] 13,
[Tcreate] 38,
[Rcreate] 13,
[Tread] 15,
[Rread] 8,
[Twrite] 16,
[Rwrite] 7,
[Tclunk] 5,
[Rclunk] 5,
[Tremove] 5,
[Rremove] 5,
[Tstat] 5,
[Rstat] 121,
[Twstat] 121,
[Rwstat] 5,
[Tclwalk] 35,
[Rclwalk] 13,
};
void
stfcalllink(void)
{
newqinfo(&fcallinfo);
}
static void
fcallreset(void)
{
}
static void
fcallopen(Queue *q, Stream *s)
{
USED(q, s);
}
static void
fcallclose(Queue * q)
{
USED(q);
}
void
fcalloput(Queue *q, Block *bp)
{
PUTNEXT(q, bp);
}
void
upstream(Queue *q, ulong len)
{
Block *bl, **tail, *bp;
ulong l;
tail = &bl;
while(len) {
l = BLEN(q->first);
if(l > len)
break;
bp = getq(q); /* Consume all of block */
*tail = bp;
tail = &bp->next;
len -= l;
}
if(len) { /* Consume partial block */
lock(q);
*tail = copyb(q->first, len);
q->first->rptr += len;
q->len -= len;
unlock(q);
}
for(bp = bl; bp->next; bp = bp->next)
;
bp->flags |= S_DELIM;
PUTNEXT(q, bl);
}
static void
fcalliput(Queue *q, Block *bp)
{
ulong len, need, off;
if(bp->type != M_DATA) {
PUTNEXT(q, bp);
return;
}
if(BLEN(bp) == 0) {
freeb(bp);
return;
}
/* Stash the data */
bp->flags &= ~S_DELIM;
putq(q, bp);
for(;;) {
bp = q->first;
if(bp == 0)
return;
switch(bp->rptr[0]) { /* This is the type */
default:
len = msglen[bp->rptr[0]];
if(len == 0){
bp = allocb(0);
bp->type = M_HANGUP;
PUTNEXT(q, bp);
return;
}
if(q->len < len)
return;
upstream(q, len);
continue;
case Twrite: /* Fmt: TGGFFOOOOOOOOCC */
len = Twritehdr; /* T = type, G = tag, F = fid */
off = Twritecnt; /* O = offset, C = count */
break;
case Rread: /* Fmt: TGGFFCC */
len = Rreadhdr;
off = Rreadcnt;
break;
}
if(q->len < len)
return;
/*
* the lock here is wrong. it should be a qlock since
* the pullup may block. not worth fixing.
*/
lock(q);
bp = q->first = pullup(q->first, len);
if(bp == 0)
q->len = 0;
unlock(q);
need = len+bp->rptr[off]+(bp->rptr[off+1]<<8);
if(q->len < need)
return;
upstream(q, need);
}
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.