~kris/9p

9hist

3aea5ab8a883559f9385b2b366f7cb66b5ea04ec — David du Colombier 35 years ago b014f5c
Plan 9 from Bell Labs 1991-05-21
1 files changed, 224 insertions(+), 0 deletions(-)

A port/stfcall.c
A port/stfcall.c => port/stfcall.c +224 -0
@@ 0,0 1,224 @@
#include	"u.h"
#include	"lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"errno.h"

#include	"fcall.h"

#define DPRINT 	if(fcalldebug)kprint

int fcalldebug = 0;

typedef struct Fcalld	Fcalld;

struct Fcalld{
	int	dev;		/* ref. for debug output */
	int	state;
	int	type;		/* of current message */
	int	need;		/* bytes remaining in current message */
	int	nhdr;		/* bytes of header treasured up in hdr */
	uchar	hdr[16];
};

enum {
	Startup, Startup1, Begin, Header, Data
};

/*
 *  fcall stream module definition
 */
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 Block *	putmsg(Queue*, Block*, int);

static uchar msglen[] = {
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  3,  3,  3,  3,  0, 67,  5,  3, 89, 13,  7,  5, 33, 13,
	  6, 13, 38, 13, 15,  8, 16,  7,  5,  5,  5,  5,  5,121,121,  5,
	 35, 13,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
};
static void
fcallreset(void)
{}

static void
fcallopen(Queue *q, Stream *s)
{
	Fcalld *f;

	DPRINT("fcallopen %d\n", s->dev);

	q->ptr = allocb(sizeof(Fcalld));
	f = (Fcalld *)((Block *)q->ptr)->base;
	f->dev = s->dev;
	f->state = Startup;
	f->type = 0;
	f->need = 0;
	f->nhdr = 0;
}

static void
fcallclose(Queue * q)
{
	Fcalld *f = (Fcalld *)((Block *)q->ptr)->base;

	DPRINT("fcallstclose %d\n", f->dev);
	freeb(q->ptr);
	q->ptr = 0;
}

void
fcalloput(Queue *q, Block *bp)
{
	PUTNEXT(q, bp);
}


static void
fcalliput(Queue *q, Block *bp)
{
	Fcalld *f = (Fcalld *)((Block *)q->ptr)->base;
	int len, n;

	len = BLEN(bp);
	DPRINT("fcalliput %d: blen=%d\n", f->dev, len);
	if(bp->type != M_DATA){
		DPRINT("fcalliput %d: type=%d\n", f->dev, bp->type);
		PUTNEXT(q, bp);
		return;
	}
	bp->flags &= ~S_DELIM;
	if(len == 0){
		freeb(bp);
		return;
	}
	while(len > 0)switch(f->state){
	case Startup:
		if (len == 1 && bp->rptr[0] == 'O'){
			DPRINT("fcalliput %d: O\n", f->dev);
			PUTNEXT(q, bp);
			f->state = Startup1;
			return;
		}
		if(bp->rptr[0] == 'O' && bp->rptr[1] == 'K'){
			DPRINT("fcalliput %d: OK\n", f->dev);
			bp = putmsg(q, bp, 2);
			len -= 2;
		}
		f->state = Begin;
		break;

	case Startup1:
		if(bp->rptr[0] == 'K'){
			DPRINT("fcalliput %d: K\n", f->dev);
			bp = putmsg(q, bp, 1);
			len -= 1;
			f->state = Begin;
			break;
		}
		f->type = 'O';
		f->need = msglen['O']-1;
		f->state = Data;
		DPRINT("fcalliput %d: type=%d, need=%d\n",
			f->dev, f->type, f->need);
		break;

	case Begin:
		f->type = bp->rptr[0];
		f->need = msglen[f->type];
		f->nhdr = 0;
		if(f->type == Twrite || f->type == Rread)
			f->state = Header;
		else
			f->state = Data;
		DPRINT("fcalliput %d: type=%d, need=%d\n",
			f->dev, f->type, f->need);
		break;

	case Header:
		n = f->need;
		if(n > len)
			n = len;
		memmove(&f->hdr[f->nhdr], bp->rptr, n);
		f->nhdr += n;
		DPRINT("fcalliput %d: nhdr=%d\n",
			f->dev, f->nhdr);
		if(n == f->need){
			f->need += f->hdr[f->nhdr-3];
			f->need += f->hdr[f->nhdr-2] << 8;
			f->state = Data;
			DPRINT("fcalliput %d: need=%d\n",
				f->dev, f->need);
		}
		/* fall through */

	case Data:
		if(f->need > len){
			f->need -= len;
			PUTNEXT(q, bp);
			return;
		}
		bp = putmsg(q, bp, f->need);
		len -= f->need;
		f->state = Begin;
		break;
	}
}

static Block *
putmsg(Queue *q, Block *bp, int n)
{
	Block *xbp;
	int k;

	DPRINT("putmsg: n=%d\n\n", n);
	k = BLEN(bp) - n;
	if(k == 0){
		bp->flags |= S_DELIM;
		PUTNEXT(q, bp);
		return 0;
	}
	if(n <= k){
		xbp = allocb(n);
		memmove(xbp->wptr, bp->rptr, n);
		xbp->wptr += n;
		bp->rptr += n;
		xbp->flags |= S_DELIM;
		PUTNEXT(q, xbp);
		return bp;
	}
	xbp = allocb(k);
	memmove(xbp->wptr, bp->rptr+n, k);
	xbp->wptr += k;
	bp->wptr -= k;
	bp->flags |= S_DELIM;
	PUTNEXT(q, bp);
	return xbp;
}