libuv 0.11.3 → 0.11.4
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.
- checksums.yaml +14 -6
- data/.gitignore +17 -17
- data/.gitmodules +3 -3
- data/.rspec +1 -1
- data/.travis.yml +16 -16
- data/Gemfile +4 -4
- data/LICENSE +23 -23
- data/README.md +82 -82
- data/Rakefile +31 -31
- data/lib/libuv.rb +54 -54
- data/lib/libuv/async.rb +47 -47
- data/lib/libuv/check.rb +55 -55
- data/lib/libuv/dns.rb +85 -85
- data/lib/libuv/error.rb +73 -70
- data/lib/libuv/ext/ext.rb +258 -258
- data/lib/libuv/ext/platform/darwin_x64.rb +23 -23
- data/lib/libuv/ext/platform/linux.rb +7 -7
- data/lib/libuv/ext/platform/unix.rb +29 -29
- data/lib/libuv/ext/platform/windows.rb +40 -40
- data/lib/libuv/ext/tasks.rb +29 -29
- data/lib/libuv/ext/tasks/mac.rb +23 -23
- data/lib/libuv/ext/tasks/unix.rb +23 -23
- data/lib/libuv/ext/tasks/win.rb +11 -11
- data/lib/libuv/ext/types.rb +238 -238
- data/lib/libuv/file.rb +191 -191
- data/lib/libuv/filesystem.rb +232 -232
- data/lib/libuv/fs_event.rb +31 -31
- data/lib/libuv/handle.rb +85 -85
- data/lib/libuv/idle.rb +56 -56
- data/lib/libuv/loop.rb +387 -385
- data/lib/libuv/mixins/assertions.rb +23 -23
- data/lib/libuv/mixins/fs_checks.rb +55 -55
- data/lib/libuv/mixins/listener.rb +34 -34
- data/lib/libuv/mixins/net.rb +40 -40
- data/lib/libuv/mixins/resource.rb +27 -27
- data/lib/libuv/mixins/stream.rb +154 -154
- data/lib/libuv/pipe.rb +197 -197
- data/lib/libuv/prepare.rb +56 -56
- data/lib/libuv/signal.rb +51 -51
- data/lib/libuv/tcp.rb +317 -315
- data/lib/libuv/timer.rb +91 -91
- data/lib/libuv/tty.rb +37 -37
- data/lib/libuv/udp.rb +224 -224
- data/lib/libuv/version.rb +3 -3
- data/lib/libuv/work.rb +75 -75
- data/libuv.gemspec +56 -56
- data/spec/async_spec.rb +60 -60
- data/spec/cpu_spec.rb +10 -10
- data/spec/defer_spec.rb +980 -980
- data/spec/dns_spec.rb +90 -90
- data/spec/filesystem_spec.rb +124 -124
- data/spec/idle_spec.rb +56 -56
- data/spec/pipe_spec.rb +160 -160
- data/spec/tcp_spec.rb +267 -267
- metadata +24 -30
data/lib/libuv/timer.rb
CHANGED
@@ -1,91 +1,91 @@
|
|
1
|
-
module Libuv
|
2
|
-
class Timer < Handle
|
3
|
-
include Assertions
|
4
|
-
|
5
|
-
|
6
|
-
TIMEOUT_ERROR = "timeout must be an Integer".freeze
|
7
|
-
REPEAT_ERROR = "repeat must be an Integer".freeze
|
8
|
-
|
9
|
-
|
10
|
-
# @param loop [::Libuv::Loop] loop this timer will be associated
|
11
|
-
# @param callback [Proc] callback to be called when the timer is triggered
|
12
|
-
def initialize(loop, callback = nil)
|
13
|
-
@loop, @callback = loop, callback
|
14
|
-
|
15
|
-
timer_ptr = ::Libuv::Ext.create_handle(:uv_timer)
|
16
|
-
error = check_result(::Libuv::Ext.timer_init(loop.handle, timer_ptr))
|
17
|
-
@stopped = true
|
18
|
-
|
19
|
-
super(timer_ptr, error)
|
20
|
-
end
|
21
|
-
|
22
|
-
# Enables the timer. A repeat of 0 means no repeat
|
23
|
-
#
|
24
|
-
# @param timeout [Fixnum] time in milliseconds before the timer callback is triggered the first time
|
25
|
-
# @param repeat [Fixnum] time in milliseconds between repeated callbacks after the first
|
26
|
-
def start(timeout, repeat = 0)
|
27
|
-
return if @closed
|
28
|
-
@stopped = false
|
29
|
-
|
30
|
-
assert_type(Integer, timeout, TIMEOUT_ERROR)
|
31
|
-
assert_type(Integer, repeat, REPEAT_ERROR)
|
32
|
-
|
33
|
-
error = check_result ::Libuv::Ext.timer_start(handle, callback(:on_timer), timeout, repeat)
|
34
|
-
reject(error) if error
|
35
|
-
end
|
36
|
-
|
37
|
-
# Disables the timer.
|
38
|
-
def stop
|
39
|
-
return if @stopped || @closed
|
40
|
-
@stopped = true
|
41
|
-
error = check_result ::Libuv::Ext.timer_stop(handle)
|
42
|
-
reject(error) if error
|
43
|
-
end
|
44
|
-
|
45
|
-
# Resets the current repeat
|
46
|
-
def again
|
47
|
-
return if @closed
|
48
|
-
error = check_result ::Libuv::Ext.timer_again(handle)
|
49
|
-
reject(error) if error
|
50
|
-
end
|
51
|
-
|
52
|
-
# Updates the repeat timeout
|
53
|
-
def repeat=(repeat)
|
54
|
-
return if @closed
|
55
|
-
assert_type(Integer, repeat, REPEAT_ERROR)
|
56
|
-
check_result ::Libuv::Ext.timer_set_repeat(handle, repeat)
|
57
|
-
reject(error) if error
|
58
|
-
end
|
59
|
-
|
60
|
-
# Returns the current repeat timeout
|
61
|
-
def repeat
|
62
|
-
return if @closed
|
63
|
-
::Libuv::Ext.timer_get_repeat(handle)
|
64
|
-
end
|
65
|
-
|
66
|
-
# Used to update the callback to be triggered by the timer
|
67
|
-
#
|
68
|
-
# @param callback [Proc] the callback to be called by the timer
|
69
|
-
def progress(callback = nil, &blk)
|
70
|
-
@callback = callback || blk
|
71
|
-
end
|
72
|
-
|
73
|
-
|
74
|
-
private
|
75
|
-
|
76
|
-
|
77
|
-
def on_timer(handle, status)
|
78
|
-
e = check_result(status)
|
79
|
-
|
80
|
-
if e
|
81
|
-
reject(e)
|
82
|
-
else
|
83
|
-
begin
|
84
|
-
@callback.call
|
85
|
-
rescue Exception => e
|
86
|
-
@loop.log :error, :timer_cb, e
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
1
|
+
module Libuv
|
2
|
+
class Timer < Handle
|
3
|
+
include Assertions
|
4
|
+
|
5
|
+
|
6
|
+
TIMEOUT_ERROR = "timeout must be an Integer".freeze
|
7
|
+
REPEAT_ERROR = "repeat must be an Integer".freeze
|
8
|
+
|
9
|
+
|
10
|
+
# @param loop [::Libuv::Loop] loop this timer will be associated
|
11
|
+
# @param callback [Proc] callback to be called when the timer is triggered
|
12
|
+
def initialize(loop, callback = nil)
|
13
|
+
@loop, @callback = loop, callback
|
14
|
+
|
15
|
+
timer_ptr = ::Libuv::Ext.create_handle(:uv_timer)
|
16
|
+
error = check_result(::Libuv::Ext.timer_init(loop.handle, timer_ptr))
|
17
|
+
@stopped = true
|
18
|
+
|
19
|
+
super(timer_ptr, error)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Enables the timer. A repeat of 0 means no repeat
|
23
|
+
#
|
24
|
+
# @param timeout [Fixnum] time in milliseconds before the timer callback is triggered the first time
|
25
|
+
# @param repeat [Fixnum] time in milliseconds between repeated callbacks after the first
|
26
|
+
def start(timeout, repeat = 0)
|
27
|
+
return if @closed
|
28
|
+
@stopped = false
|
29
|
+
|
30
|
+
assert_type(Integer, timeout, TIMEOUT_ERROR)
|
31
|
+
assert_type(Integer, repeat, REPEAT_ERROR)
|
32
|
+
|
33
|
+
error = check_result ::Libuv::Ext.timer_start(handle, callback(:on_timer), timeout, repeat)
|
34
|
+
reject(error) if error
|
35
|
+
end
|
36
|
+
|
37
|
+
# Disables the timer.
|
38
|
+
def stop
|
39
|
+
return if @stopped || @closed
|
40
|
+
@stopped = true
|
41
|
+
error = check_result ::Libuv::Ext.timer_stop(handle)
|
42
|
+
reject(error) if error
|
43
|
+
end
|
44
|
+
|
45
|
+
# Resets the current repeat
|
46
|
+
def again
|
47
|
+
return if @closed
|
48
|
+
error = check_result ::Libuv::Ext.timer_again(handle)
|
49
|
+
reject(error) if error
|
50
|
+
end
|
51
|
+
|
52
|
+
# Updates the repeat timeout
|
53
|
+
def repeat=(repeat)
|
54
|
+
return if @closed
|
55
|
+
assert_type(Integer, repeat, REPEAT_ERROR)
|
56
|
+
check_result ::Libuv::Ext.timer_set_repeat(handle, repeat)
|
57
|
+
reject(error) if error
|
58
|
+
end
|
59
|
+
|
60
|
+
# Returns the current repeat timeout
|
61
|
+
def repeat
|
62
|
+
return if @closed
|
63
|
+
::Libuv::Ext.timer_get_repeat(handle)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Used to update the callback to be triggered by the timer
|
67
|
+
#
|
68
|
+
# @param callback [Proc] the callback to be called by the timer
|
69
|
+
def progress(callback = nil, &blk)
|
70
|
+
@callback = callback || blk
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
|
77
|
+
def on_timer(handle, status)
|
78
|
+
e = check_result(status)
|
79
|
+
|
80
|
+
if e
|
81
|
+
reject(e)
|
82
|
+
else
|
83
|
+
begin
|
84
|
+
@callback.call
|
85
|
+
rescue Exception => e
|
86
|
+
@loop.log :error, :timer_cb, e
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
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,225 +1,225 @@
|
|
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_allocate(client, suggested_size, buffer)
|
199
|
-
buffer[:len] = suggested_size
|
200
|
-
buffer[:base] = ::Libuv::Ext.malloc(suggested_size)
|
201
|
-
end
|
202
|
-
|
203
|
-
def on_recv(handle, nread, buf, sockaddr, flags)
|
204
|
-
e = check_result(nread)
|
205
|
-
base = buf[:base]
|
206
|
-
|
207
|
-
if e
|
208
|
-
::Libuv::Ext.free(base)
|
209
|
-
reject(e)
|
210
|
-
else
|
211
|
-
data = base.read_string(nread)
|
212
|
-
::Libuv::Ext.free(base)
|
213
|
-
unless sockaddr.null?
|
214
|
-
ip, port = get_ip_and_port(UV::Sockaddr.new(sockaddr))
|
215
|
-
end
|
216
|
-
|
217
|
-
begin
|
218
|
-
@progress.call data, ip, port, self
|
219
|
-
rescue Exception => e
|
220
|
-
@loop.log :error, :udp_progress_cb, e
|
221
|
-
end
|
222
|
-
end
|
223
|
-
end
|
224
|
-
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_allocate(client, suggested_size, buffer)
|
199
|
+
buffer[:len] = suggested_size
|
200
|
+
buffer[:base] = ::Libuv::Ext.malloc(suggested_size)
|
201
|
+
end
|
202
|
+
|
203
|
+
def on_recv(handle, nread, buf, sockaddr, flags)
|
204
|
+
e = check_result(nread)
|
205
|
+
base = buf[:base]
|
206
|
+
|
207
|
+
if e
|
208
|
+
::Libuv::Ext.free(base)
|
209
|
+
reject(e)
|
210
|
+
else
|
211
|
+
data = base.read_string(nread)
|
212
|
+
::Libuv::Ext.free(base)
|
213
|
+
unless sockaddr.null?
|
214
|
+
ip, port = get_ip_and_port(UV::Sockaddr.new(sockaddr))
|
215
|
+
end
|
216
|
+
|
217
|
+
begin
|
218
|
+
@progress.call data, ip, port, self
|
219
|
+
rescue Exception => e
|
220
|
+
@loop.log :error, :udp_progress_cb, e
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
225
|
end
|