libuv 0.11.22 → 0.12.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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +19 -17
  3. data/.gitmodules +3 -3
  4. data/.rspec +1 -1
  5. data/.travis.yml +16 -16
  6. data/Gemfile +4 -4
  7. data/LICENSE +23 -23
  8. data/README.md +89 -89
  9. data/Rakefile +31 -31
  10. data/lib/libuv.rb +54 -54
  11. data/lib/libuv/async.rb +47 -47
  12. data/lib/libuv/check.rb +55 -55
  13. data/lib/libuv/dns.rb +85 -85
  14. data/lib/libuv/error.rb +78 -74
  15. data/lib/libuv/ext/ext.rb +260 -258
  16. data/lib/libuv/ext/platform/darwin_x64.rb +23 -23
  17. data/lib/libuv/ext/platform/linux.rb +7 -7
  18. data/lib/libuv/ext/platform/unix.rb +29 -29
  19. data/lib/libuv/ext/platform/windows.rb +40 -40
  20. data/lib/libuv/ext/tasks.rb +31 -31
  21. data/lib/libuv/ext/tasks/mac.rb +23 -23
  22. data/lib/libuv/ext/tasks/unix.rb +23 -23
  23. data/lib/libuv/ext/tasks/win.rb +14 -14
  24. data/lib/libuv/ext/types.rb +238 -238
  25. data/lib/libuv/file.rb +281 -269
  26. data/lib/libuv/filesystem.rb +232 -232
  27. data/lib/libuv/fs_event.rb +31 -31
  28. data/lib/libuv/handle.rb +85 -85
  29. data/lib/libuv/idle.rb +56 -56
  30. data/lib/libuv/loop.rb +412 -412
  31. data/lib/libuv/mixins/assertions.rb +23 -23
  32. data/lib/libuv/mixins/fs_checks.rb +60 -58
  33. data/lib/libuv/mixins/listener.rb +34 -34
  34. data/lib/libuv/mixins/net.rb +40 -40
  35. data/lib/libuv/mixins/resource.rb +27 -27
  36. data/lib/libuv/mixins/stream.rb +153 -154
  37. data/lib/libuv/pipe.rb +184 -203
  38. data/lib/libuv/prepare.rb +56 -56
  39. data/lib/libuv/signal.rb +51 -51
  40. data/lib/libuv/tcp.rb +334 -334
  41. data/lib/libuv/timer.rb +85 -85
  42. data/lib/libuv/tty.rb +37 -37
  43. data/lib/libuv/udp.rb +240 -240
  44. data/lib/libuv/version.rb +3 -3
  45. data/lib/libuv/work.rb +75 -75
  46. data/libuv.gemspec +56 -56
  47. data/spec/async_spec.rb +61 -60
  48. data/spec/cpu_spec.rb +10 -10
  49. data/spec/defer_spec.rb +980 -980
  50. data/spec/dns_spec.rb +96 -90
  51. data/spec/filesystem_spec.rb +270 -261
  52. data/spec/idle_spec.rb +56 -56
  53. data/spec/pipe_spec.rb +160 -160
  54. data/spec/tcp_spec.rb +271 -267
  55. metadata +64 -51
data/lib/libuv/timer.rb CHANGED
@@ -1,85 +1,85 @@
1
- module Libuv
2
- class Timer < Handle
3
-
4
- # @param loop [::Libuv::Loop] loop this timer will be associated
5
- # @param callback [Proc] callback to be called when the timer is triggered
6
- def initialize(loop, callback = nil)
7
- @loop, @callback = loop, callback
8
-
9
- timer_ptr = ::Libuv::Ext.create_handle(:uv_timer)
10
- error = check_result(::Libuv::Ext.timer_init(loop.handle, timer_ptr))
11
- @stopped = true
12
-
13
- super(timer_ptr, error)
14
- end
15
-
16
- # Enables the timer. A repeat of 0 means no repeat
17
- #
18
- # @param timeout [Fixnum] time in milliseconds before the timer callback is triggered the first time
19
- # @param repeat [Fixnum] time in milliseconds between repeated callbacks after the first
20
- def start(timeout, repeat = 0)
21
- return if @closed
22
- @stopped = false
23
-
24
- timeout = timeout.to_i
25
- repeat = repeat.to_i
26
-
27
- error = check_result ::Libuv::Ext.timer_start(handle, callback(:on_timer), timeout, repeat)
28
- reject(error) if error
29
- end
30
-
31
- # Disables the timer.
32
- def stop
33
- return if @stopped || @closed
34
- @stopped = true
35
- error = check_result ::Libuv::Ext.timer_stop(handle)
36
- reject(error) if error
37
- end
38
-
39
- # Resets the current repeat
40
- def again
41
- return if @closed
42
- error = check_result ::Libuv::Ext.timer_again(handle)
43
- reject(error) if error
44
- end
45
-
46
- # Updates the repeat timeout
47
- def repeat=(repeat)
48
- return if @closed
49
- repeat = repeat.to_i
50
- check_result ::Libuv::Ext.timer_set_repeat(handle, repeat)
51
- reject(error) if error
52
- end
53
-
54
- # Returns the current repeat timeout
55
- def repeat
56
- return if @closed
57
- ::Libuv::Ext.timer_get_repeat(handle)
58
- end
59
-
60
- # Used to update the callback to be triggered by the timer
61
- #
62
- # @param callback [Proc] the callback to be called by the timer
63
- def progress(callback = nil, &blk)
64
- @callback = callback || blk
65
- end
66
-
67
-
68
- private
69
-
70
-
71
- def on_timer(handle, status)
72
- e = check_result(status)
73
-
74
- if e
75
- reject(e)
76
- else
77
- begin
78
- @callback.call
79
- rescue Exception => e
80
- @loop.log :error, :timer_cb, e
81
- end
82
- end
83
- end
84
- end
85
- end
1
+ module Libuv
2
+ class Timer < Handle
3
+
4
+ # @param loop [::Libuv::Loop] loop this timer will be associated
5
+ # @param callback [Proc] callback to be called when the timer is triggered
6
+ def initialize(loop, callback = nil)
7
+ @loop, @callback = loop, callback
8
+
9
+ timer_ptr = ::Libuv::Ext.create_handle(:uv_timer)
10
+ error = check_result(::Libuv::Ext.timer_init(loop.handle, timer_ptr))
11
+ @stopped = true
12
+
13
+ super(timer_ptr, error)
14
+ end
15
+
16
+ # Enables the timer. A repeat of 0 means no repeat
17
+ #
18
+ # @param timeout [Fixnum] time in milliseconds before the timer callback is triggered the first time
19
+ # @param repeat [Fixnum] time in milliseconds between repeated callbacks after the first
20
+ def start(timeout, repeat = 0)
21
+ return if @closed
22
+ @stopped = false
23
+
24
+ timeout = timeout.to_i
25
+ repeat = repeat.to_i
26
+
27
+ error = check_result ::Libuv::Ext.timer_start(handle, callback(:on_timer), timeout, repeat)
28
+ reject(error) if error
29
+ end
30
+
31
+ # Disables the timer.
32
+ def stop
33
+ return if @stopped || @closed
34
+ @stopped = true
35
+ error = check_result ::Libuv::Ext.timer_stop(handle)
36
+ reject(error) if error
37
+ end
38
+
39
+ # Resets the current repeat
40
+ def again
41
+ return if @closed
42
+ error = check_result ::Libuv::Ext.timer_again(handle)
43
+ reject(error) if error
44
+ end
45
+
46
+ # Updates the repeat timeout
47
+ def repeat=(repeat)
48
+ return if @closed
49
+ repeat = repeat.to_i
50
+ check_result ::Libuv::Ext.timer_set_repeat(handle, repeat)
51
+ reject(error) if error
52
+ end
53
+
54
+ # Returns the current repeat timeout
55
+ def repeat
56
+ return if @closed
57
+ ::Libuv::Ext.timer_get_repeat(handle)
58
+ end
59
+
60
+ # Used to update the callback to be triggered by the timer
61
+ #
62
+ # @param callback [Proc] the callback to be called by the timer
63
+ def progress(callback = nil, &blk)
64
+ @callback = callback || blk
65
+ end
66
+
67
+
68
+ private
69
+
70
+
71
+ def on_timer(handle, status)
72
+ e = check_result(status)
73
+
74
+ if e
75
+ reject(e)
76
+ else
77
+ begin
78
+ @callback.call
79
+ rescue Exception => e
80
+ @loop.log :error, :timer_cb, e
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
data/lib/libuv/tty.rb CHANGED
@@ -1,37 +1,37 @@
1
- module Libuv
2
- class TTY < Handle
3
- include Stream
4
-
5
-
6
- def initialize(loop, fileno, readable)
7
- @loop = loop
8
-
9
- tty_ptr = ::Libuv::Ext.create_handle(:uv_tty)
10
- error = check_result(::Libuv::Ext.tty_init(loop.handle, tty_ptr, fileno, readable ? 1 : 0))
11
-
12
- super(tty_ptr, error)
13
- end
14
-
15
- def enable_raw_mode
16
- return if @closed
17
- check_result ::Libuv::Ext.tty_set_mode(handle, 1)
18
- end
19
-
20
- def disable_raw_mode
21
- return if @closed
22
- check_result ::Libuv::Ext.tty_set_mode(handle, 0)
23
- end
24
-
25
- def reset_mode
26
- ::Libuv::Ext.tty_reset_mode
27
- end
28
-
29
- def winsize
30
- return [] if @closed
31
- width = FFI::MemoryPointer.new(:int)
32
- height = FFI::MemoryPointer.new(:int)
33
- ::Libuv::Ext.tty_get_winsize(handle, width, height)
34
- [width.get_int(0), height.get_int(0)]
35
- end
36
- end
37
- end
1
+ module Libuv
2
+ class TTY < Handle
3
+ include Stream
4
+
5
+
6
+ def initialize(loop, fileno, readable)
7
+ @loop = loop
8
+
9
+ tty_ptr = ::Libuv::Ext.create_handle(:uv_tty)
10
+ error = check_result(::Libuv::Ext.tty_init(loop.handle, tty_ptr, fileno, readable ? 1 : 0))
11
+
12
+ super(tty_ptr, error)
13
+ end
14
+
15
+ def enable_raw_mode
16
+ return if @closed
17
+ check_result ::Libuv::Ext.tty_set_mode(handle, 1)
18
+ end
19
+
20
+ def disable_raw_mode
21
+ return if @closed
22
+ check_result ::Libuv::Ext.tty_set_mode(handle, 0)
23
+ end
24
+
25
+ def reset_mode
26
+ ::Libuv::Ext.tty_reset_mode
27
+ end
28
+
29
+ def winsize
30
+ return [] if @closed
31
+ width = FFI::MemoryPointer.new(:int)
32
+ height = FFI::MemoryPointer.new(:int)
33
+ ::Libuv::Ext.tty_get_winsize(handle, width, height)
34
+ [width.get_int(0), height.get_int(0)]
35
+ end
36
+ end
37
+ end
data/lib/libuv/udp.rb CHANGED
@@ -1,241 +1,241 @@
1
- module Libuv
2
- class UDP < Handle
3
- include Net
4
-
5
-
6
- SEND_DATA_ERROR = "data must be a String".freeze
7
- TTL_ARGUMENT_ERROR = "ttl must be an Integer".freeze
8
- MULTICAST_ARGUMENT_ERROR = "multicast_address must be a String".freeze
9
- INTERFACE_ARGUMENT_ERROR = "interface_address must be a String".freeze
10
- HANDLE_CLOSED_ERROR = "unable to send as handle closed".freeze
11
-
12
-
13
- def initialize(loop)
14
- @loop = loop
15
-
16
- udp_ptr = ::Libuv::Ext.create_handle(:uv_udp)
17
- error = check_result(::Libuv::Ext.udp_init(loop.handle, udp_ptr))
18
-
19
- super(udp_ptr, error)
20
- end
21
-
22
- def bind(ip, port)
23
- return if @closed
24
- assert_type(String, ip, IP_ARGUMENT_ERROR)
25
- assert_type(Integer, port, PORT_ARGUMENT_ERROR)
26
-
27
- sockaddr = create_sockaddr(ip, port)
28
- error = check_result ::Libuv::Ext.udp_bind(handle, sockaddr, 0)
29
- reject(error) if error
30
- end
31
-
32
- def open(fd, binding = true, callback = nil, &blk)
33
- return if @closed
34
- error = check_result UV.udp_open(handle, fd)
35
- reject(error) if error
36
- end
37
-
38
- def sockname
39
- return [] if @closed
40
- sockaddr, len = get_sockaddr_and_len
41
- check_result! ::Libuv::Ext.udp_getsockname(handle, sockaddr, len)
42
- get_ip_and_port(UV::Sockaddr.new(sockaddr), len.get_int(0))
43
- end
44
-
45
- def join(multicast_address, interface_address)
46
- return if @closed
47
- assert_type(String, multicast_address, MULTICAST_ARGUMENT_ERROR)
48
- assert_type(String, interface_address, INTERFACE_ARGUMENT_ERROR)
49
-
50
- error = check_result ::Libuv::Ext.udp_set_membership(handle, multicast_address, interface_address, :uv_join_group)
51
- reject(error) if error
52
- end
53
-
54
- def leave(multicast_address, interface_address)
55
- return if @closed
56
- assert_type(String, multicast_address, MULTICAST_ARGUMENT_ERROR)
57
- assert_type(String, interface_address, INTERFACE_ARGUMENT_ERROR)
58
-
59
- error = check_result ::Libuv::Ext.udp_set_membership(handle, multicast_address, interface_address, :uv_leave_group)
60
- reject(error) if error
61
- end
62
-
63
- # Starts reading from the handle
64
- # Renamed to match Stream
65
- def start_read
66
- return if @closed
67
- error = check_result ::Libuv::Ext.udp_recv_start(handle, callback(:on_allocate), callback(:on_recv))
68
- reject(error) if error
69
- end
70
-
71
- # Stops reading from the handle
72
- # Renamed to match Stream
73
- def stop_read
74
- return if @closed
75
- error = check_result ::Libuv::Ext.udp_recv_stop(handle)
76
- reject(error) if error
77
- end
78
-
79
- def send(ip, port, data)
80
- # NOTE:: Similar to stream.rb -> write
81
- deferred = @loop.defer
82
- if !@closed
83
- begin
84
- assert_type(String, ip, IP_ARGUMENT_ERROR)
85
- assert_type(Integer, port, PORT_ARGUMENT_ERROR)
86
- assert_type(String, data, SEND_DATA_ERROR)
87
-
88
- sockaddr = create_sockaddr(ip, port)
89
-
90
- # local as this variable will be avaliable until the handle is closed
91
- @sent_callbacks ||= []
92
-
93
- #
94
- # create the curried callback
95
- #
96
- callback = FFI::Function.new(:void, [:pointer, :int]) do |req, status|
97
- ::Libuv::Ext.free(req)
98
- # remove the callback from the array
99
- # assumes sends are done in order
100
- promise = @sent_callbacks.shift[0]
101
- resolve promise, status
102
- end
103
-
104
- #
105
- # Save the callback and return the promise
106
- #
107
- @sent_callbacks << [deferred, callback]
108
- error = check_result ::Libuv::Ext.udp_send(
109
- send_req,
110
- handle,
111
- buf_init(data),
112
- 1,
113
- sockaddr,
114
- callback
115
- )
116
- if error
117
- @sent_callbacks.pop
118
- deferred.reject(error)
119
- reject(error) # close the handle
120
- end
121
- rescue StandardError => e
122
- deferred.reject(e)
123
- end
124
- else
125
- deferred.reject(RuntimeError.new(HANDLE_CLOSED_ERROR))
126
- end
127
- deferred.promise
128
- end
129
-
130
- def enable_multicast_loop
131
- return if @closed
132
- error = check_result ::Libuv::Ext.udp_set_multicast_loop(handle, 1)
133
- reject(error) if error
134
- end
135
-
136
- def disable_multicast_loop
137
- return if @closed
138
- error = check_result ::Libuv::Ext.udp_set_multicast_loop(handle, 0)
139
- reject(error) if error
140
- end
141
-
142
- def multicast_ttl=(ttl)
143
- return if @closed
144
- assert_type(Integer, ttl, TTL_ARGUMENT_ERROR)
145
- error = check_result ::Libuv::Ext.udp_set_multicast_ttl(handle, ttl)
146
- reject(error) if error
147
- end
148
-
149
- def enable_broadcast
150
- return if @closed
151
- error = check_result ::Libuv::Ext.udp_set_broadcast(handle, 1)
152
- reject(error) if error
153
- end
154
-
155
- def disable_broadcast
156
- return if @closed
157
- error = check_result ::Libuv::Ext.udp_set_broadcast(handle, 0)
158
- reject(error) if error
159
- end
160
-
161
- def ttl=(ttl)
162
- return if @closed
163
- assert_type(Integer, ttl, TTL_ARGUMENT_ERROR)
164
- error = check_result ::Libuv::Ext.udp_set_ttl(handle, Integer(ttl))
165
- reject(error) if error
166
- end
167
-
168
- def progress(callback = nil, &blk)
169
- @progress = callback || blk
170
- end
171
-
172
-
173
- private
174
-
175
-
176
- def send_req
177
- ::Libuv::Ext.create_request(:uv_udp_send)
178
- end
179
-
180
- def buf_init(data)
181
- ::Libuv::Ext.buf_init(FFI::MemoryPointer.from_string(data), data.respond_to?(:bytesize) ? data.bytesize : data.size)
182
- end
183
-
184
- def create_sockaddr(ip, port)
185
- ips = IPAddr.new(ip)
186
- if ips.ipv4?
187
- addr = Ext::SockaddrIn.new
188
- check_result! ::Libuv::Ext.ip4_addr(ip, port, addr)
189
- addr
190
- else
191
- addr = Ext::SockaddrIn6.new
192
- check_result! ::Libuv::Ext.ip6_addr(ip, port, addr)
193
- addr
194
- end
195
- end
196
-
197
-
198
- def on_close(pointer)
199
- if @receive_buff
200
- ::Libuv::Ext.free(@receive_buff)
201
- @receive_buff = nil
202
- @receive_size = nil
203
- end
204
-
205
- super(pointer)
206
- end
207
-
208
- def on_allocate(client, suggested_size, buffer)
209
- if @receive_buff.nil?
210
- @receive_buff = ::Libuv::Ext.malloc(suggested_size)
211
- @receive_size = suggested_size
212
- end
213
-
214
- buffer[:base] = @receive_buff
215
- buffer[:len] = @receive_size
216
- end
217
-
218
- def on_recv(handle, nread, buf, sockaddr, flags)
219
- e = check_result(nread)
220
-
221
- if e
222
- reject(e) # Will call close
223
- elsif nread > 0
224
- data = @receive_buff.read_string(nread)
225
- unless sockaddr.null?
226
- ip, port = get_ip_and_port(sockaddr)
227
- end
228
-
229
- begin
230
- @progress.call data, ip, port, self
231
- rescue Exception => e
232
- @loop.log :error, :udp_progress_cb, e
233
- end
234
- else
235
- ::Libuv::Ext.free(@receive_buff)
236
- @receive_buff = nil
237
- @receive_size = nil
238
- end
239
- end
240
- end
1
+ module Libuv
2
+ class UDP < Handle
3
+ include Net
4
+
5
+
6
+ SEND_DATA_ERROR = "data must be a String".freeze
7
+ TTL_ARGUMENT_ERROR = "ttl must be an Integer".freeze
8
+ MULTICAST_ARGUMENT_ERROR = "multicast_address must be a String".freeze
9
+ INTERFACE_ARGUMENT_ERROR = "interface_address must be a String".freeze
10
+ HANDLE_CLOSED_ERROR = "unable to send as handle closed".freeze
11
+
12
+
13
+ def initialize(loop)
14
+ @loop = loop
15
+
16
+ udp_ptr = ::Libuv::Ext.create_handle(:uv_udp)
17
+ error = check_result(::Libuv::Ext.udp_init(loop.handle, udp_ptr))
18
+
19
+ super(udp_ptr, error)
20
+ end
21
+
22
+ def bind(ip, port)
23
+ return if @closed
24
+ assert_type(String, ip, IP_ARGUMENT_ERROR)
25
+ assert_type(Integer, port, PORT_ARGUMENT_ERROR)
26
+
27
+ sockaddr = create_sockaddr(ip, port)
28
+ error = check_result ::Libuv::Ext.udp_bind(handle, sockaddr, 0)
29
+ reject(error) if error
30
+ end
31
+
32
+ def open(fd, binding = true, callback = nil, &blk)
33
+ return if @closed
34
+ error = check_result UV.udp_open(handle, fd)
35
+ reject(error) if error
36
+ end
37
+
38
+ def sockname
39
+ return [] if @closed
40
+ sockaddr, len = get_sockaddr_and_len
41
+ check_result! ::Libuv::Ext.udp_getsockname(handle, sockaddr, len)
42
+ get_ip_and_port(UV::Sockaddr.new(sockaddr), len.get_int(0))
43
+ end
44
+
45
+ def join(multicast_address, interface_address)
46
+ return if @closed
47
+ assert_type(String, multicast_address, MULTICAST_ARGUMENT_ERROR)
48
+ assert_type(String, interface_address, INTERFACE_ARGUMENT_ERROR)
49
+
50
+ error = check_result ::Libuv::Ext.udp_set_membership(handle, multicast_address, interface_address, :uv_join_group)
51
+ reject(error) if error
52
+ end
53
+
54
+ def leave(multicast_address, interface_address)
55
+ return if @closed
56
+ assert_type(String, multicast_address, MULTICAST_ARGUMENT_ERROR)
57
+ assert_type(String, interface_address, INTERFACE_ARGUMENT_ERROR)
58
+
59
+ error = check_result ::Libuv::Ext.udp_set_membership(handle, multicast_address, interface_address, :uv_leave_group)
60
+ reject(error) if error
61
+ end
62
+
63
+ # Starts reading from the handle
64
+ # Renamed to match Stream
65
+ def start_read
66
+ return if @closed
67
+ error = check_result ::Libuv::Ext.udp_recv_start(handle, callback(:on_allocate), callback(:on_recv))
68
+ reject(error) if error
69
+ end
70
+
71
+ # Stops reading from the handle
72
+ # Renamed to match Stream
73
+ def stop_read
74
+ return if @closed
75
+ error = check_result ::Libuv::Ext.udp_recv_stop(handle)
76
+ reject(error) if error
77
+ end
78
+
79
+ def send(ip, port, data)
80
+ # NOTE:: Similar to stream.rb -> write
81
+ deferred = @loop.defer
82
+ if !@closed
83
+ begin
84
+ assert_type(String, ip, IP_ARGUMENT_ERROR)
85
+ assert_type(Integer, port, PORT_ARGUMENT_ERROR)
86
+ assert_type(String, data, SEND_DATA_ERROR)
87
+
88
+ sockaddr = create_sockaddr(ip, port)
89
+
90
+ # local as this variable will be avaliable until the handle is closed
91
+ @sent_callbacks ||= []
92
+
93
+ #
94
+ # create the curried callback
95
+ #
96
+ callback = FFI::Function.new(:void, [:pointer, :int]) do |req, status|
97
+ ::Libuv::Ext.free(req)
98
+ # remove the callback from the array
99
+ # assumes sends are done in order
100
+ promise = @sent_callbacks.shift[0]
101
+ resolve promise, status
102
+ end
103
+
104
+ #
105
+ # Save the callback and return the promise
106
+ #
107
+ @sent_callbacks << [deferred, callback]
108
+ error = check_result ::Libuv::Ext.udp_send(
109
+ send_req,
110
+ handle,
111
+ buf_init(data),
112
+ 1,
113
+ sockaddr,
114
+ callback
115
+ )
116
+ if error
117
+ @sent_callbacks.pop
118
+ deferred.reject(error)
119
+ reject(error) # close the handle
120
+ end
121
+ rescue StandardError => e
122
+ deferred.reject(e)
123
+ end
124
+ else
125
+ deferred.reject(RuntimeError.new(HANDLE_CLOSED_ERROR))
126
+ end
127
+ deferred.promise
128
+ end
129
+
130
+ def enable_multicast_loop
131
+ return if @closed
132
+ error = check_result ::Libuv::Ext.udp_set_multicast_loop(handle, 1)
133
+ reject(error) if error
134
+ end
135
+
136
+ def disable_multicast_loop
137
+ return if @closed
138
+ error = check_result ::Libuv::Ext.udp_set_multicast_loop(handle, 0)
139
+ reject(error) if error
140
+ end
141
+
142
+ def multicast_ttl=(ttl)
143
+ return if @closed
144
+ assert_type(Integer, ttl, TTL_ARGUMENT_ERROR)
145
+ error = check_result ::Libuv::Ext.udp_set_multicast_ttl(handle, ttl)
146
+ reject(error) if error
147
+ end
148
+
149
+ def enable_broadcast
150
+ return if @closed
151
+ error = check_result ::Libuv::Ext.udp_set_broadcast(handle, 1)
152
+ reject(error) if error
153
+ end
154
+
155
+ def disable_broadcast
156
+ return if @closed
157
+ error = check_result ::Libuv::Ext.udp_set_broadcast(handle, 0)
158
+ reject(error) if error
159
+ end
160
+
161
+ def ttl=(ttl)
162
+ return if @closed
163
+ assert_type(Integer, ttl, TTL_ARGUMENT_ERROR)
164
+ error = check_result ::Libuv::Ext.udp_set_ttl(handle, Integer(ttl))
165
+ reject(error) if error
166
+ end
167
+
168
+ def progress(callback = nil, &blk)
169
+ @progress = callback || blk
170
+ end
171
+
172
+
173
+ private
174
+
175
+
176
+ def send_req
177
+ ::Libuv::Ext.create_request(:uv_udp_send)
178
+ end
179
+
180
+ def buf_init(data)
181
+ ::Libuv::Ext.buf_init(FFI::MemoryPointer.from_string(data), data.respond_to?(:bytesize) ? data.bytesize : data.size)
182
+ end
183
+
184
+ def create_sockaddr(ip, port)
185
+ ips = IPAddr.new(ip)
186
+ if ips.ipv4?
187
+ addr = Ext::SockaddrIn.new
188
+ check_result! ::Libuv::Ext.ip4_addr(ip, port, addr)
189
+ addr
190
+ else
191
+ addr = Ext::SockaddrIn6.new
192
+ check_result! ::Libuv::Ext.ip6_addr(ip, port, addr)
193
+ addr
194
+ end
195
+ end
196
+
197
+
198
+ def on_close(pointer)
199
+ if @receive_buff
200
+ ::Libuv::Ext.free(@receive_buff)
201
+ @receive_buff = nil
202
+ @receive_size = nil
203
+ end
204
+
205
+ super(pointer)
206
+ end
207
+
208
+ def on_allocate(client, suggested_size, buffer)
209
+ if @receive_buff.nil?
210
+ @receive_buff = ::Libuv::Ext.malloc(suggested_size)
211
+ @receive_size = suggested_size
212
+ end
213
+
214
+ buffer[:base] = @receive_buff
215
+ buffer[:len] = @receive_size
216
+ end
217
+
218
+ def on_recv(handle, nread, buf, sockaddr, flags)
219
+ e = check_result(nread)
220
+
221
+ if e
222
+ reject(e) # Will call close
223
+ elsif nread > 0
224
+ data = @receive_buff.read_string(nread)
225
+ unless sockaddr.null?
226
+ ip, port = get_ip_and_port(sockaddr)
227
+ end
228
+
229
+ begin
230
+ @progress.call data, ip, port, self
231
+ rescue Exception => e
232
+ @loop.log :error, :udp_progress_cb, e
233
+ end
234
+ else
235
+ ::Libuv::Ext.free(@receive_buff)
236
+ @receive_buff = nil
237
+ @receive_size = nil
238
+ end
239
+ end
240
+ end
241
241
  end