BPRFileDesc.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /**
  2. * @file BPRFileDesc.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/offset.h>
  24. #include <misc/debug.h>
  25. #include <nspr_support/BPRFileDesc.h>
  26. static void init_handlers (BPRFileDesc *obj);
  27. static int get_event_index (int event);
  28. static int get_bsocket_events (PRUint16 pr_events);
  29. static void init_bottom (BPRFileDesc *obj);
  30. static void free_bottom (BPRFileDesc *obj);
  31. static void update_bottom (BPRFileDesc *obj);
  32. static void set_bottom_events (BPRFileDesc *obj, PRInt16 new_events);
  33. static void socket_handler (BPRFileDesc *obj, int event);
  34. void init_handlers (BPRFileDesc *obj)
  35. {
  36. int i;
  37. for (i = 0; i < 2; i++) {
  38. obj->handlers[i] = NULL;
  39. }
  40. }
  41. int get_event_index (int event)
  42. {
  43. switch (event) {
  44. case PR_POLL_READ:
  45. return 0;
  46. case PR_POLL_WRITE:
  47. return 1;
  48. default:
  49. ASSERT(0)
  50. return 0;
  51. }
  52. }
  53. int get_bsocket_events (PRUint16 pr_events)
  54. {
  55. int res = 0;
  56. if (pr_events&PR_POLL_READ) {
  57. res |= BSOCKET_READ;
  58. }
  59. if (pr_events&PR_POLL_WRITE) {
  60. res |= BSOCKET_WRITE;
  61. }
  62. return res;
  63. }
  64. void init_bottom (BPRFileDesc *obj)
  65. {
  66. PRFileDesc *layer = obj->prfd;
  67. do {
  68. if (layer->identity == bsocketprfiledesc_identity) {
  69. obj->bottom_type = BPRFILEDESC_BOTTOM_BSOCKET;
  70. obj->bottom = layer;
  71. BSocket_AddGlobalEventHandler((BSocket *)obj->bottom->secret, (BSocket_handler)socket_handler, obj);
  72. return;
  73. }
  74. layer = layer->lower;
  75. } while (layer);
  76. ASSERT(0)
  77. }
  78. void free_bottom (BPRFileDesc *obj)
  79. {
  80. switch (obj->bottom_type) {
  81. case BPRFILEDESC_BOTTOM_BSOCKET:
  82. BSocket_RemoveGlobalEventHandler((BSocket *)obj->bottom->secret);
  83. break;
  84. default:
  85. ASSERT(0)
  86. break;
  87. }
  88. }
  89. void update_bottom (BPRFileDesc *obj)
  90. {
  91. // calculate bottom events
  92. PRInt16 new_bottom_events = 0;
  93. PRInt16 new_flags;
  94. PRInt16 out_flags;
  95. if (obj->waitEvents&PR_POLL_READ) {
  96. new_flags = obj->prfd->methods->poll(obj->prfd, PR_POLL_READ, &out_flags);
  97. if ((new_flags&out_flags) == 0) {
  98. new_bottom_events |= new_flags;
  99. }
  100. }
  101. if (obj->waitEvents&PR_POLL_WRITE) {
  102. new_flags = obj->prfd->methods->poll(obj->prfd, PR_POLL_WRITE, &out_flags);
  103. if ((new_flags&out_flags) == 0) {
  104. new_bottom_events |= new_flags;
  105. }
  106. }
  107. switch (obj->bottom_type) {
  108. case BPRFILEDESC_BOTTOM_BSOCKET:
  109. BSocket_SetGlobalEvents((BSocket *)obj->bottom->secret, get_bsocket_events(new_bottom_events));
  110. break;
  111. default:
  112. ASSERT(0)
  113. break;
  114. }
  115. }
  116. void socket_handler (BPRFileDesc *obj, int events)
  117. {
  118. // make sure bottom events are not recalculated whenever an event
  119. // is disabled or enabled, it's faster to do it only once
  120. obj->in_handler = 1;
  121. // call handlers for all enabled events
  122. if (obj->waitEvents&PR_POLL_READ) {
  123. BPRFileDesc_DisableEvent(obj, PR_POLL_READ);
  124. DEAD_ENTER(obj->dead)
  125. obj->handlers[0](obj->handlers_user[0], PR_POLL_READ);
  126. if (DEAD_LEAVE(obj->dead)) {
  127. return;
  128. }
  129. }
  130. if (obj->waitEvents&PR_POLL_WRITE) {
  131. BPRFileDesc_DisableEvent(obj, PR_POLL_WRITE);
  132. DEAD_ENTER(obj->dead)
  133. obj->handlers[1](obj->handlers_user[1], PR_POLL_WRITE);
  134. if (DEAD_LEAVE(obj->dead)) {
  135. return;
  136. }
  137. }
  138. // recalculate bottom events
  139. obj->in_handler = 0;
  140. update_bottom(obj);
  141. }
  142. void BPRFileDesc_Init (BPRFileDesc *obj, PRFileDesc *prfd)
  143. {
  144. DEAD_INIT(obj->dead);
  145. obj->prfd = prfd;
  146. init_handlers(obj);
  147. obj->waitEvents = 0;
  148. init_bottom(obj);
  149. obj->in_handler = 0;
  150. // init debug object
  151. DebugObject_Init(&obj->d_obj);
  152. }
  153. void BPRFileDesc_Free (BPRFileDesc *obj)
  154. {
  155. // free debug object
  156. DebugObject_Free(&obj->d_obj);
  157. free_bottom(obj);
  158. DEAD_KILL(obj->dead);
  159. }
  160. void BPRFileDesc_AddEventHandler (BPRFileDesc *obj, PRInt16 event, BPRFileDesc_handler handler, void *user)
  161. {
  162. ASSERT(handler)
  163. // get index
  164. int index = get_event_index(event);
  165. // event must not have handler
  166. ASSERT(!obj->handlers[index])
  167. // change handler
  168. obj->handlers[index] = handler;
  169. obj->handlers_user[index] = user;
  170. }
  171. void BPRFileDesc_RemoveEventHandler (BPRFileDesc *obj, PRInt16 event)
  172. {
  173. // get index
  174. int index = get_event_index(event);
  175. // event must have handler
  176. ASSERT(obj->handlers[index])
  177. // disable event if enabled
  178. if (obj->waitEvents&event) {
  179. BPRFileDesc_DisableEvent(obj, event);
  180. }
  181. // change handler
  182. obj->handlers[index] = NULL;
  183. }
  184. void BPRFileDesc_EnableEvent (BPRFileDesc *obj, PRInt16 event)
  185. {
  186. // get index
  187. int index = get_event_index(event);
  188. // event must have handler
  189. ASSERT(obj->handlers[index])
  190. // event must not be enabled
  191. ASSERT(!(obj->waitEvents&event))
  192. // update events
  193. obj->waitEvents |= event;
  194. // update bottom
  195. if (!obj->in_handler) {
  196. update_bottom(obj);
  197. }
  198. }
  199. void BPRFileDesc_DisableEvent (BPRFileDesc *obj, PRInt16 event)
  200. {
  201. // get index
  202. int index = get_event_index(event);
  203. // event must have handler
  204. ASSERT(obj->handlers[index])
  205. // event must be enabled
  206. ASSERT(obj->waitEvents&event)
  207. // update events
  208. obj->waitEvents &= ~event;
  209. // update bottom
  210. if (!obj->in_handler) {
  211. update_bottom(obj);
  212. }
  213. }