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