loopbackmedium.c (1665B)
1 #include "u.h" 2 #include "lib.h" 3 #include "mem.h" 4 #include "dat.h" 5 #include "fns.h" 6 #include "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 }