asyncengine 0.0.1.testing1 → 0.0.2.alpha1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (251) hide show
  1. data/README.markdown +3 -0
  2. data/Rakefile +38 -0
  3. data/asyncengine.gemspec +8 -4
  4. data/ext/asyncengine/ae_call_from_other_thread.c +106 -0
  5. data/ext/asyncengine/ae_call_from_other_thread.h +12 -0
  6. data/ext/asyncengine/ae_handle_common.c +193 -48
  7. data/ext/asyncengine/ae_handle_common.h +40 -13
  8. data/ext/asyncengine/ae_ip_utils.c +246 -0
  9. data/ext/asyncengine/ae_ip_utils.h +25 -0
  10. data/ext/asyncengine/ae_next_tick.c +81 -21
  11. data/ext/asyncengine/ae_next_tick.h +4 -2
  12. data/ext/asyncengine/ae_resolver.c +156 -0
  13. data/ext/asyncengine/ae_resolver.h +10 -0
  14. data/ext/asyncengine/ae_tcp.c +908 -0
  15. data/ext/asyncengine/ae_tcp.h +20 -0
  16. data/ext/asyncengine/ae_timer.c +355 -81
  17. data/ext/asyncengine/ae_timer.h +11 -4
  18. data/ext/asyncengine/ae_udp.c +579 -13
  19. data/ext/asyncengine/ae_udp.h +15 -2
  20. data/ext/asyncengine/ae_utils.c +192 -0
  21. data/ext/asyncengine/ae_utils.h +16 -0
  22. data/ext/asyncengine/asyncengine_ruby.c +469 -26
  23. data/ext/asyncengine/asyncengine_ruby.h +49 -11
  24. data/ext/asyncengine/debug.h +68 -0
  25. data/ext/asyncengine/extconf.rb +26 -2
  26. data/ext/asyncengine/ip_parser.c +5954 -0
  27. data/ext/asyncengine/ip_parser.h +16 -0
  28. data/ext/asyncengine/libuv/AUTHORS +16 -0
  29. data/ext/asyncengine/libuv/common.gypi +4 -4
  30. data/ext/asyncengine/libuv/config-mingw.mk +6 -6
  31. data/ext/asyncengine/libuv/config-unix.mk +13 -13
  32. data/ext/asyncengine/libuv/gyp_uv +5 -1
  33. data/ext/asyncengine/libuv/ibc_tests/exec_test.sh +8 -0
  34. data/ext/asyncengine/libuv/ibc_tests/uv_shutdown_write_issue.c +171 -0
  35. data/ext/asyncengine/libuv/ibc_tests/uv_tcp_close_while_connecting.c +102 -0
  36. data/ext/asyncengine/libuv/include/uv-private/ngx-queue.h +3 -1
  37. data/ext/asyncengine/libuv/include/uv-private/uv-unix.h +103 -50
  38. data/ext/asyncengine/libuv/include/uv-private/uv-win.h +76 -24
  39. data/ext/asyncengine/libuv/include/uv.h +353 -88
  40. data/ext/asyncengine/libuv/src/ares/ares__close_sockets.o +0 -0
  41. data/ext/asyncengine/libuv/src/ares/ares__get_hostent.o +0 -0
  42. data/ext/asyncengine/libuv/src/ares/ares__read_line.o +0 -0
  43. data/ext/asyncengine/libuv/src/ares/ares__timeval.o +0 -0
  44. data/ext/asyncengine/libuv/src/ares/ares_cancel.o +0 -0
  45. data/ext/asyncengine/libuv/src/ares/ares_data.o +0 -0
  46. data/ext/asyncengine/libuv/src/ares/ares_destroy.o +0 -0
  47. data/ext/asyncengine/libuv/src/ares/ares_expand_name.o +0 -0
  48. data/ext/asyncengine/libuv/src/ares/ares_expand_string.o +0 -0
  49. data/ext/asyncengine/libuv/src/ares/ares_fds.o +0 -0
  50. data/ext/asyncengine/libuv/src/ares/ares_free_hostent.o +0 -0
  51. data/ext/asyncengine/libuv/src/ares/ares_free_string.o +0 -0
  52. data/ext/asyncengine/libuv/src/ares/ares_gethostbyaddr.o +0 -0
  53. data/ext/asyncengine/libuv/src/ares/ares_gethostbyname.o +0 -0
  54. data/ext/asyncengine/libuv/src/ares/ares_getnameinfo.o +0 -0
  55. data/ext/asyncengine/libuv/src/ares/ares_getopt.o +0 -0
  56. data/ext/asyncengine/libuv/src/ares/ares_getsock.o +0 -0
  57. data/ext/asyncengine/libuv/src/ares/ares_init.o +0 -0
  58. data/ext/asyncengine/libuv/src/ares/ares_library_init.o +0 -0
  59. data/ext/asyncengine/libuv/src/ares/ares_llist.o +0 -0
  60. data/ext/asyncengine/libuv/src/ares/ares_mkquery.o +0 -0
  61. data/ext/asyncengine/libuv/src/ares/ares_nowarn.o +0 -0
  62. data/ext/asyncengine/libuv/src/ares/ares_options.o +0 -0
  63. data/ext/asyncengine/libuv/src/ares/ares_parse_a_reply.o +0 -0
  64. data/ext/asyncengine/libuv/src/ares/ares_parse_aaaa_reply.o +0 -0
  65. data/ext/asyncengine/libuv/src/ares/ares_parse_mx_reply.o +0 -0
  66. data/ext/asyncengine/libuv/src/ares/ares_parse_ns_reply.o +0 -0
  67. data/ext/asyncengine/libuv/src/ares/ares_parse_ptr_reply.o +0 -0
  68. data/ext/asyncengine/libuv/src/ares/ares_parse_srv_reply.o +0 -0
  69. data/ext/asyncengine/libuv/src/ares/ares_parse_txt_reply.o +0 -0
  70. data/ext/asyncengine/libuv/src/ares/ares_process.o +0 -0
  71. data/ext/asyncengine/libuv/src/ares/ares_query.o +0 -0
  72. data/ext/asyncengine/libuv/src/ares/ares_search.o +0 -0
  73. data/ext/asyncengine/libuv/src/ares/ares_send.o +0 -0
  74. data/ext/asyncengine/libuv/src/ares/ares_strcasecmp.o +0 -0
  75. data/ext/asyncengine/libuv/src/ares/ares_strdup.o +0 -0
  76. data/ext/asyncengine/libuv/src/ares/ares_strerror.o +0 -0
  77. data/ext/asyncengine/libuv/src/ares/ares_timeout.o +0 -0
  78. data/ext/asyncengine/libuv/src/ares/ares_version.o +0 -0
  79. data/ext/asyncengine/libuv/src/ares/ares_writev.o +0 -0
  80. data/ext/asyncengine/libuv/src/ares/bitncmp.o +0 -0
  81. data/ext/asyncengine/libuv/src/ares/inet_net_pton.o +0 -0
  82. data/ext/asyncengine/libuv/src/ares/inet_ntop.o +0 -0
  83. data/ext/asyncengine/libuv/src/cares.c +225 -0
  84. data/ext/asyncengine/libuv/src/cares.o +0 -0
  85. data/ext/asyncengine/libuv/src/fs-poll.c +237 -0
  86. data/ext/asyncengine/libuv/src/fs-poll.o +0 -0
  87. data/ext/asyncengine/libuv/src/unix/async.c +78 -17
  88. data/ext/asyncengine/libuv/src/unix/async.o +0 -0
  89. data/ext/asyncengine/libuv/src/unix/core.c +305 -213
  90. data/ext/asyncengine/libuv/src/unix/core.o +0 -0
  91. data/ext/asyncengine/libuv/src/unix/cygwin.c +1 -1
  92. data/ext/asyncengine/libuv/src/unix/darwin.c +2 -1
  93. data/ext/asyncengine/libuv/src/unix/dl.c +36 -44
  94. data/ext/asyncengine/libuv/src/unix/dl.o +0 -0
  95. data/ext/asyncengine/libuv/src/unix/eio/eio.o +0 -0
  96. data/ext/asyncengine/libuv/src/unix/error.c +6 -0
  97. data/ext/asyncengine/libuv/src/unix/error.o +0 -0
  98. data/ext/asyncengine/libuv/src/unix/ev/ev.c +8 -4
  99. data/ext/asyncengine/libuv/src/unix/ev/ev.o +0 -0
  100. data/ext/asyncengine/libuv/src/unix/freebsd.c +1 -1
  101. data/ext/asyncengine/libuv/src/unix/fs.c +25 -33
  102. data/ext/asyncengine/libuv/src/unix/fs.o +0 -0
  103. data/ext/asyncengine/libuv/src/unix/internal.h +50 -31
  104. data/ext/asyncengine/libuv/src/unix/kqueue.c +2 -7
  105. data/ext/asyncengine/libuv/src/unix/linux/core.o +0 -0
  106. data/ext/asyncengine/libuv/src/unix/linux/inotify.c +12 -14
  107. data/ext/asyncengine/libuv/src/unix/linux/inotify.o +0 -0
  108. data/ext/asyncengine/libuv/src/unix/linux/{core.c → linux-core.c} +1 -1
  109. data/ext/asyncengine/libuv/src/unix/linux/linux-core.o +0 -0
  110. data/ext/asyncengine/libuv/src/unix/linux/syscalls.c +147 -1
  111. data/ext/asyncengine/libuv/src/unix/linux/syscalls.h +39 -2
  112. data/ext/asyncengine/libuv/src/unix/linux/syscalls.o +0 -0
  113. data/ext/asyncengine/libuv/src/unix/loop-watcher.c +63 -0
  114. data/ext/asyncengine/libuv/src/unix/loop-watcher.o +0 -0
  115. data/ext/asyncengine/libuv/src/unix/loop.c +29 -6
  116. data/ext/asyncengine/libuv/src/unix/loop.o +0 -0
  117. data/ext/asyncengine/libuv/src/unix/netbsd.c +1 -1
  118. data/ext/asyncengine/libuv/src/unix/openbsd.c +1 -1
  119. data/ext/asyncengine/libuv/src/unix/pipe.c +31 -36
  120. data/ext/asyncengine/libuv/src/unix/pipe.o +0 -0
  121. data/ext/asyncengine/libuv/src/unix/poll.c +116 -0
  122. data/ext/asyncengine/libuv/src/unix/poll.o +0 -0
  123. data/ext/asyncengine/libuv/src/unix/process.c +193 -115
  124. data/ext/asyncengine/libuv/src/unix/process.o +0 -0
  125. data/ext/asyncengine/libuv/src/unix/stream.c +146 -153
  126. data/ext/asyncengine/libuv/src/unix/stream.o +0 -0
  127. data/ext/asyncengine/libuv/src/unix/sunos.c +45 -36
  128. data/ext/asyncengine/libuv/src/unix/tcp.c +6 -5
  129. data/ext/asyncengine/libuv/src/unix/tcp.o +0 -0
  130. data/ext/asyncengine/libuv/src/unix/thread.c +82 -25
  131. data/ext/asyncengine/libuv/src/unix/thread.o +0 -0
  132. data/ext/asyncengine/libuv/src/unix/timer.c +69 -58
  133. data/ext/asyncengine/libuv/src/unix/timer.o +0 -0
  134. data/ext/asyncengine/libuv/src/unix/tty.c +3 -3
  135. data/ext/asyncengine/libuv/src/unix/tty.o +0 -0
  136. data/ext/asyncengine/libuv/src/unix/udp.c +57 -66
  137. data/ext/asyncengine/libuv/src/unix/udp.o +0 -0
  138. data/ext/asyncengine/libuv/src/unix/uv-eio.c +33 -50
  139. data/ext/asyncengine/libuv/src/unix/uv-eio.o +0 -0
  140. data/ext/asyncengine/libuv/src/uv-common.c +68 -38
  141. data/ext/asyncengine/libuv/src/uv-common.h +104 -20
  142. data/ext/asyncengine/libuv/src/uv-common.o +0 -0
  143. data/ext/asyncengine/libuv/src/win/async.c +20 -17
  144. data/ext/asyncengine/libuv/src/win/core.c +44 -31
  145. data/ext/asyncengine/libuv/src/win/dl.c +40 -36
  146. data/ext/asyncengine/libuv/src/win/error.c +21 -1
  147. data/ext/asyncengine/libuv/src/win/fs-event.c +19 -21
  148. data/ext/asyncengine/libuv/src/win/fs.c +541 -189
  149. data/ext/asyncengine/libuv/src/win/getaddrinfo.c +56 -63
  150. data/ext/asyncengine/libuv/src/win/handle-inl.h +145 -0
  151. data/ext/asyncengine/libuv/src/win/handle.c +26 -101
  152. data/ext/asyncengine/libuv/src/win/internal.h +92 -107
  153. data/ext/asyncengine/libuv/src/win/loop-watcher.c +6 -14
  154. data/ext/asyncengine/libuv/src/win/pipe.c +78 -64
  155. data/ext/asyncengine/libuv/src/win/poll.c +618 -0
  156. data/ext/asyncengine/libuv/src/win/process-stdio.c +479 -0
  157. data/ext/asyncengine/libuv/src/win/process.c +147 -274
  158. data/ext/asyncengine/libuv/src/win/req-inl.h +225 -0
  159. data/ext/asyncengine/libuv/src/win/req.c +0 -149
  160. data/ext/asyncengine/libuv/src/{unix/check.c → win/stream-inl.h} +31 -42
  161. data/ext/asyncengine/libuv/src/win/stream.c +9 -43
  162. data/ext/asyncengine/libuv/src/win/tcp.c +200 -82
  163. data/ext/asyncengine/libuv/src/win/thread.c +42 -2
  164. data/ext/asyncengine/libuv/src/win/threadpool.c +3 -2
  165. data/ext/asyncengine/libuv/src/win/timer.c +13 -63
  166. data/ext/asyncengine/libuv/src/win/tty.c +26 -20
  167. data/ext/asyncengine/libuv/src/win/udp.c +26 -17
  168. data/ext/asyncengine/libuv/src/win/util.c +312 -167
  169. data/ext/asyncengine/libuv/src/win/winapi.c +16 -1
  170. data/ext/asyncengine/libuv/src/win/winapi.h +33 -9
  171. data/ext/asyncengine/libuv/src/win/winsock.c +88 -1
  172. data/ext/asyncengine/libuv/src/win/winsock.h +36 -3
  173. data/ext/asyncengine/libuv/test/benchmark-ares.c +16 -17
  174. data/ext/asyncengine/libuv/test/benchmark-fs-stat.c +164 -0
  175. data/ext/asyncengine/libuv/test/benchmark-list.h +9 -0
  176. data/ext/asyncengine/libuv/{src/unix/prepare.c → test/benchmark-loop-count.c} +42 -33
  177. data/ext/asyncengine/libuv/test/benchmark-million-timers.c +65 -0
  178. data/ext/asyncengine/libuv/test/benchmark-pound.c +1 -1
  179. data/ext/asyncengine/libuv/test/benchmark-sizes.c +2 -0
  180. data/ext/asyncengine/libuv/test/benchmark-spawn.c +7 -1
  181. data/ext/asyncengine/libuv/test/benchmark-udp-packet-storm.c +1 -1
  182. data/ext/asyncengine/libuv/test/echo-server.c +8 -0
  183. data/ext/asyncengine/libuv/test/run-tests.c +30 -0
  184. data/ext/asyncengine/libuv/test/runner-unix.c +6 -26
  185. data/ext/asyncengine/libuv/test/runner-win.c +5 -63
  186. data/ext/asyncengine/libuv/test/runner.c +10 -1
  187. data/ext/asyncengine/libuv/test/task.h +0 -8
  188. data/ext/asyncengine/libuv/test/test-async.c +43 -141
  189. data/ext/asyncengine/libuv/test/test-callback-order.c +76 -0
  190. data/ext/asyncengine/libuv/test/test-counters-init.c +2 -3
  191. data/ext/asyncengine/libuv/test/test-dlerror.c +17 -8
  192. data/ext/asyncengine/libuv/test/test-fs-event.c +31 -39
  193. data/ext/asyncengine/libuv/test/test-fs-poll.c +146 -0
  194. data/ext/asyncengine/libuv/test/test-fs.c +114 -2
  195. data/ext/asyncengine/libuv/test/test-gethostbyname.c +8 -8
  196. data/ext/asyncengine/libuv/test/test-hrtime.c +18 -15
  197. data/ext/asyncengine/libuv/test/test-ipc.c +8 -2
  198. data/ext/asyncengine/libuv/test/test-list.h +59 -9
  199. data/ext/asyncengine/libuv/test/test-loop-handles.c +2 -25
  200. data/ext/asyncengine/libuv/{src/unix/idle.c → test/test-poll-close.c} +37 -39
  201. data/ext/asyncengine/libuv/test/test-poll.c +573 -0
  202. data/ext/asyncengine/libuv/test/test-ref.c +79 -63
  203. data/ext/asyncengine/libuv/test/test-run-once.c +15 -11
  204. data/ext/asyncengine/libuv/test/test-semaphore.c +111 -0
  205. data/ext/asyncengine/libuv/test/test-spawn.c +368 -20
  206. data/ext/asyncengine/libuv/test/test-stdio-over-pipes.c +25 -35
  207. data/ext/asyncengine/libuv/test/test-tcp-close-while-connecting.c +80 -0
  208. data/ext/asyncengine/libuv/test/test-tcp-close.c +1 -1
  209. data/ext/asyncengine/libuv/test/test-tcp-connect-error-after-write.c +95 -0
  210. data/ext/asyncengine/libuv/test/test-tcp-connect-timeout.c +85 -0
  211. data/ext/asyncengine/libuv/test/test-tcp-shutdown-after-write.c +131 -0
  212. data/ext/asyncengine/libuv/test/test-tcp-write-error.c +2 -2
  213. data/ext/asyncengine/libuv/test/test-tcp-writealot.c +29 -54
  214. data/ext/asyncengine/libuv/test/test-timer-again.c +1 -1
  215. data/ext/asyncengine/libuv/test/test-timer.c +23 -1
  216. data/ext/asyncengine/libuv/test/test-udp-options.c +1 -1
  217. data/ext/asyncengine/libuv/test/{test-eio-overflow.c → test-walk-handles.c} +31 -44
  218. data/ext/asyncengine/libuv/uv.gyp +26 -9
  219. data/ext/asyncengine/rb_utilities.c +54 -0
  220. data/ext/asyncengine/rb_utilities.h +63 -0
  221. data/lib/asyncengine.rb +45 -38
  222. data/lib/asyncengine/asyncengine_ext.so +0 -0
  223. data/lib/asyncengine/debug.rb +37 -0
  224. data/lib/asyncengine/handle.rb +9 -0
  225. data/lib/asyncengine/tcp.rb +28 -0
  226. data/lib/asyncengine/timer.rb +18 -28
  227. data/lib/asyncengine/udp.rb +29 -0
  228. data/lib/asyncengine/utils.rb +32 -0
  229. data/lib/asyncengine/uv_error.rb +17 -0
  230. data/lib/asyncengine/version.rb +9 -1
  231. data/test/ae_test_helper.rb +62 -0
  232. data/test/test_basic.rb +169 -0
  233. data/test/test_call_from_other_thread.rb +55 -0
  234. data/test/test_error.rb +92 -0
  235. data/test/test_ip_utils.rb +44 -0
  236. data/test/test_next_tick.rb +37 -0
  237. data/test/test_resolver.rb +51 -0
  238. data/test/test_threads.rb +69 -0
  239. data/test/test_timer.rb +95 -0
  240. data/test/test_udp.rb +216 -0
  241. data/test/test_utils.rb +49 -0
  242. metadata +84 -57
  243. data/ext/asyncengine/libuv/mkmf.log +0 -24
  244. data/ext/asyncengine/libuv/src/unix/cares.c +0 -194
  245. data/ext/asyncengine/libuv/src/unix/cares.o +0 -0
  246. data/ext/asyncengine/libuv/src/unix/check.o +0 -0
  247. data/ext/asyncengine/libuv/src/unix/idle.o +0 -0
  248. data/ext/asyncengine/libuv/src/unix/prepare.o +0 -0
  249. data/ext/asyncengine/libuv/src/win/cares.c +0 -290
  250. data/lib/asyncengine/errors.rb +0 -5
  251. data/lib/asyncengine/next_tick.rb +0 -24
@@ -2,11 +2,18 @@
2
2
  #define AE_TIMER_H
3
3
 
4
4
 
5
- void init_ae_timer();
5
+ void init_ae_timer(void);
6
6
 
7
- VALUE AsyncEngine_c_add_timer(VALUE self, VALUE delay, VALUE interval, VALUE block, VALUE instance);
8
- VALUE AsyncEngineTimer_cancel(VALUE self);
9
- VALUE AsyncEngineTimer_c_set_interval(VALUE self, VALUE interval);
7
+ static VALUE AsyncEngineTimer_new(int argc, VALUE *argv, VALUE self);
8
+ static VALUE AsyncEnginePeriodicTimer_new(int argc, VALUE *argv, VALUE self);
9
+ static VALUE AsyncEngineTimer_pause(VALUE self);
10
+ static VALUE AsyncEngineTimer_restart(int argc, VALUE *argv, VALUE self);
11
+ static VALUE AsyncEnginePeriodicTimer_restart(int argc, VALUE *argv, VALUE self);
12
+ static VALUE AsyncEngineTimer_delay(VALUE self);
13
+ static VALUE AsyncEnginePeriodicTimer_interval(VALUE self);
14
+ static VALUE AsyncEngineTimer_is_alive(VALUE self);
15
+ static VALUE AsyncEngineTimer_close(VALUE self);
16
+ static VALUE AsyncEngineTimer_destroy(VALUE self);
10
17
 
11
18
 
12
19
  #endif /* AE_TIMER_H */
@@ -1,24 +1,590 @@
1
1
  #include "asyncengine_ruby.h"
2
2
  #include "ae_handle_common.h"
3
+ #include "ae_ip_utils.h"
3
4
  #include "ae_udp.h"
4
5
 
5
6
 
7
+ #define AE_UDP_DATAGRAM_MAX_SIZE 65536
8
+
9
+
10
+ static VALUE cAsyncEngineUdpSocket;
11
+
12
+ static ID method_on_datagram_received;
13
+
14
+
15
+ enum flags {
16
+ PAUSED = 1 << 1
17
+ };
18
+
19
+ typedef struct {
20
+ uv_udp_t *_uv_handle;
21
+ uv_buf_t recv_buffer;
22
+ enum_ip_type ip_type;
23
+ unsigned int flags;
24
+ enum_string_encoding encoding;
25
+ VALUE ae_handle;
26
+ VALUE ae_handle_id;
27
+ } struct_cdata;
28
+
29
+ struct _uv_recv_callback_data {
30
+ struct_cdata* cdata;
31
+ ssize_t nread;
32
+ struct sockaddr* addr;
33
+ unsigned flags;
34
+ };
35
+
36
+ typedef struct {
37
+ char *datagram;
38
+ VALUE on_send_proc_id;
39
+ } struct_send_data;
40
+
41
+ struct _uv_send_callback_data {
42
+ VALUE on_send_proc_id;
43
+ int status;
44
+ };
45
+
46
+
47
+ // Used for storing information about the last UDP recv callback.
48
+ static struct _uv_recv_callback_data last_uv_recv_callback_data;
49
+
50
+ // Used for storing information about the last UDP send callback.
51
+ static struct _uv_send_callback_data last_uv_send_callback_data;
52
+
53
+
54
+ /** Predeclaration of static functions. */
55
+
56
+ static VALUE AsyncEngineUdpSocket_alloc(VALUE klass);
57
+ static void AsyncEngineUdpSocket_mark(struct_cdata* cdata);
58
+ static void AsyncEngineUdpSocket_free(struct_cdata* cdata);
59
+ static void init_instance(VALUE self, enum_ip_type ip_type, char *bind_ip, int bind_port);
60
+ static uv_buf_t _uv_alloc_callback(uv_handle_t* handle, size_t suggested_size);
61
+ static void _uv_recv_callback(uv_udp_t* handle, ssize_t nread, uv_buf_t buf, struct sockaddr* addr, unsigned flags);
62
+ static VALUE _ae_recv_callback(void);
63
+ static void _uv_send_callback(uv_udp_send_t* req, int status);
64
+ static VALUE _ae_send_callback(void);
65
+ static void close_handle(struct_cdata *cdata);
66
+
67
+
6
68
  void init_ae_udp()
7
69
  {
8
- rb_define_module_function(mAsyncEngine, "test_ipv4", AsyncEngine_test_ipv4, 2);
70
+ AE_TRACE();
71
+
72
+ cAsyncEngineUdpSocket = rb_define_class_under(mAsyncEngine, "UDPSocket", cAsyncEngineHandle);
73
+
74
+ rb_define_alloc_func(cAsyncEngineUdpSocket, AsyncEngineUdpSocket_alloc);
75
+
76
+ rb_define_singleton_method(cAsyncEngineUdpSocket, "new", AsyncEngineUdpSocket_new, -1);
77
+
78
+ rb_define_method(cAsyncEngineUdpSocket, "send_datagram", AsyncEngineUdpSocket_send_datagram, -1);
79
+ rb_define_method(cAsyncEngineUdpSocket, "local_address", AsyncEngineUdpSocket_local_address, 0);
80
+ rb_define_method(cAsyncEngineUdpSocket, "ip_type", AsyncEngineUdpSocket_ip_type, 0);
81
+ rb_define_method(cAsyncEngineUdpSocket, "pause", AsyncEngineUdpSocket_pause, 0);
82
+ rb_define_method(cAsyncEngineUdpSocket, "resume", AsyncEngineUdpSocket_resume, 0);
83
+ rb_define_method(cAsyncEngineUdpSocket, "paused?", AsyncEngineUdpSocket_is_paused, 0);
84
+ rb_define_method(cAsyncEngineUdpSocket, "set_encoding_external", AsyncEngineUdpSocket_set_encoding_external, 0);
85
+ rb_define_method(cAsyncEngineUdpSocket, "set_encoding_utf8", AsyncEngineUdpSocket_set_encoding_utf8, 0);
86
+ rb_define_method(cAsyncEngineUdpSocket, "set_encoding_ascii", AsyncEngineUdpSocket_set_encoding_ascii, 0);
87
+ rb_define_method(cAsyncEngineUdpSocket, "encoding", AsyncEngineUdpSocket_encoding, 0);
88
+ rb_define_method(cAsyncEngineUdpSocket, "alive?", AsyncEngineUdpSocket_is_alive, 0);
89
+ rb_define_method(cAsyncEngineUdpSocket, "close", AsyncEngineUdpSocket_close, 0);
90
+ rb_define_private_method(cAsyncEngineUdpSocket, "destroy", AsyncEngineUdpSocket_destroy, 0);
91
+
92
+ method_on_datagram_received = rb_intern("on_datagram_received");
93
+ }
94
+
95
+
96
+ /** Class alloc, mark and free functions. */
97
+
98
+ static
99
+ VALUE AsyncEngineUdpSocket_alloc(VALUE klass)
100
+ {
101
+ AE_TRACE();
102
+
103
+ struct_cdata* cdata = ALLOC(struct_cdata);
104
+ cdata->recv_buffer = uv_buf_init(ALLOC_N(char, AE_UDP_DATAGRAM_MAX_SIZE), AE_UDP_DATAGRAM_MAX_SIZE);
105
+ cdata->_uv_handle = NULL;
106
+
107
+ return Data_Wrap_Struct(klass, AsyncEngineUdpSocket_mark, AsyncEngineUdpSocket_free, cdata);
108
+ }
109
+
110
+
111
+ static
112
+ void AsyncEngineUdpSocket_mark(struct_cdata* cdata)
113
+ {
114
+ AE_TRACE();
115
+
116
+ // TODO: hash de send_datagram...
117
+ }
118
+
119
+
120
+ static
121
+ void AsyncEngineUdpSocket_free(struct_cdata* cdata)
122
+ {
123
+ AE_TRACE();
124
+
125
+ xfree(cdata->recv_buffer.base);
126
+ xfree(cdata);
127
+ }
128
+
129
+
130
+ /** UDPSocket.new() method.
131
+ *
132
+ * Arguments:
133
+ * - bind IP (String).
134
+ * - bind port (Fixnum).
135
+ */
136
+
137
+ static
138
+ VALUE AsyncEngineUdpSocket_new(int argc, VALUE *argv, VALUE self)
139
+ {
140
+ AE_TRACE();
141
+ char *bind_ip;
142
+ int bind_ip_len;
143
+ int bind_port;
144
+ enum_ip_type ip_type;
145
+ VALUE instance;
146
+
147
+ AE_CHECK_STATUS();
148
+ AE_RB_CHECK_NUM_ARGS(2,2);
149
+
150
+ // Parameter 1: bind IP.
151
+ if (! RB_TYPE_P(argv[0], T_STRING))
152
+ rb_raise(rb_eTypeError, "bind IP must be a String");
153
+ bind_ip = StringValueCStr(argv[0]);
154
+ bind_ip_len = RSTRING_LEN(argv[0]);
155
+
156
+ // Parameter 2: bind port.
157
+ if (! FIXNUM_P(argv[1]))
158
+ rb_raise(rb_eTypeError, "bind port must be a Fixnum");
159
+ bind_port = FIX2INT(argv[1]);
160
+ if (! ae_ip_utils_is_valid_port(bind_port))
161
+ rb_raise(rb_eArgError, "invalid bind port value");
162
+
163
+ if ((ip_type = ae_ip_parser_execute(bind_ip, bind_ip_len)) == ip_type_no_ip)
164
+ rb_raise(rb_eTypeError, "bind IP is not valid IPv4 or IPv6");
165
+
166
+ // Allocate the Ruby instance.
167
+ instance = rb_obj_alloc(self);
168
+
169
+ // Init the UV stuff within the instance.
170
+ init_instance(instance, ip_type, bind_ip, bind_port);
171
+
172
+ return instance;
173
+ }
174
+
175
+
176
+ static
177
+ void init_instance(VALUE self, enum_ip_type ip_type, char *bind_ip, int bind_port)
178
+ {
179
+ AE_TRACE();
180
+ uv_udp_t *_uv_handle;
181
+ int r;
182
+
183
+ // Create and init the UV handle.
184
+ _uv_handle = ALLOC(uv_udp_t);
185
+ r = uv_udp_init(AE_uv_loop, _uv_handle);
186
+ if (r != 0) {
187
+ xfree(_uv_handle);
188
+ ae_raise_last_uv_error();
189
+ }
190
+
191
+ GET_CDATA_FROM_SELF;
192
+
193
+ // Bind.
194
+ switch(ip_type) {
195
+ case ip_type_ipv4:
196
+ r = uv_udp_bind(_uv_handle, uv_ip4_addr(bind_ip, bind_port), 0);
197
+ break;
198
+ case ip_type_ipv6:
199
+ r = uv_udp_bind6(_uv_handle, uv_ip6_addr(bind_ip, bind_port), UV_UDP_IPV6ONLY);
200
+ break;
201
+ }
202
+ if (r != 0) {
203
+ close_handle(cdata);
204
+ ae_raise_last_uv_error();
205
+ }
206
+
207
+ // Start receiving.
208
+ r = uv_udp_recv_start(_uv_handle, _uv_alloc_callback, _uv_recv_callback);
209
+ if (r != 0) {
210
+ close_handle(cdata);
211
+ ae_raise_last_uv_error();
212
+ }
213
+
214
+ // Fill cdata struct.
215
+ cdata->_uv_handle = _uv_handle;
216
+ cdata->ip_type = ip_type;
217
+ cdata->flags = 0;
218
+ cdata->encoding = string_encoding_ascii;
219
+ cdata->ae_handle = self;
220
+ cdata->ae_handle_id = ae_store_handle(self); // Avoid GC.
221
+
222
+ // Fill data field of the UV handle.
223
+ cdata->_uv_handle->data = (void *)cdata;
224
+ }
225
+
226
+
227
+ static
228
+ uv_buf_t _uv_alloc_callback(uv_handle_t* handle, size_t suggested_size)
229
+ {
230
+ AE_TRACE();
231
+
232
+ return ((struct_cdata*)handle->data)->recv_buffer;
233
+ }
234
+
235
+
236
+ static
237
+ void _uv_recv_callback(uv_udp_t* handle, ssize_t nread, uv_buf_t buf, struct sockaddr* addr, unsigned flags)
238
+ {
239
+ AE_TRACE();
240
+ struct_cdata* cdata = (struct_cdata*)handle->data;
241
+
242
+ // Don't execute the callback when AsyncEngine is releasing.
243
+ if (AE_status == AE_RELEASING)
244
+ return;
245
+
246
+ if (nread == 0)
247
+ return;
248
+
249
+ // uv.h: -1 if a transmission error was detected, ignore it.
250
+ if (nread == -1) {
251
+ AE_WARN("nread == -1"); // TODO: tmp
252
+ return;
253
+ }
254
+
255
+ // Ignore datagram when paused.
256
+ if (cdata->flags & PAUSED)
257
+ return;
258
+
259
+ last_uv_recv_callback_data.cdata = cdata;
260
+ last_uv_recv_callback_data.nread = nread;
261
+ last_uv_recv_callback_data.addr = addr;
262
+ last_uv_recv_callback_data.flags = flags;
263
+
264
+ ae_take_gvl_and_run_with_error_handler(_ae_recv_callback);
265
+ }
266
+
267
+
268
+ static
269
+ VALUE _ae_recv_callback(void)
270
+ {
271
+ AE_TRACE();
272
+ struct_cdata* cdata = last_uv_recv_callback_data.cdata;
273
+ VALUE datagram, array_ip_port, _rb_src_ip, _rb_src_port;
274
+
275
+ datagram = ae_rb_str_new(cdata->recv_buffer.base,
276
+ last_uv_recv_callback_data.nread, cdata->encoding, 1);
277
+ array_ip_port = ae_ip_utils_get_ip_port((struct sockaddr_storage *)last_uv_recv_callback_data.addr,
278
+ cdata->ip_type);
279
+
280
+ return rb_funcall(cdata->ae_handle, method_on_datagram_received, 3, datagram,
281
+ rb_ary_entry(array_ip_port, 0), rb_ary_entry(array_ip_port, 1));
9
282
  }
10
283
 
11
284
 
12
- VALUE AsyncEngine_test_ipv4(VALUE self, VALUE rb_ip, VALUE rb_port)
285
+ /** UDPSocket#send_datagram() method.
286
+ *
287
+ * Arguments:
288
+ * - datagram (String).
289
+ * - destination IP (String).
290
+ * - destination port (Fixnum).
291
+ * - proc (Proc) (optional).
292
+ *
293
+ * Block optional.
294
+ */
295
+
296
+ static
297
+ VALUE AsyncEngineUdpSocket_send_datagram(int argc, VALUE *argv, VALUE self)
13
298
  {
14
- char* ip = StringValueCStr(rb_ip);
15
- int port = FIX2INT(rb_port);
16
- struct sockaddr_in addr;
17
-
18
- //printf("AsyncEngine_ip4(): ip=%s, port=%d\n", ip, port);
19
- /* Convert string ip addresses to binary structures */
20
-
21
- //UV_EXTERN struct sockaddr_in uv_ip4_addr(const char* ip, int port);
22
- addr = uv_ip4_addr(ip, port);
23
-
24
- }
299
+ AE_TRACE();
300
+ char *_rb_datagram, *datagram, *ip;
301
+ int datagram_len, ip_len, port;
302
+ uv_buf_t buffer;
303
+ uv_udp_send_t* _uv_udp_send_req;
304
+ struct_send_data* send_data;
305
+ VALUE proc;
306
+ int r;
307
+
308
+ AE_RB_CHECK_NUM_ARGS(3,4);
309
+ GET_CDATA_FROM_SELF_AND_CHECK_UV_HANDLE_IS_OPEN;
310
+ AE_RB_GET_BLOCK_OR_PROC(4, proc);
311
+
312
+ // Parameter 1: data.
313
+ if (! RB_TYPE_P(argv[0], T_STRING))
314
+ rb_raise(rb_eTypeError, "datagram must be a String");
315
+ _rb_datagram = RSTRING_PTR(argv[0]);
316
+ datagram_len = RSTRING_LEN(argv[0]);
317
+
318
+ // Parameter 2: destination IP.
319
+ if (! RB_TYPE_P(argv[1], T_STRING))
320
+ rb_raise(rb_eTypeError, "destination IP must be a String");
321
+ ip = StringValueCStr(argv[1]);
322
+ ip_len = RSTRING_LEN(argv[1]);
323
+
324
+ // Parameter 3: destination port.
325
+ if (! FIXNUM_P(argv[2]))
326
+ rb_raise(rb_eTypeError, "destination port must be a Fixnum");
327
+ port = FIX2INT(argv[2]);
328
+ if (! ae_ip_utils_is_valid_port(port))
329
+ rb_raise(rb_eArgError, "invalid destination port value");
330
+
331
+ if (cdata->ip_type != ae_ip_parser_execute(ip, ip_len))
332
+ rb_raise(rb_eTypeError, "invalid destination IP family");
333
+
334
+ datagram = ALLOC_N(char, datagram_len);
335
+ memcpy(datagram, _rb_datagram, datagram_len);
336
+
337
+ send_data = ALLOC(struct_send_data);
338
+ send_data->datagram = datagram;
339
+
340
+ if (! NIL_P(proc))
341
+ send_data->on_send_proc_id = ae_store_proc(proc);
342
+ else
343
+ send_data->on_send_proc_id = Qnil;
344
+
345
+ _uv_udp_send_req = ALLOC(uv_udp_send_t);
346
+ _uv_udp_send_req->data = (void *)send_data;
347
+
348
+ buffer = uv_buf_init(datagram, datagram_len);
349
+
350
+ switch(cdata->ip_type) {
351
+ case ip_type_ipv4:
352
+ r = uv_udp_send(_uv_udp_send_req, cdata->_uv_handle, &buffer, 1, uv_ip4_addr(ip, port), _uv_send_callback);
353
+ break;
354
+ case ip_type_ipv6:
355
+ r = uv_udp_send6(_uv_udp_send_req, cdata->_uv_handle, &buffer, 1, uv_ip6_addr(ip, port), _uv_send_callback);
356
+ break;
357
+ }
358
+ if (r != 0) {
359
+ xfree(datagram);
360
+ xfree(send_data);
361
+ xfree(_uv_udp_send_req);
362
+ ae_raise_last_uv_error();
363
+ }
364
+
365
+ return Qtrue;
366
+ }
367
+
368
+
369
+ static
370
+ void _uv_send_callback(uv_udp_send_t* req, int status)
371
+ {
372
+ AE_TRACE();
373
+ struct_send_data* send_data = (struct_send_data*)req->data;
374
+ int do_on_send = 0;
375
+
376
+ // Block was provided so must call it with success or error param.
377
+ if (! NIL_P(send_data->on_send_proc_id)) {
378
+ last_uv_send_callback_data.on_send_proc_id = send_data->on_send_proc_id;
379
+ last_uv_send_callback_data.status = status;
380
+ do_on_send = 1;
381
+ }
382
+
383
+ xfree(req);
384
+ xfree(send_data->datagram);
385
+ xfree(send_data);
386
+
387
+ if (do_on_send)
388
+ ae_take_gvl_and_run_with_error_handler(_ae_send_callback);
389
+ }
390
+
391
+
392
+ static
393
+ VALUE _ae_send_callback(void)
394
+ {
395
+ AE_TRACE();
396
+ VALUE proc = ae_remove_proc(last_uv_send_callback_data.on_send_proc_id);
397
+
398
+ // Don't execute the callback when AsyncEngine is releasing.
399
+ if (AE_status == AE_RELEASING)
400
+ return Qnil;
401
+
402
+ if (last_uv_send_callback_data.status == 0)
403
+ return ae_proc_call_1(proc, Qnil);
404
+ else
405
+ return ae_proc_call_1(proc, ae_get_last_uv_error());
406
+ }
407
+
408
+
409
+ /** UDPSocket#local_address() method. */
410
+
411
+ static
412
+ VALUE AsyncEngineUdpSocket_local_address(VALUE self)
413
+ {
414
+ AE_TRACE();
415
+ struct sockaddr_storage local_addr;
416
+ int len = sizeof(local_addr);
417
+ int r;
418
+
419
+ GET_CDATA_FROM_SELF_AND_CHECK_UV_HANDLE_IS_OPEN;
420
+
421
+ r = uv_udp_getsockname(cdata->_uv_handle, (struct sockaddr*)&local_addr, &len);
422
+ if (r != 0)
423
+ ae_raise_last_uv_error();
424
+
425
+ return ae_ip_utils_get_ip_port(&local_addr, cdata->ip_type);
426
+ }
427
+
428
+
429
+ /** UDPSocket#ip_type() method. */
430
+
431
+ static
432
+ VALUE AsyncEngineUdpSocket_ip_type(VALUE self)
433
+ {
434
+ AE_TRACE();
435
+
436
+ GET_CDATA_FROM_SELF_AND_CHECK_UV_HANDLE_IS_OPEN;
437
+
438
+ return ae_ip_type_to_rb_symbol(cdata->ip_type);
439
+ }
440
+
441
+
442
+ /** UDPSocket#pause() method. */
443
+
444
+ static
445
+ VALUE AsyncEngineUdpSocket_pause(VALUE self)
446
+ {
447
+ AE_TRACE();
448
+
449
+ GET_CDATA_FROM_SELF_AND_CHECK_UV_HANDLE_IS_OPEN;
450
+
451
+ cdata->flags |= PAUSED;
452
+ return Qtrue;
453
+ }
454
+
455
+
456
+ /** UDPSocket#resume() method. */
457
+
458
+ static
459
+ VALUE AsyncEngineUdpSocket_resume(VALUE self)
460
+ {
461
+ AE_TRACE();
462
+
463
+ GET_CDATA_FROM_SELF_AND_CHECK_UV_HANDLE_IS_OPEN;
464
+
465
+ cdata->flags &= ~PAUSED;
466
+ return Qtrue;
467
+ }
468
+
469
+
470
+ /** UDPSocket#paused?() method. */
471
+
472
+ static
473
+ VALUE AsyncEngineUdpSocket_is_paused(VALUE self)
474
+ {
475
+ AE_TRACE();
476
+
477
+ GET_CDATA_FROM_SELF_AND_CHECK_UV_HANDLE_IS_OPEN;
478
+
479
+ if (cdata->flags & PAUSED)
480
+ return Qtrue;
481
+ else
482
+ return Qfalse;
483
+ }
484
+
485
+
486
+ /** UDPSocket#set_encoding_external() method. */
487
+
488
+ static
489
+ VALUE AsyncEngineUdpSocket_set_encoding_external(VALUE self)
490
+ {
491
+ AE_TRACE();
492
+
493
+ GET_CDATA_FROM_SELF_AND_CHECK_UV_HANDLE_IS_OPEN;
494
+
495
+ cdata->encoding = string_encoding_external;
496
+ return Qtrue;
497
+ }
498
+
499
+
500
+ /** UDPSocket#set_encoding_utf8() method. */
501
+
502
+ static
503
+ VALUE AsyncEngineUdpSocket_set_encoding_utf8(VALUE self)
504
+ {
505
+ AE_TRACE();
506
+
507
+ GET_CDATA_FROM_SELF_AND_CHECK_UV_HANDLE_IS_OPEN;
508
+
509
+ cdata->encoding = string_encoding_utf8;
510
+ return Qtrue;
511
+ }
512
+
513
+
514
+ /** UDPSocket#set_encoding_ascii() method. */
515
+
516
+ static
517
+ VALUE AsyncEngineUdpSocket_set_encoding_ascii(VALUE self)
518
+ {
519
+ AE_TRACE();
520
+
521
+ GET_CDATA_FROM_SELF_AND_CHECK_UV_HANDLE_IS_OPEN;
522
+
523
+ cdata->encoding = string_encoding_ascii;
524
+ return Qtrue;
525
+ }
526
+
527
+
528
+ /** UDPSocket#encoding() method. */
529
+
530
+ static
531
+ VALUE AsyncEngineUdpSocket_encoding(VALUE self)
532
+ {
533
+ AE_TRACE();
534
+
535
+ GET_CDATA_FROM_SELF_AND_CHECK_UV_HANDLE_IS_OPEN;
536
+
537
+ return ae_encoding_to_rb_symbol(cdata->encoding);
538
+ }
539
+
540
+
541
+ /** UDPSocket#alive?() method. */
542
+
543
+ static
544
+ VALUE AsyncEngineUdpSocket_is_alive(VALUE self)
545
+ {
546
+ AE_TRACE();
547
+
548
+ GET_CDATA_FROM_SELF_AND_CHECK_UV_HANDLE_IS_OPEN;
549
+
550
+ return Qtrue;
551
+ }
552
+
553
+
554
+ /** UDPSocket#close() method. */
555
+
556
+ static
557
+ VALUE AsyncEngineUdpSocket_close(VALUE self)
558
+ {
559
+ AE_TRACE();
560
+
561
+ GET_CDATA_FROM_SELF_AND_CHECK_UV_HANDLE_IS_OPEN;
562
+
563
+ close_handle(cdata);
564
+ return Qtrue;
565
+ }
566
+
567
+
568
+ /** UDPSocket#destroy() private method. */
569
+
570
+ static
571
+ VALUE AsyncEngineUdpSocket_destroy(VALUE self)
572
+ {
573
+ AE_TRACE();
574
+
575
+ GET_CDATA_FROM_SELF_AND_CHECK_UV_HANDLE_IS_OPEN;
576
+
577
+ close_handle(cdata);
578
+ return Qtrue;
579
+ }
580
+
581
+
582
+ static
583
+ void close_handle(struct_cdata *cdata)
584
+ {
585
+ AE_TRACE();
586
+
587
+ AE_CLOSE_UV_HANDLE(cdata->_uv_handle);
588
+ cdata->_uv_handle = NULL;
589
+ ae_remove_handle(cdata->ae_handle_id);
590
+ }