xref: /plan9/sys/src/9/ip/loopbackmedium.c (revision dc5a79c1208f0704eeb474acc990728f8b4854f5)
180ee5cbfSDavid du Colombier #include "u.h"
280ee5cbfSDavid du Colombier #include "../port/lib.h"
380ee5cbfSDavid du Colombier #include "mem.h"
480ee5cbfSDavid du Colombier #include "dat.h"
580ee5cbfSDavid du Colombier #include "fns.h"
680ee5cbfSDavid du Colombier #include "../port/error.h"
780ee5cbfSDavid du Colombier 
880ee5cbfSDavid du Colombier #include "ip.h"
980ee5cbfSDavid du Colombier 
1080ee5cbfSDavid du Colombier enum
1180ee5cbfSDavid du Colombier {
1280ee5cbfSDavid du Colombier 	Maxtu=	16*1024,
1380ee5cbfSDavid du Colombier };
1480ee5cbfSDavid du Colombier 
1580ee5cbfSDavid du Colombier typedef struct LB LB;
1680ee5cbfSDavid du Colombier struct LB
1780ee5cbfSDavid du Colombier {
1880ee5cbfSDavid du Colombier 	Proc	*readp;
1980ee5cbfSDavid du Colombier 	Queue	*q;
2080ee5cbfSDavid du Colombier 	Fs	*f;
2180ee5cbfSDavid du Colombier };
2280ee5cbfSDavid du Colombier 
2380ee5cbfSDavid du Colombier static void loopbackread(void *a);
2480ee5cbfSDavid du Colombier 
2580ee5cbfSDavid du Colombier static void
loopbackbind(Ipifc * ifc,int,char **)2680ee5cbfSDavid du Colombier loopbackbind(Ipifc *ifc, int, char**)
2780ee5cbfSDavid du Colombier {
2880ee5cbfSDavid du Colombier 	LB *lb;
2980ee5cbfSDavid du Colombier 
3080ee5cbfSDavid du Colombier 	lb = smalloc(sizeof(*lb));
3180ee5cbfSDavid du Colombier 	lb->f = ifc->conv->p->f;
32*dc5a79c1SDavid du Colombier 	lb->q = qopen(1024*1024, Qmsg, nil, nil);
3380ee5cbfSDavid du Colombier 	ifc->arg = lb;
34*dc5a79c1SDavid du Colombier 	ifc->mbps = 1000;
3580ee5cbfSDavid du Colombier 
3680ee5cbfSDavid du Colombier 	kproc("loopbackread", loopbackread, ifc);
3780ee5cbfSDavid du Colombier 
3880ee5cbfSDavid du Colombier }
3980ee5cbfSDavid du Colombier 
4080ee5cbfSDavid du Colombier static void
loopbackunbind(Ipifc * ifc)4180ee5cbfSDavid du Colombier loopbackunbind(Ipifc *ifc)
4280ee5cbfSDavid du Colombier {
4380ee5cbfSDavid du Colombier 	LB *lb = ifc->arg;
4480ee5cbfSDavid du Colombier 
4580ee5cbfSDavid du Colombier 	if(lb->readp)
4680ee5cbfSDavid du Colombier 		postnote(lb->readp, 1, "unbind", 0);
4780ee5cbfSDavid du Colombier 
4880ee5cbfSDavid du Colombier 	/* wait for reader to die */
4980ee5cbfSDavid du Colombier 	while(lb->readp != 0)
5080ee5cbfSDavid du Colombier 		tsleep(&up->sleep, return0, 0, 300);
5180ee5cbfSDavid du Colombier 
5280ee5cbfSDavid du Colombier 	/* clean up */
5380ee5cbfSDavid du Colombier 	qfree(lb->q);
5480ee5cbfSDavid du Colombier 	free(lb);
5580ee5cbfSDavid du Colombier }
5680ee5cbfSDavid du Colombier 
5780ee5cbfSDavid du Colombier static void
loopbackbwrite(Ipifc * ifc,Block * bp,int,uchar *)5880ee5cbfSDavid du Colombier loopbackbwrite(Ipifc *ifc, Block *bp, int, uchar*)
5980ee5cbfSDavid du Colombier {
6080ee5cbfSDavid du Colombier 	LB *lb;
6180ee5cbfSDavid du Colombier 
6280ee5cbfSDavid du Colombier 	lb = ifc->arg;
6380ee5cbfSDavid du Colombier 	if(qpass(lb->q, bp) < 0)
6480ee5cbfSDavid du Colombier 		ifc->outerr++;
6580ee5cbfSDavid du Colombier 	ifc->out++;
6680ee5cbfSDavid du Colombier }
6780ee5cbfSDavid du Colombier 
6880ee5cbfSDavid du Colombier static void
loopbackread(void * a)6980ee5cbfSDavid du Colombier loopbackread(void *a)
7080ee5cbfSDavid du Colombier {
7180ee5cbfSDavid du Colombier 	Ipifc *ifc;
7280ee5cbfSDavid du Colombier 	Block *bp;
7380ee5cbfSDavid du Colombier 	LB *lb;
7480ee5cbfSDavid du Colombier 
7580ee5cbfSDavid du Colombier 	ifc = a;
7680ee5cbfSDavid du Colombier 	lb = ifc->arg;
7780ee5cbfSDavid du Colombier 	lb->readp = up;	/* hide identity under a rock for unbind */
7880ee5cbfSDavid du Colombier 	if(waserror()){
7980ee5cbfSDavid du Colombier 		lb->readp = 0;
8080ee5cbfSDavid du Colombier 		pexit("hangup", 1);
8180ee5cbfSDavid du Colombier 	}
8280ee5cbfSDavid du Colombier 	for(;;){
8380ee5cbfSDavid du Colombier 		bp = qbread(lb->q, Maxtu);
8480ee5cbfSDavid du Colombier 		if(bp == nil)
8580ee5cbfSDavid du Colombier 			continue;
8680ee5cbfSDavid du Colombier 		ifc->in++;
8780ee5cbfSDavid du Colombier 		if(!canrlock(ifc)){
8880ee5cbfSDavid du Colombier 			freeb(bp);
8980ee5cbfSDavid du Colombier 			continue;
9080ee5cbfSDavid du Colombier 		}
9180ee5cbfSDavid du Colombier 		if(waserror()){
9280ee5cbfSDavid du Colombier 			runlock(ifc);
9380ee5cbfSDavid du Colombier 			nexterror();
9480ee5cbfSDavid du Colombier 		}
9580ee5cbfSDavid du Colombier 		if(ifc->lifc == nil)
9680ee5cbfSDavid du Colombier 			freeb(bp);
9780ee5cbfSDavid du Colombier 		else
983ff48bf5SDavid du Colombier 			ipiput4(lb->f, ifc, bp);
9980ee5cbfSDavid du Colombier 		runlock(ifc);
10080ee5cbfSDavid du Colombier 		poperror();
10180ee5cbfSDavid du Colombier 	}
10280ee5cbfSDavid du Colombier }
10380ee5cbfSDavid du Colombier 
10480ee5cbfSDavid du Colombier Medium loopbackmedium =
10580ee5cbfSDavid du Colombier {
10680ee5cbfSDavid du Colombier .hsize=		0,
1073f695129SDavid du Colombier .mintu=		0,
1083f695129SDavid du Colombier .maxtu=		Maxtu,
10980ee5cbfSDavid du Colombier .maclen=	0,
11080ee5cbfSDavid du Colombier .name=		"loopback",
11180ee5cbfSDavid du Colombier .bind=		loopbackbind,
11280ee5cbfSDavid du Colombier .unbind=	loopbackunbind,
11380ee5cbfSDavid du Colombier .bwrite=	loopbackbwrite,
11480ee5cbfSDavid du Colombier };
11580ee5cbfSDavid du Colombier 
11680ee5cbfSDavid du Colombier void
loopbackmediumlink(void)11780ee5cbfSDavid du Colombier loopbackmediumlink(void)
11880ee5cbfSDavid du Colombier {
11980ee5cbfSDavid du Colombier 	addipmedium(&loopbackmedium);
12080ee5cbfSDavid du Colombier }
121