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