uvrb 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. data/.gitignore +17 -0
  2. data/.gitmodules +3 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +13 -0
  5. data/Formula/libuv.rb +20 -0
  6. data/Gemfile +3 -0
  7. data/LICENSE +24 -0
  8. data/README.rdoc +70 -0
  9. data/Rakefile +29 -0
  10. data/examples/example +0 -0
  11. data/examples/example.c +37 -0
  12. data/examples/example.rb +29 -0
  13. data/examples/example_oop.rb +26 -0
  14. data/examples/python.py +1 -0
  15. data/examples/ruby.rb +1 -0
  16. data/examples/tcp_client_oop.rb +31 -0
  17. data/examples/tcp_example +0 -0
  18. data/examples/tcp_example.c +68 -0
  19. data/examples/tcp_example.rb +41 -0
  20. data/examples/tcp_example_oop.rb +43 -0
  21. data/examples/tcp_example_plain.rb +19 -0
  22. data/examples/tty_example.rb +20 -0
  23. data/features/async.feature +38 -0
  24. data/features/idle.feature +44 -0
  25. data/features/pipe.feature +150 -0
  26. data/features/prepare_and_check.feature +49 -0
  27. data/features/step_definitions/additional_cli_steps.rb +20 -0
  28. data/features/support/env.rb +6 -0
  29. data/lib/uv.rb +248 -0
  30. data/lib/uv/assertions.rb +24 -0
  31. data/lib/uv/async.rb +24 -0
  32. data/lib/uv/check.rb +27 -0
  33. data/lib/uv/error.rb +58 -0
  34. data/lib/uv/file.rb +221 -0
  35. data/lib/uv/file/stat.rb +35 -0
  36. data/lib/uv/filesystem.rb +335 -0
  37. data/lib/uv/fs_event.rb +21 -0
  38. data/lib/uv/handle.rb +65 -0
  39. data/lib/uv/idle.rb +27 -0
  40. data/lib/uv/listener.rb +26 -0
  41. data/lib/uv/loop.rb +326 -0
  42. data/lib/uv/net.rb +31 -0
  43. data/lib/uv/pipe.rb +47 -0
  44. data/lib/uv/prepare.rb +27 -0
  45. data/lib/uv/resource.rb +20 -0
  46. data/lib/uv/stream.rb +105 -0
  47. data/lib/uv/tasks.rb +27 -0
  48. data/lib/uv/tasks/mac.rb +23 -0
  49. data/lib/uv/tasks/unix.rb +23 -0
  50. data/lib/uv/tasks/win.rb +2 -0
  51. data/lib/uv/tcp.rb +162 -0
  52. data/lib/uv/timer.rb +48 -0
  53. data/lib/uv/tty.rb +30 -0
  54. data/lib/uv/types.rb +249 -0
  55. data/lib/uv/types/darwin_x64.rb +10 -0
  56. data/lib/uv/types/linux.rb +6 -0
  57. data/lib/uv/types/unix.rb +12 -0
  58. data/lib/uv/types/windows.rb +13 -0
  59. data/lib/uv/udp.rb +215 -0
  60. data/lib/uv/version.rb +3 -0
  61. data/lib/uvrb.rb +1 -0
  62. data/spec/shared_examples/handle.rb +54 -0
  63. data/spec/shared_examples/stream.rb +109 -0
  64. data/spec/spec_helper.rb +26 -0
  65. data/spec/uv/async_spec.rb +18 -0
  66. data/spec/uv/check_spec.rb +30 -0
  67. data/spec/uv/file_spec.rb +177 -0
  68. data/spec/uv/filesystem_spec.rb +246 -0
  69. data/spec/uv/fs_event_spec.rb +10 -0
  70. data/spec/uv/idle_spec.rb +30 -0
  71. data/spec/uv/loop_spec.rb +241 -0
  72. data/spec/uv/pipe_spec.rb +54 -0
  73. data/spec/uv/prepare_spec.rb +30 -0
  74. data/spec/uv/tcp_spec.rb +134 -0
  75. data/spec/uv/timer_spec.rb +61 -0
  76. data/spec/uv/tty_spec.rb +53 -0
  77. data/spec/uv/udp_spec.rb +190 -0
  78. data/uvrb.gemspec +28 -0
  79. metadata +247 -0
data/lib/uv/timer.rb ADDED
@@ -0,0 +1,48 @@
1
+ module UV
2
+ class Timer
3
+ include Handle
4
+
5
+ def start(timeout, repeat, &block)
6
+ assert_block(block)
7
+ assert_arity(1, block)
8
+ assert_type(Integer, timeout, "timeout must be an Integer")
9
+ assert_type(Integer, repeat, "repeat must be an Integer")
10
+
11
+ @timer_block = block
12
+
13
+ check_result! UV.timer_start(handle, callback(:on_timer), timeout, repeat)
14
+
15
+ self
16
+ end
17
+
18
+ def stop
19
+ check_result! UV.timer_stop(handle)
20
+
21
+ self
22
+ end
23
+
24
+ def again
25
+ check_result! UV.timer_again(handle)
26
+
27
+ self
28
+ end
29
+
30
+ def repeat=(repeat)
31
+ assert_type(Integer, repeat, "repeat must be an Integer")
32
+
33
+ check_result! UV.timer_set_repeat(handle, repeat)
34
+
35
+ self
36
+ end
37
+
38
+ def repeat
39
+ UV.timer_get_repeat(handle)
40
+ end
41
+
42
+ private
43
+
44
+ def on_timer(handle, status)
45
+ @timer_block.call(check_result(status))
46
+ end
47
+ end
48
+ end
data/lib/uv/tty.rb ADDED
@@ -0,0 +1,30 @@
1
+ module UV
2
+ class TTY
3
+ include Stream
4
+
5
+ def enable_raw_mode
6
+ check_result! UV.tty_set_mode(handle, 1)
7
+
8
+ self
9
+ end
10
+
11
+ def disable_raw_mode
12
+ check_result! UV.tty_set_mode(handle, 0)
13
+
14
+ self
15
+ end
16
+
17
+ def reset_mode
18
+ UV.tty_reset_mode
19
+
20
+ self
21
+ end
22
+
23
+ def winsize
24
+ width = FFI::MemoryPointer.new(:int)
25
+ height = FFI::MemoryPointer.new(:int)
26
+ UV.tty_get_winsize(handle, width, height)
27
+ [width.get_int(0), height.get_int(0)]
28
+ end
29
+ end
30
+ end
data/lib/uv/types.rb ADDED
@@ -0,0 +1,249 @@
1
+ module FFI::Platform
2
+ def self.linux?
3
+ IS_LINUX
4
+ end
5
+ end
6
+
7
+ module UV
8
+ require 'uv/types/linux.rb' if FFI::Platform.linux?
9
+ require 'uv/types/unix.rb' if FFI::Platform.unix?
10
+ require 'uv/types/darwin_x64.rb' if FFI::Platform.mac? and FFI::Platform::ARCH == 'x86_64'
11
+ require 'uv/types/windows.rb' if FFI::Platform.windows?
12
+
13
+ enum :uv_handle_type, [
14
+ :uv_unknown_handle, 0,
15
+ :uv_async,
16
+ :uv_check,
17
+ :uv_fs_event,
18
+ :uv_idle,
19
+ :uv_pipe,
20
+ :uv_poll,
21
+ :uv_prepare,
22
+ :uv_process,
23
+ :uv_tcp,
24
+ :uv_timer,
25
+ :uv_tty,
26
+ :uv_udp,
27
+ :uv_ares_task,
28
+ :uv_file,
29
+ :uv_handle_type_max
30
+ ]
31
+ enum :uv_req_type, [
32
+ :uv_unknown_req, 0,
33
+ :uv_connect,
34
+ :uv_write,
35
+ :uv_shutdown,
36
+ :uv_udp_send,
37
+ :uv_fs,
38
+ :uv_work,
39
+ :uv_getaddrinfo,
40
+ :uv_req_type_private,
41
+ :uv_req_type_max
42
+ ]
43
+ enum :uv_membership, [
44
+ :uv_leave_group, 0,
45
+ :uv_join_group
46
+ ]
47
+ enum :uv_err_code, [
48
+ :UNKNOWN, -1,
49
+ :OK, 0,
50
+ :EOF, 1,
51
+ :EADDRINFO, 2,
52
+ :EACCES, 3,
53
+ :EAGAIN, 4,
54
+ :EADDRINUSE, 5,
55
+ :EADDRNOTAVAIL, 6,
56
+ :EAFNOSUPPORT, 7,
57
+ :EALREADY, 8,
58
+ :EBADF, 9,
59
+ :EBUSY, 10,
60
+ :ECONNABORTED, 11,
61
+ :ECONNREFUSED, 12,
62
+ :ECONNRESET, 13,
63
+ :EDESTADDRREQ, 14,
64
+ :EFAULT, 15,
65
+ :EHOSTUNREACH, 16,
66
+ :EINTR, 17,
67
+ :EINVAL, 18,
68
+ :EISCONN, 19,
69
+ :EMFILE, 20,
70
+ :EMSGSIZE, 21,
71
+ :ENETDOWN, 22,
72
+ :ENETUNREACH, 23,
73
+ :ENFILE, 24,
74
+ :ENOBUFS, 25,
75
+ :ENOMEM, 26,
76
+ :ENOTDIR, 27,
77
+ :EISDIR, 28,
78
+ :ENONET, 29,
79
+ :ENOTCONN, 31,
80
+ :ENOTSOCK, 32,
81
+ :ENOTSUP, 33,
82
+ :ENOENT, 34,
83
+ :ENOSYS, 35,
84
+ :EPIPE, 36,
85
+ :EPROTO, 37,
86
+ :EPROTONOSUPPORT, 38,
87
+ :EPROTOTYPE, 39,
88
+ :ETIMEDOUT, 40,
89
+ :ECHARSET, 41,
90
+ :EAIFAMNOSUPPORT, 42,
91
+ :EAISERVICE, 44,
92
+ :EAISOCKTYPE, 45,
93
+ :ESHUTDOWN, 46,
94
+ :EEXIST, 47,
95
+ :ESRCH, 48,
96
+ :ENAMETOOLONG, 49,
97
+ :EPERM, 50,
98
+ :ELOOP, 51,
99
+ :EXDEV, 52,
100
+ :ENOTEMPTY, 53,
101
+ :ENOSPC, 54,
102
+ :EIO, 55,
103
+ :EROFS, 56,
104
+ :UV_MAX_ERRORS
105
+ ]
106
+ enum :uv_fs_type, [
107
+ :UV_FS_UNKNOWN, -1,
108
+ :UV_FS_CUSTOM,
109
+ :UV_FS_OPEN,
110
+ :UV_FS_CLOSE,
111
+ :UV_FS_READ,
112
+ :UV_FS_WRITE,
113
+ :UV_FS_SENDFILE,
114
+ :UV_FS_STAT,
115
+ :UV_FS_LSTAT,
116
+ :UV_FS_FSTAT,
117
+ :UV_FS_FTRUNCATE,
118
+ :UV_FS_UTIME,
119
+ :UV_FS_FUTIME,
120
+ :UV_FS_CHMOD,
121
+ :UV_FS_FCHMOD,
122
+ :UV_FS_FSYNC,
123
+ :UV_FS_FDATASYNC,
124
+ :UV_FS_UNLINK,
125
+ :UV_FS_RMDIR,
126
+ :UV_FS_MKDIR,
127
+ :UV_FS_RENAME,
128
+ :UV_FS_READDIR,
129
+ :UV_FS_LINK,
130
+ :UV_FS_SYMLINK,
131
+ :UV_FS_READLINK,
132
+ :UV_FS_CHOWN,
133
+ :UV_FS_FCHOWN
134
+ ]
135
+ enum :uv_fs_event, [
136
+ :UV_RENAME, 1,
137
+ :UV_CHANGE, 2
138
+ ]
139
+
140
+ typedef UvBuf.by_value, :uv_buf_t
141
+ typedef UvFSStat.by_value, :uv_fs_stat_t
142
+
143
+ class UvErr < FFI::Struct
144
+ layout :code, :uv_err_code,
145
+ :sys_errno_, :int
146
+ end
147
+
148
+ typedef UvErr.by_value, :uv_err_t
149
+
150
+ class Sockaddr < FFI::Struct
151
+ layout :sa_len, :uint8,
152
+ :sa_family, :sa_family_t,
153
+ :sa_data, [:char, 14]
154
+ end
155
+
156
+ class InAddr < FFI::Struct
157
+ layout :s_addr, :in_addr_t
158
+ end
159
+
160
+ class SockaddrIn < FFI::Struct
161
+ layout :sin_len, :uint8,
162
+ :sin_family, :sa_family_t,
163
+ :sin_port, :in_port_t,
164
+ :sin_addr, InAddr,
165
+ :sin_zero, [:char, 8]
166
+ end
167
+
168
+ typedef SockaddrIn.by_value, :sockaddr_in
169
+
170
+ class U6Addr < FFI::Union
171
+ layout :__u6_addr8, [:uint8, 16],
172
+ :__u6_addr16, [:uint16, 8]
173
+ end
174
+
175
+ class In6Addr < FFI::Struct
176
+ layout :__u6_addr, U6Addr
177
+ end
178
+
179
+ class SockaddrIn6 < FFI::Struct
180
+ layout :sin6_len, :uint8,
181
+ :sin6_family, :sa_family_t,
182
+ :sin6_port, :in_port_t,
183
+ :sin6_flowinfo, :uint32,
184
+ :sin6_addr, In6Addr,
185
+ :sin6_scope_id, :uint32
186
+ end
187
+
188
+ typedef SockaddrIn6.by_value, :sockaddr_in6
189
+
190
+ typedef :pointer, :uv_handle_t
191
+ typedef :pointer, :uv_fs_event_t
192
+ typedef :pointer, :uv_stream_t
193
+ typedef :pointer, :uv_tcp_t
194
+ typedef :pointer, :uv_udp_t
195
+ typedef :pointer, :uv_tty_t
196
+ typedef :pointer, :uv_pipe_t
197
+ typedef :pointer, :uv_prepare_t
198
+ typedef :pointer, :uv_check_t
199
+ typedef :pointer, :uv_idle_t
200
+ typedef :pointer, :uv_async_t
201
+ typedef :pointer, :uv_timer_t
202
+ typedef :pointer, :uv_process_t
203
+ typedef :pointer, :uv_getaddrinfo_cb
204
+ typedef :pointer, :addrinfo
205
+ typedef :pointer, :uv_fs_t
206
+ typedef :pointer, :uv_work_t
207
+ typedef :pointer, :uv_loop_t
208
+ typedef :pointer, :uv_shutdown_t
209
+ typedef :pointer, :uv_write_t
210
+ typedef :pointer, :uv_connect_t
211
+ typedef :pointer, :uv_udp_send_t
212
+ typedef :int, :uv_file
213
+ typedef :pointer, :ares_channel
214
+ typedef :pointer, :ares_options
215
+ typedef :pointer, :uv_getaddrinfo_t
216
+ typedef :pointer, :uv_options_t
217
+ typedef :pointer, :uv_cpu_info_t
218
+ typedef :pointer, :uv_interface_address_t
219
+ typedef :pointer, :uv_fs_t
220
+ typedef :pointer, :uv_lib_t
221
+ typedef :pointer, :uv_mutex_t
222
+ typedef :pointer, :uv_rwlock_t
223
+ typedef :pointer, :uv_once_t
224
+ typedef :pointer, :uv_thread_t
225
+ typedef :int, :status
226
+
227
+ callback :uv_alloc_cb, [:uv_handle_t, :size_t], :uv_buf_t
228
+ callback :uv_read_cb, [:uv_stream_t, :ssize_t, :uv_buf_t], :void
229
+ callback :uv_read2_cb, [:uv_pipe_t, :ssize_t, :uv_buf_t, :uv_handle_type], :void
230
+ callback :uv_write_cb, [:uv_write_t, :status], :void
231
+ callback :uv_connect_cb, [:uv_connect_t, :status], :void
232
+ callback :uv_shutdown_cb, [:uv_shutdown_t, :status], :void
233
+ callback :uv_connection_cb, [:uv_stream_t, :status], :void
234
+ callback :uv_close_cb, [:uv_handle_t], :void
235
+ callback :uv_timer_cb, [:uv_timer_t, :status], :void
236
+ callback :uv_async_cb, [:uv_async_t, :status], :void
237
+ callback :uv_prepare_cb, [:uv_prepare_t, :status], :void
238
+ callback :uv_check_cb, [:uv_check_t, :status], :void
239
+ callback :uv_idle_cb, [:uv_idle_t, :status], :void
240
+ callback :uv_getaddrinfo_cb, [:uv_getaddrinfo_t, :status, :addrinfo], :void
241
+ callback :uv_exit_cb, [:uv_process_t, :int, :int], :void
242
+ callback :uv_fs_cb, [:uv_fs_t], :void
243
+ callback :uv_work_cb, [:uv_work_t], :void
244
+ callback :uv_after_work_cb, [:uv_work_t], :void
245
+ callback :uv_fs_event_cb, [:uv_fs_event_t, :string, :int, :int], :void
246
+ callback :uv_udp_send_cb, [:uv_udp_send_t, :int], :void
247
+ callback :uv_udp_recv_cb, [:uv_udp_t, :ssize_t, :uv_buf_t, :pointer, :uint], :void
248
+ callback :uv_cb, [], :void
249
+ end
@@ -0,0 +1,10 @@
1
+ module UV
2
+ class UvFSStat < FFI::Struct
3
+ layout :st_dev, :dev_t, :st_mode, :mode_t, :st_nlink, :nlink_t,
4
+ :st_ino, :ino_t, :st_uid, :uid_t, :st_gid, :gid_t, :st_rdev,
5
+ :dev_t, :st_atime, :time_t, :st_mtime, :time_t, :st_ctime,
6
+ :time_t, :st_size, :off_t, :st_blocks, :blkcnt_t, :st_blksize,
7
+ :blksize_t, :st_flags, :uint32, :st_gen, :uint32, :st_lspare,
8
+ :int32, :st_qspare_0, :int64, :st_qspare_1, :int64
9
+ end
10
+ end
@@ -0,0 +1,6 @@
1
+ module UV
2
+ # blksize_t, in_addr_t is not yet part of types.conf on linux
3
+ typedef :long, :blksize_t
4
+ typedef :uint32, :in_addr_t
5
+ typedef :ushort, :in_port_t
6
+ end
@@ -0,0 +1,12 @@
1
+ module UV
2
+ class UvBuf < FFI::Struct
3
+ layout :base, :pointer, :len, :size_t
4
+ end
5
+
6
+ class UvFSStat < FFI::Struct
7
+ layout :st_dev, :dev_t, :st_ino, :ino_t, :st_mode, :mode_t, :st_nlink, :nlink_t,
8
+ :st_uid, :uid_t, :st_gid, :gid_t, :st_rdev, :dev_t, :st_size, :off_t,
9
+ :st_blksize, :blksize_t, :st_blocks, :blkcnt_t, :st_atime, :time_t,
10
+ :st_mtime, :time_t, :st_ctime, :time_t
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ module UV
2
+ # win32 has a different uv_buf_t layout to everything else.
3
+ class UvBuf < FFI::Struct
4
+ layout :len, :ulong, :base, :pointer
5
+ end
6
+
7
+ # win32 uses _stati64
8
+ class UvFSStat < FFI::Struct
9
+ layout :st_gid, :gid_t, :st_atime, :time_t, :st_ctime, :time_t, :st_dev, :dev_t,
10
+ :st_ino, :ino_t, :st_mode, :mode_t, :st_mtime, :time_t, :st_nlink, :nlink_t,
11
+ :st_rdev, :dev_t, :st_size, :off_t, :st_uid, :uid_t
12
+ end
13
+ end
data/lib/uv/udp.rb ADDED
@@ -0,0 +1,215 @@
1
+ module UV
2
+ class UDP
3
+ include Handle, Net
4
+
5
+ def bind(ip, port, ipv6_only = false)
6
+ assert_type(String, ip, "ip must be a String")
7
+ assert_type(Integer, port, "port must be an Integer")
8
+ assert_boolean(ipv6_only, "ipv6_only must be a Boolean")
9
+
10
+ @socket = create_socket(IPAddr.new(ip), port)
11
+ @socket.bind(ipv6_only)
12
+
13
+ self
14
+ end
15
+
16
+ def sockname
17
+ sockaddr, len = get_sockaddr_and_len
18
+ check_result! UV.udp_getsockname(handle, sockaddr, len)
19
+ get_ip_and_port(UV::Sockaddr.new(sockaddr), len.get_int(0))
20
+ end
21
+
22
+ def join(multicast_address, interface_address)
23
+ assert_type(String, multicast_address, "multicast_address must be a String")
24
+ assert_type(String, interface_address, "interface_address must be a String")
25
+
26
+ check_result! UV.udp_set_membership(handle, multicast_address, interface_address, :uv_join_group)
27
+
28
+ self
29
+ end
30
+
31
+ def leave(multicast_address, interface_address)
32
+ assert_type(String, multicast_address, "multicast_address must be a String")
33
+ assert_type(String, interface_address, "interface_address must be a String")
34
+
35
+ check_result! UV.udp_set_membership(handle, multicast_address, interface_address, :uv_leave_group)
36
+
37
+ self
38
+ end
39
+
40
+ def start_recv(&block)
41
+ assert_block(block)
42
+ assert_arity(4, block)
43
+
44
+ @recv_block = block
45
+
46
+ check_result! UV.udp_recv_start(handle, callback(:on_allocate), callback(:on_recv))
47
+
48
+ self
49
+ end
50
+
51
+ def stop_recv
52
+ check_result! UV.udp_recv_stop(handle)
53
+ end
54
+
55
+ def send(ip, port, data, &block)
56
+ assert_block(block)
57
+ assert_arity(1, block)
58
+ assert_type(String, ip, "ip must be a String")
59
+ assert_type(Integer, port, "port must be an Integer")
60
+ assert_type(String, data, "data must be a String")
61
+
62
+ @send_block = block
63
+
64
+ @socket = create_socket(IPAddr.new(ip), port)
65
+ @socket.send(data, callback(:on_send))
66
+
67
+ self
68
+ end
69
+
70
+ def enable_multicast_loop
71
+ check_result! UV.udp_set_multicast_loop(handle, 1)
72
+
73
+ self
74
+ end
75
+
76
+ def disable_multicast_loop
77
+ check_result! UV.udp_set_multicast_loop(handle, 0)
78
+
79
+ self
80
+ end
81
+
82
+ def multicast_ttl=(ttl)
83
+ assert_type(Integer, ttl, "ttl must be an Integer")
84
+
85
+ check_result! UV.udp_set_multicast_ttl(handle, ttl)
86
+
87
+ self
88
+ end
89
+
90
+ def enable_broadcast
91
+ check_result! UV.udp_set_broadcast(handle, 1)
92
+
93
+ self
94
+ end
95
+
96
+ def disable_broadcast
97
+ check_result! UV.udp_set_broadcast(handle, 0)
98
+
99
+ self
100
+ end
101
+
102
+ def ttl=(ttl)
103
+ assert_type(Integer, ttl, "ttl must be an Integer")
104
+
105
+ check_result! UV.udp_set_ttl(handle, Integer(ttl))
106
+
107
+ self
108
+ end
109
+
110
+ private
111
+
112
+ def on_allocate(client, suggested_size)
113
+ UV.buf_init(UV.malloc(suggested_size), suggested_size)
114
+ end
115
+
116
+ def on_recv(handle, nread, buf, sockaddr, flags)
117
+ e = check_result(nread)
118
+ base = buf[:base]
119
+ unless e
120
+ data = base.read_string(nread)
121
+ end
122
+ UV.free(base)
123
+ unless sockaddr.null?
124
+ ip, port = get_ip_and_port(UV::Sockaddr.new(sockaddr))
125
+ end
126
+ @recv_block.call(e, data, ip, port)
127
+ end
128
+
129
+ def on_send(req, status)
130
+ UV.free(req)
131
+ @send_block.call(check_result(status))
132
+ end
133
+
134
+ def create_socket(ip, port)
135
+ if ip.ipv4?
136
+ Socket4.new(@loop, handle, ip, port)
137
+ else
138
+ Socket6.new(@loop, handle, ip, port)
139
+ end
140
+ end
141
+
142
+ module SocketMethods
143
+ include Resource
144
+
145
+ def initialize(loop, udp, ip, port)
146
+ @loop, @udp, @sockaddr = loop, udp, ip_addr(ip.to_s, port)
147
+ end
148
+
149
+ def bind(ipv6_only = false)
150
+ check_result! udp_bind(ipv6_only)
151
+ end
152
+
153
+ def send(data, callback)
154
+ check_result! udp_send(data, callback)
155
+ end
156
+
157
+ private
158
+ def send_req
159
+ UV.create_request(:uv_udp_send)
160
+ end
161
+
162
+ def buf_init(data)
163
+ UV.buf_init(FFI::MemoryPointer.from_string(data), data.respond_to?(:bytesize) ? data.bytesize : data.size)
164
+ end
165
+ end
166
+
167
+ class Socket4
168
+ include SocketMethods
169
+
170
+ private
171
+ def ip_addr(ip, port)
172
+ UV.ip4_addr(ip, port)
173
+ end
174
+
175
+ def udp_bind(ipv6_only)
176
+ UV.udp_bind(@udp, @sockaddr, 0)
177
+ end
178
+
179
+ def udp_send(data, callback)
180
+ UV.udp_send(
181
+ send_req,
182
+ @udp,
183
+ buf_init(data),
184
+ 1,
185
+ @sockaddr,
186
+ callback
187
+ )
188
+ end
189
+ end
190
+
191
+ class Socket6 < Socket
192
+ include SocketMethods
193
+
194
+ private
195
+ def ip_addr(ip, port)
196
+ UV.ip6_addr(ip, port)
197
+ end
198
+
199
+ def udp_bind(ipv6_only)
200
+ UV.udp_bind6(@udp, @sockaddr, ipv6_only ? 1 : 0)
201
+ end
202
+
203
+ def udp_send(data, callback)
204
+ UV.udp_send6(
205
+ send_req,
206
+ @udp,
207
+ buf_init(data),
208
+ 1,
209
+ @sockaddr,
210
+ callback
211
+ )
212
+ end
213
+ end
214
+ end
215
+ end