loopbackmedium.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "u.h"
  10. #include "../port/lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "../port/error.h"
  15. #include "ip.h"
  16. enum
  17. {
  18. Maxtu= 16*1024,
  19. };
  20. typedef struct LB LB;
  21. struct LB
  22. {
  23. Proc *readp;
  24. Queue *q;
  25. Fs *f;
  26. };
  27. static void loopbackread(void *a);
  28. static void
  29. loopbackbind(Ipifc *ifc, int i, char**argv)
  30. {
  31. LB *lb;
  32. lb = smalloc(sizeof(*lb));
  33. lb->f = ifc->conv->p->f;
  34. lb->q = qopen(1024*1024, Qmsg, nil, nil);
  35. ifc->arg = lb;
  36. ifc->mbps = 1000;
  37. kproc("loopbackread", loopbackread, ifc);
  38. }
  39. static void
  40. loopbackunbind(Ipifc *ifc)
  41. {
  42. Proc *up = externup();
  43. LB *lb = ifc->arg;
  44. if(lb->readp)
  45. postnote(lb->readp, 1, "unbind", 0);
  46. /* wait for reader to die */
  47. while(lb->readp != 0)
  48. tsleep(&up->sleep, return0, 0, 300);
  49. /* clean up */
  50. qfree(lb->q);
  51. free(lb);
  52. }
  53. static void
  54. loopbackbwrite(Ipifc *ifc, Block *bp, int i, uint8_t *c)
  55. {
  56. LB *lb;
  57. lb = ifc->arg;
  58. if(qpass(lb->q, bp) < 0)
  59. ifc->outerr++;
  60. ifc->out++;
  61. }
  62. static void
  63. loopbackread(void *a)
  64. {
  65. Proc *up = externup();
  66. Ipifc *ifc;
  67. Block *bp;
  68. LB *lb;
  69. ifc = a;
  70. lb = ifc->arg;
  71. lb->readp = up; /* hide identity under a rock for unbind */
  72. if(waserror()){
  73. lb->readp = 0;
  74. pexit("hangup", 1);
  75. }
  76. for(;;){
  77. bp = qbread(lb->q, Maxtu);
  78. if(bp == nil)
  79. continue;
  80. ifc->in++;
  81. if(!canrlock(&ifc->rwl)){
  82. freeb(bp);
  83. continue;
  84. }
  85. if(waserror()){
  86. runlock(&ifc->rwl);
  87. nexterror();
  88. }
  89. if(ifc->lifc == nil)
  90. freeb(bp);
  91. else
  92. ipiput4(lb->f, ifc, bp);
  93. runlock(&ifc->rwl);
  94. poperror();
  95. }
  96. }
  97. Medium loopbackmedium =
  98. {
  99. .hsize= 0,
  100. .mintu= 0,
  101. .maxtu= Maxtu,
  102. .maclen= 0,
  103. .name= "loopback",
  104. .bind= loopbackbind,
  105. .unbind= loopbackunbind,
  106. .bwrite= loopbackbwrite,
  107. };
  108. void
  109. loopbackmediumlink(void)
  110. {
  111. addipmedium(&loopbackmedium);
  112. }