asyncengine 0.0.1.testing1 → 0.0.2.alpha1

Sign up to get free protection for your applications and to get access to all the features.
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
+ }