xref: /plan9/sys/src/9/ip/loopbackmedium.c (revision 3ff48bf5ed603850fcd251ddf13025d23d693782)
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
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*3ff48bf5SDavid du Colombier 	lb->q = qopen(128*1024, Qmsg, nil, nil);
3380ee5cbfSDavid du Colombier 	ifc->arg = lb;
3480ee5cbfSDavid du Colombier 
3580ee5cbfSDavid du Colombier 	kproc("loopbackread", loopbackread, ifc);
3680ee5cbfSDavid du Colombier 
3780ee5cbfSDavid du Colombier }
3880ee5cbfSDavid du Colombier 
3980ee5cbfSDavid du Colombier static void
4080ee5cbfSDavid du Colombier loopbackunbind(Ipifc *ifc)
4180ee5cbfSDavid du Colombier {
4280ee5cbfSDavid du Colombier 	LB *lb = ifc->arg;
4380ee5cbfSDavid du Colombier 
4480ee5cbfSDavid du Colombier 	if(lb->readp)
4580ee5cbfSDavid du Colombier 		postnote(lb->readp, 1, "unbind", 0);
4680ee5cbfSDavid du Colombier 
4780ee5cbfSDavid du Colombier 	/* wait for reader to die */
4880ee5cbfSDavid du Colombier 	while(lb->readp != 0)
4980ee5cbfSDavid du Colombier 		tsleep(&up->sleep, return0, 0, 300);
5080ee5cbfSDavid du Colombier 
5180ee5cbfSDavid du Colombier 	/* clean up */
5280ee5cbfSDavid du Colombier 	qfree(lb->q);
5380ee5cbfSDavid du Colombier 	free(lb);
5480ee5cbfSDavid du Colombier }
5580ee5cbfSDavid du Colombier 
5680ee5cbfSDavid du Colombier static void
5780ee5cbfSDavid du Colombier loopbackbwrite(Ipifc *ifc, Block *bp, int, uchar*)
5880ee5cbfSDavid du Colombier {
5980ee5cbfSDavid du Colombier 	LB *lb;
6080ee5cbfSDavid du Colombier 
6180ee5cbfSDavid du Colombier 	lb = ifc->arg;
6280ee5cbfSDavid du Colombier 	if(qpass(lb->q, bp) < 0)
6380ee5cbfSDavid du Colombier 		ifc->outerr++;
6480ee5cbfSDavid du Colombier 	ifc->out++;
6580ee5cbfSDavid du Colombier }
6680ee5cbfSDavid du Colombier 
6780ee5cbfSDavid du Colombier static void
6880ee5cbfSDavid du Colombier loopbackread(void *a)
6980ee5cbfSDavid du Colombier {
7080ee5cbfSDavid du Colombier 	Ipifc *ifc;
7180ee5cbfSDavid du Colombier 	Block *bp;
7280ee5cbfSDavid du Colombier 	LB *lb;
7380ee5cbfSDavid du Colombier 
7480ee5cbfSDavid du Colombier 	ifc = a;
7580ee5cbfSDavid du Colombier 	lb = ifc->arg;
7680ee5cbfSDavid du Colombier 	lb->readp = up;	/* hide identity under a rock for unbind */
7780ee5cbfSDavid du Colombier 	if(waserror()){
7880ee5cbfSDavid du Colombier 		lb->readp = 0;
7980ee5cbfSDavid du Colombier 		pexit("hangup", 1);
8080ee5cbfSDavid du Colombier 	}
8180ee5cbfSDavid du Colombier 	for(;;){
8280ee5cbfSDavid du Colombier 		bp = qbread(lb->q, Maxtu);
8380ee5cbfSDavid du Colombier 		if(bp == nil)
8480ee5cbfSDavid du Colombier 			continue;
8580ee5cbfSDavid du Colombier 		ifc->in++;
8680ee5cbfSDavid du Colombier 		if(!canrlock(ifc)){
8780ee5cbfSDavid du Colombier 			freeb(bp);
8880ee5cbfSDavid du Colombier 			continue;
8980ee5cbfSDavid du Colombier 		}
9080ee5cbfSDavid du Colombier 		if(waserror()){
9180ee5cbfSDavid du Colombier 			runlock(ifc);
9280ee5cbfSDavid du Colombier 			nexterror();
9380ee5cbfSDavid du Colombier 		}
9480ee5cbfSDavid du Colombier 		if(ifc->lifc == nil)
9580ee5cbfSDavid du Colombier 			freeb(bp);
9680ee5cbfSDavid du Colombier 		else
97*3ff48bf5SDavid du Colombier 			ipiput4(lb->f, ifc, bp);
9880ee5cbfSDavid du Colombier 		runlock(ifc);
9980ee5cbfSDavid du Colombier 		poperror();
10080ee5cbfSDavid du Colombier 	}
10180ee5cbfSDavid du Colombier }
10280ee5cbfSDavid du Colombier 
10380ee5cbfSDavid du Colombier Medium loopbackmedium =
10480ee5cbfSDavid du Colombier {
10580ee5cbfSDavid du Colombier .hsize=		0,
10680ee5cbfSDavid du Colombier .minmtu=	0,
10780ee5cbfSDavid du Colombier .maxmtu=	Maxtu,
10880ee5cbfSDavid du Colombier .maclen=	0,
10980ee5cbfSDavid du Colombier .name=		"loopback",
11080ee5cbfSDavid du Colombier .bind=		loopbackbind,
11180ee5cbfSDavid du Colombier .unbind=	loopbackunbind,
11280ee5cbfSDavid du Colombier .bwrite=	loopbackbwrite,
11380ee5cbfSDavid du Colombier };
11480ee5cbfSDavid du Colombier 
11580ee5cbfSDavid du Colombier void
11680ee5cbfSDavid du Colombier loopbackmediumlink(void)
11780ee5cbfSDavid du Colombier {
11880ee5cbfSDavid du Colombier 	addipmedium(&loopbackmedium);
11980ee5cbfSDavid du Colombier }
120