PacketBuffer.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /**
  2. * @file PacketBuffer.c
  3. * @author Ambroz Bizjak <ambrop7@gmail.com>
  4. *
  5. * @section LICENSE
  6. *
  7. * This file is part of BadVPN.
  8. *
  9. * BadVPN is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2
  11. * as published by the Free Software Foundation.
  12. *
  13. * BadVPN is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License along
  19. * with this program; if not, write to the Free Software Foundation, Inc.,
  20. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  21. */
  22. #include <stdlib.h>
  23. #include <misc/debug.h>
  24. #include <flow/PacketBuffer.h>
  25. static int call_recv (PacketBuffer *buf, uint8_t *data, int *len);
  26. static int call_send (PacketBuffer *buf, uint8_t *data, int len);
  27. static int try_recv (PacketBuffer *buf);
  28. static int try_send (PacketBuffer *buf);
  29. static void input_handler_done (PacketBuffer *buf, int in_len);
  30. static void output_handler_done (PacketBuffer *buf);
  31. static void job_handler (PacketBuffer *buf);
  32. int call_recv (PacketBuffer *buf, uint8_t *data, int *len)
  33. {
  34. ASSERT(!PacketRecvInterface_InClient(buf->input))
  35. DEAD_ENTER(buf->dead)
  36. int res = PacketRecvInterface_Receiver_Recv(buf->input, data, len);
  37. if (DEAD_LEAVE(buf->dead)) {
  38. return -1;
  39. }
  40. ASSERT(res == 0 || res == 1)
  41. if (res) {
  42. ASSERT(*len >= 0)
  43. ASSERT(*len <= buf->input_mtu)
  44. }
  45. return res;
  46. }
  47. int call_send (PacketBuffer *buf, uint8_t *data, int len)
  48. {
  49. ASSERT(len >= 0)
  50. ASSERT(len <= buf->input_mtu)
  51. ASSERT(!PacketPassInterface_InClient(buf->output))
  52. DEAD_ENTER(buf->dead)
  53. int res = PacketPassInterface_Sender_Send(buf->output, data, len);
  54. if (DEAD_LEAVE(buf->dead)) {
  55. return -1;
  56. }
  57. ASSERT(res == 0 || res == 1)
  58. return res;
  59. }
  60. int try_recv (PacketBuffer *buf)
  61. {
  62. ASSERT(buf->buf.input_avail >= buf->input_mtu)
  63. ASSERT(!PacketRecvInterface_InClient(buf->input))
  64. ASSERT(!PacketPassInterface_InClient(buf->output))
  65. do {
  66. // receive packet
  67. int in_len;
  68. int res;
  69. if ((res = call_recv(buf, buf->buf.input_dest, &in_len)) < 0) {
  70. return -1;
  71. }
  72. if (!res) {
  73. // input busy, continue in input_handler_done
  74. return 0;
  75. }
  76. // remember if buffer is empty
  77. int was_empty = (buf->buf.output_avail < 0);
  78. // submit packet to buffer
  79. ChunkBuffer2_SubmitPacket(&buf->buf, in_len);
  80. // if buffer was empty, start sending
  81. if (was_empty) {
  82. if (try_send(buf) < 0) {
  83. return -1;
  84. }
  85. }
  86. } while (buf->buf.input_avail >= buf->input_mtu);
  87. return 0;
  88. }
  89. int try_send (PacketBuffer *buf)
  90. {
  91. ASSERT(buf->buf.output_avail >= 0)
  92. ASSERT(!PacketRecvInterface_InClient(buf->input))
  93. ASSERT(!PacketPassInterface_InClient(buf->output))
  94. do {
  95. // send packet
  96. int res;
  97. if ((res = call_send(buf, buf->buf.output_dest, buf->buf.output_avail)) < 0) {
  98. return -1;
  99. }
  100. if (!res) {
  101. // output busy, continue in output_handler_done
  102. return 0;
  103. }
  104. // remove packet from buffer
  105. ChunkBuffer2_ConsumePacket(&buf->buf);
  106. } while (buf->buf.output_avail >= 0);
  107. return 0;
  108. }
  109. void input_handler_done (PacketBuffer *buf, int in_len)
  110. {
  111. ASSERT(in_len >= 0)
  112. ASSERT(in_len <= buf->input_mtu)
  113. ASSERT(!PacketRecvInterface_InClient(buf->input))
  114. ASSERT(!PacketPassInterface_InClient(buf->output))
  115. // remember if buffer is empty
  116. int was_empty = (buf->buf.output_avail < 0);
  117. // submit packet to buffer
  118. ChunkBuffer2_SubmitPacket(&buf->buf, in_len);
  119. // if buffer was empty, try sending
  120. if (was_empty) {
  121. if (try_send(buf) < 0) {
  122. return;
  123. }
  124. }
  125. // try receiving more
  126. if (buf->buf.input_avail >= buf->input_mtu) {
  127. try_recv(buf);
  128. return;
  129. }
  130. }
  131. void output_handler_done (PacketBuffer *buf)
  132. {
  133. ASSERT(!PacketRecvInterface_InClient(buf->input))
  134. ASSERT(!PacketPassInterface_InClient(buf->output))
  135. // remember if buffer is full
  136. int was_full = (buf->buf.input_avail < buf->input_mtu);
  137. // remove packet from buffer
  138. ChunkBuffer2_ConsumePacket(&buf->buf);
  139. // try sending more
  140. if (buf->buf.output_avail >= 0) {
  141. if (try_send(buf) < 0) {
  142. return;
  143. }
  144. }
  145. // try receiving
  146. if (was_full && buf->buf.input_avail >= buf->input_mtu) {
  147. try_recv(buf);
  148. return;
  149. }
  150. }
  151. void job_handler (PacketBuffer *buf)
  152. {
  153. try_recv(buf);
  154. return;
  155. }
  156. int PacketBuffer_Init (PacketBuffer *buf, PacketRecvInterface *input, PacketPassInterface *output, int num_packets, BPendingGroup *pg)
  157. {
  158. ASSERT(PacketPassInterface_GetMTU(output) >= PacketRecvInterface_GetMTU(input))
  159. ASSERT(num_packets > 0)
  160. // init arguments
  161. buf->input = input;
  162. buf->output = output;
  163. // init dead var
  164. DEAD_INIT(buf->dead);
  165. // init input
  166. PacketRecvInterface_Receiver_Init(buf->input, (PacketRecvInterface_handler_done)input_handler_done, buf);
  167. // set input MTU
  168. buf->input_mtu = PacketRecvInterface_GetMTU(buf->input);
  169. // init output
  170. PacketPassInterface_Sender_Init(buf->output, (PacketPassInterface_handler_done)output_handler_done, buf);
  171. // allocate buffer
  172. int num_blocks = CHUNKBUFFER2_MAKE_NUMBLOCKS(buf->input_mtu, num_packets);
  173. if (!(buf->buf_data = malloc(num_blocks * sizeof(struct ChunkBuffer2_block)))) {
  174. goto fail0;
  175. }
  176. // init buffer
  177. ChunkBuffer2_Init(&buf->buf, buf->buf_data, num_blocks, buf->input_mtu);
  178. // init start job
  179. BPending_Init(&buf->start_job, pg, (BPending_handler)job_handler, buf);
  180. BPending_Set(&buf->start_job);
  181. // init debug object
  182. DebugObject_Init(&buf->d_obj);
  183. return 1;
  184. fail0:
  185. return 0;
  186. }
  187. void PacketBuffer_Free (PacketBuffer *buf)
  188. {
  189. // free debug object
  190. DebugObject_Free(&buf->d_obj);
  191. // free start job
  192. BPending_Free(&buf->start_job);
  193. // free buffer
  194. free(buf->buf_data);
  195. // free dead var
  196. DEAD_KILL(buf->dead);
  197. }