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