uvrb 0.1.0

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 (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