xref: /plan9-contrib/sys/src/9k/ip/loopbackmedium.c (revision 9ef1f84b659abcb917c5c090acbce0772e494f21)
1*9ef1f84bSDavid du Colombier #include "u.h"
2*9ef1f84bSDavid du Colombier #include "../port/lib.h"
3*9ef1f84bSDavid du Colombier #include "mem.h"
4*9ef1f84bSDavid du Colombier #include "dat.h"
5*9ef1f84bSDavid du Colombier #include "fns.h"
6*9ef1f84bSDavid du Colombier #include "../port/error.h"
7*9ef1f84bSDavid du Colombier 
8*9ef1f84bSDavid du Colombier #include "ip.h"
9*9ef1f84bSDavid du Colombier 
10*9ef1f84bSDavid du Colombier enum
11*9ef1f84bSDavid du Colombier {
12*9ef1f84bSDavid du Colombier 	Maxtu=	16*1024,
13*9ef1f84bSDavid du Colombier };
14*9ef1f84bSDavid du Colombier 
15*9ef1f84bSDavid du Colombier typedef struct LB LB;
16*9ef1f84bSDavid du Colombier struct LB
17*9ef1f84bSDavid du Colombier {
18*9ef1f84bSDavid du Colombier 	Proc	*readp;
19*9ef1f84bSDavid du Colombier 	Queue	*q;
20*9ef1f84bSDavid du Colombier 	Fs	*f;
21*9ef1f84bSDavid du Colombier };
22*9ef1f84bSDavid du Colombier 
23*9ef1f84bSDavid du Colombier static void loopbackread(void *a);
24*9ef1f84bSDavid du Colombier 
25*9ef1f84bSDavid du Colombier static void
loopbackbind(Ipifc * ifc,int,char **)26*9ef1f84bSDavid du Colombier loopbackbind(Ipifc *ifc, int, char**)
27*9ef1f84bSDavid du Colombier {
28*9ef1f84bSDavid du Colombier 	LB *lb;
29*9ef1f84bSDavid du Colombier 
30*9ef1f84bSDavid du Colombier 	lb = smalloc(sizeof(*lb));
31*9ef1f84bSDavid du Colombier 	lb->f = ifc->conv->p->f;
32*9ef1f84bSDavid du Colombier 	lb->q = qopen(1024*1024, Qmsg, nil, nil);
33*9ef1f84bSDavid du Colombier 	ifc->arg = lb;
34*9ef1f84bSDavid du Colombier 	ifc->mbps = 1000;
35*9ef1f84bSDavid du Colombier 
36*9ef1f84bSDavid du Colombier 	kproc("loopbackread", loopbackread, ifc);
37*9ef1f84bSDavid du Colombier 
38*9ef1f84bSDavid du Colombier }
39*9ef1f84bSDavid du Colombier 
40*9ef1f84bSDavid du Colombier static void
loopbackunbind(Ipifc * ifc)41*9ef1f84bSDavid du Colombier loopbackunbind(Ipifc *ifc)
42*9ef1f84bSDavid du Colombier {
43*9ef1f84bSDavid du Colombier 	LB *lb = ifc->arg;
44*9ef1f84bSDavid du Colombier 
45*9ef1f84bSDavid du Colombier 	if(lb->readp)
46*9ef1f84bSDavid du Colombier 		postnote(lb->readp, 1, "unbind", 0);
47*9ef1f84bSDavid du Colombier 
48*9ef1f84bSDavid du Colombier 	/* wait for reader to die */
49*9ef1f84bSDavid du Colombier 	while(lb->readp != 0)
50*9ef1f84bSDavid du Colombier 		tsleep(&up->sleep, return0, 0, 300);
51*9ef1f84bSDavid du Colombier 
52*9ef1f84bSDavid du Colombier 	/* clean up */
53*9ef1f84bSDavid du Colombier 	qfree(lb->q);
54*9ef1f84bSDavid du Colombier 	free(lb);
55*9ef1f84bSDavid du Colombier }
56*9ef1f84bSDavid du Colombier 
57*9ef1f84bSDavid du Colombier static void
loopbackbwrite(Ipifc * ifc,Block * bp,int,uchar *)58*9ef1f84bSDavid du Colombier loopbackbwrite(Ipifc *ifc, Block *bp, int, uchar*)
59*9ef1f84bSDavid du Colombier {
60*9ef1f84bSDavid du Colombier 	LB *lb;
61*9ef1f84bSDavid du Colombier 
62*9ef1f84bSDavid du Colombier 	lb = ifc->arg;
63*9ef1f84bSDavid du Colombier 	if(qpass(lb->q, bp) < 0)
64*9ef1f84bSDavid du Colombier 		ifc->outerr++;
65*9ef1f84bSDavid du Colombier 	ifc->out++;
66*9ef1f84bSDavid du Colombier }
67*9ef1f84bSDavid du Colombier 
68*9ef1f84bSDavid du Colombier static void
loopbackread(void * a)69*9ef1f84bSDavid du Colombier loopbackread(void *a)
70*9ef1f84bSDavid du Colombier {
71*9ef1f84bSDavid du Colombier 	Ipifc *ifc;
72*9ef1f84bSDavid du Colombier 	Block *bp;
73*9ef1f84bSDavid du Colombier 	LB *lb;
74*9ef1f84bSDavid du Colombier 
75*9ef1f84bSDavid du Colombier 	ifc = a;
76*9ef1f84bSDavid du Colombier 	lb = ifc->arg;
77*9ef1f84bSDavid du Colombier 	lb->readp = up;	/* hide identity under a rock for unbind */
78*9ef1f84bSDavid du Colombier 	if(waserror()){
79*9ef1f84bSDavid du Colombier 		lb->readp = 0;
80*9ef1f84bSDavid du Colombier 		pexit("hangup", 1);
81*9ef1f84bSDavid du Colombier 	}
82*9ef1f84bSDavid du Colombier 	for(;;){
83*9ef1f84bSDavid du Colombier 		bp = qbread(lb->q, Maxtu);
84*9ef1f84bSDavid du Colombier 		if(bp == nil)
85*9ef1f84bSDavid du Colombier 			continue;
86*9ef1f84bSDavid du Colombier 		ifc->in++;
87*9ef1f84bSDavid du Colombier 		if(!canrlock(ifc)){
88*9ef1f84bSDavid du Colombier 			freeb(bp);
89*9ef1f84bSDavid du Colombier 			continue;
90*9ef1f84bSDavid du Colombier 		}
91*9ef1f84bSDavid du Colombier 		if(waserror()){
92*9ef1f84bSDavid du Colombier 			runlock(ifc);
93*9ef1f84bSDavid du Colombier 			nexterror();
94*9ef1f84bSDavid du Colombier 		}
95*9ef1f84bSDavid du Colombier 		if(ifc->lifc == nil)
96*9ef1f84bSDavid du Colombier 			freeb(bp);
97*9ef1f84bSDavid du Colombier 		else
98*9ef1f84bSDavid du Colombier 			ipiput4(lb->f, ifc, bp);
99*9ef1f84bSDavid du Colombier 		runlock(ifc);
100*9ef1f84bSDavid du Colombier 		poperror();
101*9ef1f84bSDavid du Colombier 	}
102*9ef1f84bSDavid du Colombier }
103*9ef1f84bSDavid du Colombier 
104*9ef1f84bSDavid du Colombier Medium loopbackmedium =
105*9ef1f84bSDavid du Colombier {
106*9ef1f84bSDavid du Colombier .hsize=		0,
107*9ef1f84bSDavid du Colombier .mintu=		0,
108*9ef1f84bSDavid du Colombier .maxtu=		Maxtu,
109*9ef1f84bSDavid du Colombier .maclen=	0,
110*9ef1f84bSDavid du Colombier .name=		"loopback",
111*9ef1f84bSDavid du Colombier .bind=		loopbackbind,
112*9ef1f84bSDavid du Colombier .unbind=	loopbackunbind,
113*9ef1f84bSDavid du Colombier .bwrite=	loopbackbwrite,
114*9ef1f84bSDavid du Colombier };
115*9ef1f84bSDavid du Colombier 
116*9ef1f84bSDavid du Colombier void
loopbackmediumlink(void)117*9ef1f84bSDavid du Colombier loopbackmediumlink(void)
118*9ef1f84bSDavid du Colombier {
119*9ef1f84bSDavid du Colombier 	addipmedium(&loopbackmedium);
120*9ef1f84bSDavid du Colombier }
121