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(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
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
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
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
117 loopbackmediumlink(void)
118 {
119 addipmedium(&loopbackmedium);
120 }
Cache object: ae5e7c1b9e8cc2a358ec697dc9dce2ad
|