xref: /plan9-contrib/sys/src/9/ip/loopbackmedium.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
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
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(128*1024, 1, nil, nil);
33 	ifc->arg = lb;
34 
35 	kproc("loopbackread", loopbackread, ifc);
36 
37 }
38 
39 static void
40 loopbackunbind(Ipifc *ifc)
41 {
42 	LB *lb = ifc->arg;
43 
44 	if(lb->readp)
45 		postnote(lb->readp, 1, "unbind", 0);
46 
47 	/* wait for reader to die */
48 	while(lb->readp != 0)
49 		tsleep(&up->sleep, return0, 0, 300);
50 
51 	/* clean up */
52 	qfree(lb->q);
53 	free(lb);
54 }
55 
56 static void
57 loopbackbwrite(Ipifc *ifc, Block *bp, int, uchar*)
58 {
59 	LB *lb;
60 
61 	lb = ifc->arg;
62 	if(qpass(lb->q, bp) < 0)
63 		ifc->outerr++;
64 	ifc->out++;
65 }
66 
67 static void
68 loopbackread(void *a)
69 {
70 	Ipifc *ifc;
71 	Block *bp;
72 	LB *lb;
73 
74 	ifc = a;
75 	lb = ifc->arg;
76 	lb->readp = up;	/* hide identity under a rock for unbind */
77 	if(waserror()){
78 		lb->readp = 0;
79 		pexit("hangup", 1);
80 	}
81 	for(;;){
82 		bp = qbread(lb->q, Maxtu);
83 		if(bp == nil)
84 			continue;
85 		ifc->in++;
86 		if(!canrlock(ifc)){
87 			freeb(bp);
88 			continue;
89 		}
90 		if(waserror()){
91 			runlock(ifc);
92 			nexterror();
93 		}
94 		if(ifc->lifc == nil)
95 			freeb(bp);
96 		else
97 			ipiput(lb->f, ifc, bp);
98 		runlock(ifc);
99 		poperror();
100 	}
101 }
102 
103 Medium loopbackmedium =
104 {
105 .hsize=		0,
106 .minmtu=	0,
107 .maxmtu=	Maxtu,
108 .maclen=	0,
109 .name=		"loopback",
110 .bind=		loopbackbind,
111 .unbind=	loopbackunbind,
112 .bwrite=	loopbackbwrite,
113 };
114 
115 void
116 loopbackmediumlink(void)
117 {
118 	addipmedium(&loopbackmedium);
119 }
120