PacketRecvInterface.h 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. /**
  2. * @file PacketRecvInterface.h
  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. * @section DESCRIPTION
  23. *
  24. * Interface allowing a packet receiver to receive data packets from a packet sender.
  25. */
  26. #ifndef BADVPN_FLOW_PACKETRECVINTERFACE_H
  27. #define BADVPN_FLOW_PACKETRECVINTERFACE_H
  28. #include <stdint.h>
  29. #include <stddef.h>
  30. #include <misc/dead.h>
  31. #include <misc/debug.h>
  32. #include <system/DebugObject.h>
  33. /**
  34. * Handler called at the sender when {@link PacketRecvInterface_Receiver_Recv} is called
  35. * from the receiver.
  36. * It is guaranteed that the interface is in not receiving state.
  37. * It is guaranteed that the handler is not being called from within Recv or Cancel handlers.
  38. *
  39. * @param user value supplied to {@link PacketRecvInterface_Init}
  40. * @param data pointer to the buffer where the packet is to be written. Will have space
  41. * for MTU bytes. May be NULL if MTU is 0.
  42. * @param data_len if the packet was written immediately, must be set to its length
  43. * @return - 1 if the sender provides a packet immediately. The interface remains in
  44. * not receiving state. The sender may not use the provided buffer after the handler
  45. * returns.
  46. * - 0 if the sender cannot provide a packet immediately. The interface enters
  47. * receiving state as the handler returns. The sender must write a packet to the
  48. * provided buffer and call {@link PacketRecvInterface_Done} when it's done.
  49. */
  50. typedef int (*PacketRecvInterface_handler_recv) (void *user, uint8_t *data, int *data_len);
  51. /**
  52. * Handler called at the receiver when {@link PacketRecvInterface_Done} is called from the sender.
  53. * The sender will no longer use the buffer it was provided with.
  54. * It is guaranteed that the interface was in receiving state.
  55. * The interface enters not receiving state before the handler is called.
  56. * It is guaranteed that the handler is not being called from within Recv, Cancel or Done handlers.
  57. *
  58. * @param user value supplied to {@link PacketRecvInterface_Receiver_Init}
  59. * @param data_len size of the packet that was written to the buffer. Will be >=0 and <=MTU.
  60. */
  61. typedef void (*PacketRecvInterface_handler_done) (void *user, int data_len);
  62. /**
  63. * Interface allowing a packet receiver to receive data packets from a packet sender.
  64. * The receiver receives a packet by providing the sender with a buffer. The sender
  65. * may then either provide the packet immediately, or tell the receiver to wait for
  66. * the packet to be available and inform it when it's done.
  67. */
  68. typedef struct {
  69. DebugObject d_obj;
  70. // sender data
  71. int mtu;
  72. PacketRecvInterface_handler_recv handler_recv;
  73. void *user_sender;
  74. // receiver data
  75. PacketRecvInterface_handler_done handler_done;
  76. void *user_receiver;
  77. // debug vars
  78. #ifndef NDEBUG
  79. dead_t debug_dead;
  80. int debug_busy;
  81. int debug_in_recv;
  82. int debug_in_done;
  83. #endif
  84. } PacketRecvInterface;
  85. /**
  86. * Initializes the interface. The receiver portion must also be initialized
  87. * with {@link PacketRecvInterface_Receiver_Init} before I/O can start.
  88. * The interface is initialized in not receiving state.
  89. *
  90. * @param i the object
  91. * @param mtu maximum packet size the sender can provide. Must be >=0.
  92. * @param handler_recv handler called when the receiver wants to receive a packet
  93. * @param user arbitrary value that will be passed to sender callback functions
  94. */
  95. static void PacketRecvInterface_Init (PacketRecvInterface *i, int mtu, PacketRecvInterface_handler_recv handler_recv, void *user);
  96. /**
  97. * Frees the interface.
  98. *
  99. * @param i the object
  100. */
  101. static void PacketRecvInterface_Free (PacketRecvInterface *i);
  102. /**
  103. * Notifies the receiver that the sender has finished providing the packet being received.
  104. * The sender must not use the buffer it was provided any more.
  105. * The interface must be in receiving state.
  106. * The interface enters not receiving state before notifying the receiver.
  107. * Must not be called from within Recv, Cancel or Done handlers.
  108. *
  109. * Be aware that the receiver may attempt to receive packets from within this function.
  110. *
  111. * @param i the object
  112. * @param data_len size of the packet written to the buffer. Must be >=0 and <=MTU.
  113. */
  114. static void PacketRecvInterface_Done (PacketRecvInterface *i, int data_len);
  115. /**
  116. * Returns the maximum packet size the sender can provide.
  117. *
  118. * @return maximum packet size. Will be >=0.
  119. */
  120. static int PacketRecvInterface_GetMTU (PacketRecvInterface *i);
  121. /**
  122. * Initializes the receiver portion of the interface.
  123. *
  124. * @param i the object
  125. * @param handler_done handler called when the sender has finished providing a packet
  126. * @param user arbitrary value that will be passed to receiver callback functions
  127. */
  128. static void PacketRecvInterface_Receiver_Init (PacketRecvInterface *i, PacketRecvInterface_handler_done handler_done, void *user);
  129. /**
  130. * Attempts to receive a packet.
  131. * The interface must be in not receiving state.
  132. * Must not be called from within Recv or Cancel handlers.
  133. *
  134. * @param i the object
  135. * @param data pointer to the buffer where the packet is to be written. Must have space
  136. * for MTU bytes. Ignored if MTU is 0.
  137. * @param data_len will contain the size of the packet if it was provided immediately
  138. * @return - 1 if a packet was provided by the sender immediately. The buffer is no longer needed.
  139. * The interface remains in not receiving state.
  140. * - 0 if a packet could not be provided immediately.
  141. * The interface enters receiving state, and the buffer must stay accessible while the
  142. * sender is providing the packet. When the sender is done providing it, the
  143. * {@link PacketRecvInterface_handler_done} handler will be called.
  144. */
  145. static int PacketRecvInterface_Receiver_Recv (PacketRecvInterface *i, uint8_t *data, int *data_len);
  146. #ifndef NDEBUG
  147. /**
  148. * Determines if we are in a Recv call.
  149. * Only available if NDEBUG is not defined.
  150. *
  151. * @param i the object
  152. * @return 1 if in a Recv call, 0 if not
  153. */
  154. static int PacketRecvInterface_InClient (PacketRecvInterface *i);
  155. /**
  156. * Determines if we are in a Done call.
  157. * Only available if NDEBUG is not defined.
  158. *
  159. * @param i the object
  160. * @return 1 if in a Done call, 0 if not
  161. */
  162. static int PacketRecvInterface_InDone (PacketRecvInterface *i);
  163. #endif
  164. void PacketRecvInterface_Init (PacketRecvInterface *i, int mtu, PacketRecvInterface_handler_recv handler_recv, void *user)
  165. {
  166. ASSERT(mtu >= 0)
  167. i->mtu = mtu;
  168. i->handler_recv = handler_recv;
  169. i->user_sender = user;
  170. i->handler_done = NULL;
  171. i->user_receiver = NULL;
  172. // init debugging
  173. #ifndef NDEBUG
  174. DEAD_INIT(i->debug_dead);
  175. i->debug_busy = 0;
  176. i->debug_in_recv = 0;
  177. i->debug_in_done = 0;
  178. #endif
  179. // init debug object
  180. DebugObject_Init(&i->d_obj);
  181. }
  182. void PacketRecvInterface_Free (PacketRecvInterface *i)
  183. {
  184. // free debug object
  185. DebugObject_Free(&i->d_obj);
  186. // free debugging
  187. #ifndef NDEBUG
  188. DEAD_KILL(i->debug_dead);
  189. #endif
  190. }
  191. void PacketRecvInterface_Done (PacketRecvInterface *i, int data_len)
  192. {
  193. ASSERT(i->debug_busy)
  194. ASSERT(!i->debug_in_recv)
  195. ASSERT(!i->debug_in_done)
  196. ASSERT(data_len >= 0)
  197. ASSERT(data_len <= i->mtu)
  198. #ifndef NDEBUG
  199. i->debug_busy = 0;
  200. i->debug_in_done = 1;
  201. DEAD_ENTER(i->debug_dead)
  202. #endif
  203. i->handler_done(i->user_receiver, data_len);
  204. #ifndef NDEBUG
  205. if (DEAD_LEAVE(i->debug_dead)) {
  206. return;
  207. }
  208. i->debug_in_done = 0;
  209. #endif
  210. }
  211. int PacketRecvInterface_GetMTU (PacketRecvInterface *i)
  212. {
  213. return i->mtu;
  214. }
  215. void PacketRecvInterface_Receiver_Init (PacketRecvInterface *i, PacketRecvInterface_handler_done handler_done, void *user)
  216. {
  217. i->handler_done = handler_done;
  218. i->user_receiver = user;
  219. }
  220. int PacketRecvInterface_Receiver_Recv (PacketRecvInterface *i, uint8_t *data, int *data_len)
  221. {
  222. ASSERT(!i->debug_busy)
  223. ASSERT(!i->debug_in_recv)
  224. ASSERT(!(i->mtu > 0) || data)
  225. ASSERT(data_len)
  226. #ifndef NDEBUG
  227. i->debug_in_recv = 1;
  228. DEAD_ENTER(i->debug_dead)
  229. #endif
  230. int res = i->handler_recv(i->user_sender, data, data_len);
  231. #ifndef NDEBUG
  232. if (DEAD_LEAVE(i->debug_dead)) {
  233. return -1;
  234. }
  235. ASSERT(i->debug_in_recv)
  236. i->debug_in_recv = 0;
  237. ASSERT(res == 0 || res == 1)
  238. ASSERT(!(res == 1) || (*data_len >= 0 && *data_len <= i->mtu))
  239. if (!res) {
  240. i->debug_busy = 1;
  241. }
  242. #endif
  243. return res;
  244. }
  245. #ifndef NDEBUG
  246. int PacketRecvInterface_InClient (PacketRecvInterface *i)
  247. {
  248. return i->debug_in_recv;
  249. }
  250. int PacketRecvInterface_InDone (PacketRecvInterface *i)
  251. {
  252. return i->debug_in_done;
  253. }
  254. #endif
  255. #endif