xref: /inferno-os/os/ip/loopbackmedium.c (revision 6e425a9de8c003b5a733621a6b6730ec3cc902b8)
174a4d8c2SCharles.Forsyth #include "u.h"
274a4d8c2SCharles.Forsyth #include "../port/lib.h"
374a4d8c2SCharles.Forsyth #include "mem.h"
474a4d8c2SCharles.Forsyth #include "dat.h"
574a4d8c2SCharles.Forsyth #include "fns.h"
674a4d8c2SCharles.Forsyth #include "../port/error.h"
774a4d8c2SCharles.Forsyth 
874a4d8c2SCharles.Forsyth #include "ip.h"
974a4d8c2SCharles.Forsyth 
1074a4d8c2SCharles.Forsyth enum
1174a4d8c2SCharles.Forsyth {
1274a4d8c2SCharles.Forsyth 	Maxtu=	16*1024,
1374a4d8c2SCharles.Forsyth };
1474a4d8c2SCharles.Forsyth 
1574a4d8c2SCharles.Forsyth typedef struct LB LB;
1674a4d8c2SCharles.Forsyth struct LB
1774a4d8c2SCharles.Forsyth {
1874a4d8c2SCharles.Forsyth 	Proc	*readp;
1974a4d8c2SCharles.Forsyth 	Queue	*q;
2074a4d8c2SCharles.Forsyth 	Fs	*f;
2174a4d8c2SCharles.Forsyth };
2274a4d8c2SCharles.Forsyth 
2374a4d8c2SCharles.Forsyth static void loopbackread(void *a);
2474a4d8c2SCharles.Forsyth 
2574a4d8c2SCharles.Forsyth static void
loopbackbind(Ipifc * ifc,int,char **)2674a4d8c2SCharles.Forsyth loopbackbind(Ipifc *ifc, int, char**)
2774a4d8c2SCharles.Forsyth {
2874a4d8c2SCharles.Forsyth 	LB *lb;
2974a4d8c2SCharles.Forsyth 
3074a4d8c2SCharles.Forsyth 	lb = smalloc(sizeof(*lb));
3174a4d8c2SCharles.Forsyth 	lb->f = ifc->conv->p->f;
3274a4d8c2SCharles.Forsyth 	/* TO DO: make queue size a function of kernel memory */
3374a4d8c2SCharles.Forsyth 	lb->q = qopen(128*1024, Qmsg, nil, nil);
3474a4d8c2SCharles.Forsyth 	ifc->arg = lb;
3574a4d8c2SCharles.Forsyth 	ifc->mbps = 1000;
3674a4d8c2SCharles.Forsyth 
37*6e425a9dSCharles.Forsyth 	kproc("loopbackread", loopbackread, ifc, 0);
3874a4d8c2SCharles.Forsyth 
3974a4d8c2SCharles.Forsyth }
4074a4d8c2SCharles.Forsyth 
4174a4d8c2SCharles.Forsyth static void
loopbackunbind(Ipifc * ifc)4274a4d8c2SCharles.Forsyth loopbackunbind(Ipifc *ifc)
4374a4d8c2SCharles.Forsyth {
4474a4d8c2SCharles.Forsyth 	LB *lb = ifc->arg;
4574a4d8c2SCharles.Forsyth 
4674a4d8c2SCharles.Forsyth 	if(lb->readp)
4774a4d8c2SCharles.Forsyth 		postnote(lb->readp, 1, "unbind", 0);
4874a4d8c2SCharles.Forsyth 
4974a4d8c2SCharles.Forsyth 	/* wait for reader to die */
5074a4d8c2SCharles.Forsyth 	while(lb->readp != 0)
5174a4d8c2SCharles.Forsyth 		tsleep(&up->sleep, return0, 0, 300);
5274a4d8c2SCharles.Forsyth 
5374a4d8c2SCharles.Forsyth 	/* clean up */
5474a4d8c2SCharles.Forsyth 	qfree(lb->q);
5574a4d8c2SCharles.Forsyth 	free(lb);
5674a4d8c2SCharles.Forsyth }
5774a4d8c2SCharles.Forsyth 
5874a4d8c2SCharles.Forsyth static void
loopbackbwrite(Ipifc * ifc,Block * bp,int,uchar *)5974a4d8c2SCharles.Forsyth loopbackbwrite(Ipifc *ifc, Block *bp, int, uchar*)
6074a4d8c2SCharles.Forsyth {
6174a4d8c2SCharles.Forsyth 	LB *lb;
6274a4d8c2SCharles.Forsyth 
6374a4d8c2SCharles.Forsyth 	lb = ifc->arg;
6474a4d8c2SCharles.Forsyth 	if(qpass(lb->q, bp) < 0)
6574a4d8c2SCharles.Forsyth 		ifc->outerr++;
6674a4d8c2SCharles.Forsyth 	ifc->out++;
6774a4d8c2SCharles.Forsyth }
6874a4d8c2SCharles.Forsyth 
6974a4d8c2SCharles.Forsyth static void
loopbackread(void * a)7074a4d8c2SCharles.Forsyth loopbackread(void *a)
7174a4d8c2SCharles.Forsyth {
7274a4d8c2SCharles.Forsyth 	Ipifc *ifc;
7374a4d8c2SCharles.Forsyth 	Block *bp;
7474a4d8c2SCharles.Forsyth 	LB *lb;
7574a4d8c2SCharles.Forsyth 
7674a4d8c2SCharles.Forsyth 	ifc = a;
7774a4d8c2SCharles.Forsyth 	lb = ifc->arg;
7874a4d8c2SCharles.Forsyth 	lb->readp = up;	/* hide identity under a rock for unbind */
7974a4d8c2SCharles.Forsyth 	if(waserror()){
8074a4d8c2SCharles.Forsyth 		lb->readp = 0;
8174a4d8c2SCharles.Forsyth 		pexit("hangup", 1);
8274a4d8c2SCharles.Forsyth 	}
8374a4d8c2SCharles.Forsyth 	for(;;){
8474a4d8c2SCharles.Forsyth 		bp = qbread(lb->q, Maxtu);
8574a4d8c2SCharles.Forsyth 		if(bp == nil)
8674a4d8c2SCharles.Forsyth 			continue;
8774a4d8c2SCharles.Forsyth 		ifc->in++;
8874a4d8c2SCharles.Forsyth 		if(!canrlock(ifc)){
8974a4d8c2SCharles.Forsyth 			freeb(bp);
9074a4d8c2SCharles.Forsyth 			continue;
9174a4d8c2SCharles.Forsyth 		}
9274a4d8c2SCharles.Forsyth 		if(waserror()){
9374a4d8c2SCharles.Forsyth 			runlock(ifc);
9474a4d8c2SCharles.Forsyth 			nexterror();
9574a4d8c2SCharles.Forsyth 		}
9674a4d8c2SCharles.Forsyth 		if(ifc->lifc == nil)
9774a4d8c2SCharles.Forsyth 			freeb(bp);
9874a4d8c2SCharles.Forsyth 		else
9974a4d8c2SCharles.Forsyth 			ipiput4(lb->f, ifc, bp);
10074a4d8c2SCharles.Forsyth 		runlock(ifc);
10174a4d8c2SCharles.Forsyth 		poperror();
10274a4d8c2SCharles.Forsyth 	}
10374a4d8c2SCharles.Forsyth }
10474a4d8c2SCharles.Forsyth 
10574a4d8c2SCharles.Forsyth Medium loopbackmedium =
10674a4d8c2SCharles.Forsyth {
10774a4d8c2SCharles.Forsyth .hsize=		0,
10874a4d8c2SCharles.Forsyth .mintu=		0,
10974a4d8c2SCharles.Forsyth .maxtu=		Maxtu,
11074a4d8c2SCharles.Forsyth .maclen=	0,
11174a4d8c2SCharles.Forsyth .name=		"loopback",
11274a4d8c2SCharles.Forsyth .bind=		loopbackbind,
11374a4d8c2SCharles.Forsyth .unbind=	loopbackunbind,
11474a4d8c2SCharles.Forsyth .bwrite=	loopbackbwrite,
11574a4d8c2SCharles.Forsyth };
11674a4d8c2SCharles.Forsyth 
11774a4d8c2SCharles.Forsyth void
loopbackmediumlink(void)11874a4d8c2SCharles.Forsyth loopbackmediumlink(void)
11974a4d8c2SCharles.Forsyth {
12074a4d8c2SCharles.Forsyth 	addipmedium(&loopbackmedium);
12174a4d8c2SCharles.Forsyth }
122