libuv 0.10.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 (49) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +17 -0
  3. data/.gitmodules +3 -0
  4. data/.rspec +1 -0
  5. data/.travis.yml +16 -0
  6. data/Gemfile +2 -0
  7. data/LICENSE +24 -0
  8. data/README.md +73 -0
  9. data/Rakefile +31 -0
  10. data/lib/libuv.rb +34 -0
  11. data/lib/libuv/assertions.rb +23 -0
  12. data/lib/libuv/async.rb +33 -0
  13. data/lib/libuv/check.rb +49 -0
  14. data/lib/libuv/error.rb +70 -0
  15. data/lib/libuv/ext/ext.rb +257 -0
  16. data/lib/libuv/ext/platform/darwin_x64.rb +12 -0
  17. data/lib/libuv/ext/platform/linux.rb +8 -0
  18. data/lib/libuv/ext/platform/unix.rb +14 -0
  19. data/lib/libuv/ext/platform/windows.rb +27 -0
  20. data/lib/libuv/ext/tasks.rb +27 -0
  21. data/lib/libuv/ext/tasks/mac.rb +23 -0
  22. data/lib/libuv/ext/tasks/unix.rb +23 -0
  23. data/lib/libuv/ext/tasks/win.rb +11 -0
  24. data/lib/libuv/ext/types.rb +230 -0
  25. data/lib/libuv/fs_event.rb +31 -0
  26. data/lib/libuv/handle.rb +82 -0
  27. data/lib/libuv/idle.rb +49 -0
  28. data/lib/libuv/listener.rb +34 -0
  29. data/lib/libuv/loop.rb +310 -0
  30. data/lib/libuv/net.rb +38 -0
  31. data/lib/libuv/pipe.rb +97 -0
  32. data/lib/libuv/prepare.rb +49 -0
  33. data/lib/libuv/q.rb +429 -0
  34. data/lib/libuv/resource.rb +28 -0
  35. data/lib/libuv/simple_async.rb +28 -0
  36. data/lib/libuv/stream.rb +124 -0
  37. data/lib/libuv/tcp.rb +194 -0
  38. data/lib/libuv/timer.rb +75 -0
  39. data/lib/libuv/tty.rb +34 -0
  40. data/lib/libuv/udp.rb +256 -0
  41. data/lib/libuv/version.rb +3 -0
  42. data/lib/libuv/work.rb +62 -0
  43. data/libuv.gemspec +54 -0
  44. data/spec/async_spec.rb +60 -0
  45. data/spec/defer_spec.rb +980 -0
  46. data/spec/idle_spec.rb +56 -0
  47. data/spec/pipe_spec.rb +148 -0
  48. data/spec/tcp_spec.rb +188 -0
  49. metadata +382 -0
@@ -0,0 +1,28 @@
1
+ module Libuv
2
+ module Resource
3
+
4
+
5
+ def resolve(deferred, rc)
6
+ if rc.nil? || rc >= 0
7
+ deferred.resolve(nil)
8
+ else
9
+ deferred.reject(@loop.lookup_error(rc))
10
+ end
11
+ end
12
+
13
+ def check_result!(rc)
14
+ e = @loop.lookup_error(rc) unless rc.nil? || rc >= 0
15
+ raise e if e
16
+ end
17
+
18
+ def check_result(rc)
19
+ @loop.lookup_error(rc) unless rc.nil? || rc >= 0
20
+ end
21
+
22
+ def to_ptr
23
+ @pointer
24
+ end
25
+
26
+
27
+ end
28
+ end
@@ -0,0 +1,28 @@
1
+ module Libuv
2
+ class SimpleAsync < Async
3
+
4
+
5
+ def initialize(loop, callback = nil, &blk)
6
+ @callback = callback || blk
7
+ super(loop)
8
+ end
9
+
10
+
11
+ private
12
+
13
+
14
+ def on_async(handle, status)
15
+ e = check_result(status)
16
+
17
+ if e
18
+ reject(e)
19
+ else
20
+ begin
21
+ @callback.call
22
+ rescue Exception => e
23
+ @loop.log :error, :simple_async_cb, e
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,124 @@
1
+ module Libuv
2
+ module Stream
3
+
4
+
5
+ BACKLOG_ERROR = "backlog must be an Integer".freeze
6
+ WRITE_ERROR = "data must be a String".freeze
7
+
8
+
9
+ def listen(backlog)
10
+ return if @closed
11
+ assert_type(Integer, backlog, BACKLOG_ERROR)
12
+ error = check_result ::Libuv::Ext.listen(handle, Integer(backlog), callback(:on_listen))
13
+ reject(error) if error
14
+ end
15
+
16
+ # Starts reading from the handle
17
+ def start_read
18
+ error = check_result ::Libuv::Ext.read_start(handle, callback(:on_allocate), callback(:on_read))
19
+ reject(error) if error
20
+ end
21
+
22
+ # Stops reading from the handle
23
+ def stop_read
24
+ error = check_result ::Libuv::Ext.read_stop(handle)
25
+ reject(error) if error
26
+ end
27
+
28
+ # Shutsdown the writes on the handle waiting until the last write is complete before triggering the callback
29
+ def shutdown
30
+ error = check_result ::Libuv::Ext.shutdown(::Libuv::Ext.create_request(:uv_shutdown), handle, callback(:on_shutdown))
31
+ reject(error) if error
32
+ end
33
+
34
+ def write(data)
35
+ deferred = @loop.defer
36
+ begin
37
+ assert_type(String, data, WRITE_ERROR)
38
+
39
+ size = data.respond_to?(:bytesize) ? data.bytesize : data.size
40
+ buffer = ::Libuv::Ext.buf_init(FFI::MemoryPointer.from_string(data), size)
41
+
42
+ # local as this variable will be avaliable until the handle is closed
43
+ @write_callbacks = @write_callbacks || []
44
+
45
+ #
46
+ # create the curried callback
47
+ #
48
+ callback = FFI::Function.new(:void, [:pointer, :int]) do |req, status|
49
+ ::Libuv::Ext.free(req)
50
+ # remove the callback from the array
51
+ # assumes writes are done in order
52
+ promise = @write_callbacks.shift[0]
53
+ resolve promise, status
54
+ end
55
+
56
+
57
+ @write_callbacks << [deferred, callback]
58
+ req = ::Libuv::Ext.create_request(:uv_write)
59
+ error = check_result ::Libuv::Ext.write(req, handle, buffer, 1, callback)
60
+
61
+ if error
62
+ @write_callbacks.pop
63
+ ::Libuv::Ext.free(req)
64
+ deferred.reject(error)
65
+
66
+ reject(error) # close the handle
67
+ end
68
+ rescue Exception => e
69
+ deferred.reject(e) # this write exception may not be fatal
70
+ end
71
+ deferred.promise
72
+ end
73
+
74
+ def readable?
75
+ ::Libuv::Ext.is_readable(handle) > 0
76
+ end
77
+
78
+ def writable?
79
+ ::Libuv::Ext.is_writable(handle) > 0
80
+ end
81
+
82
+
83
+ private
84
+
85
+
86
+ def on_listen(server, status)
87
+ e = check_result(status)
88
+
89
+ if e
90
+ reject(e) # is this cause for closing the handle?
91
+ else
92
+ begin
93
+ @on_listen.call(self)
94
+ rescue Exception => e
95
+ @loop.log :error, :stream_listen_cb, e
96
+ end
97
+ end
98
+ end
99
+
100
+ def on_allocate(client, suggested_size)
101
+ ::Libuv::Ext.buf_init(::Libuv::Ext.malloc(suggested_size), suggested_size)
102
+ end
103
+
104
+ def on_read(handle, nread, buf)
105
+ e = check_result(nread)
106
+ base = buf[:base]
107
+
108
+ if e
109
+ ::Libuv::Ext.free(base)
110
+ reject(e)
111
+ else
112
+ data = base.read_string(nread)
113
+ ::Libuv::Ext.free(base)
114
+ defer.notify(data) # stream the data
115
+ end
116
+ end
117
+
118
+ def on_shutdown(req, status)
119
+ ::Libuv::Ext.free(req)
120
+ @close_error = check_result(status)
121
+ close
122
+ end
123
+ end
124
+ end
data/lib/libuv/tcp.rb ADDED
@@ -0,0 +1,194 @@
1
+ require 'ipaddr'
2
+
3
+
4
+ module Libuv
5
+ class TCP < Handle
6
+ include Stream, Net
7
+
8
+
9
+ KEEPALIVE_ARGUMENT_ERROR = "delay must be an Integer".freeze
10
+
11
+
12
+ def initialize(loop, acceptor = nil)
13
+ @loop = loop
14
+
15
+ tcp_ptr = ::Libuv::Ext.create_handle(:uv_tcp)
16
+ error = check_result(::Libuv::Ext.tcp_init(loop.handle, tcp_ptr))
17
+ error = check_result(::Libuv::Ext.accept(acceptor, tcp_ptr)) if acceptor && error.nil?
18
+
19
+ super(tcp_ptr, error)
20
+ end
21
+
22
+ def bind(ip, port, callback = nil, &blk)
23
+ @on_listen = callback || blk
24
+ assert_type(String, ip, IP_ARGUMENT_ERROR)
25
+ assert_type(Integer, port, PORT_ARGUMENT_ERROR)
26
+
27
+ begin
28
+ @tcp_socket = create_socket(IPAddr.new(ip), port)
29
+ @tcp_socket.bind
30
+ rescue Exception => e
31
+ reject(e)
32
+ end
33
+ end
34
+
35
+ def accept(callback = nil, &blk)
36
+ tcp = nil
37
+ begin
38
+ tcp = TCP.new(loop, handle)
39
+ rescue Exception => e
40
+ @loop.log :info, :tcp_accept_failed, e
41
+ end
42
+ if tcp
43
+ begin
44
+ (callback || blk).call(tcp)
45
+ rescue Exception => e
46
+ @loop.log :error, :tcp_accept_cb, e
47
+ end
48
+ end
49
+ nil
50
+ end
51
+
52
+ def connect(ip, port, callback = nil, &blk)
53
+ @callback = callback || blk
54
+ assert_type(String, ip, IP_ARGUMENT_ERROR)
55
+ assert_type(Integer, port, PORT_ARGUMENT_ERROR)
56
+
57
+ begin
58
+ @tcp_socket = create_socket(IPAddr.new(ip), port)
59
+ @tcp_socket.connect(callback(:on_connect))
60
+ rescue Exception => e
61
+ reject(e)
62
+ end
63
+ end
64
+
65
+ def sockname
66
+ sockaddr, len = get_sockaddr_and_len
67
+ check_result! ::Libuv::Ext.tcp_getsockname(handle, sockaddr, len)
68
+ get_ip_and_port(::Libuv::Sockaddr.new(sockaddr), len.get_int(0))
69
+ end
70
+
71
+ def peername
72
+ sockaddr, len = get_sockaddr_and_len
73
+ check_result! ::Libuv::Ext.tcp_getpeername(handle, sockaddr, len)
74
+ get_ip_and_port(::Libuv::Sockaddr.new(sockaddr), len.get_int(0))
75
+ end
76
+
77
+ def enable_nodelay
78
+ check_result ::Libuv::Ext.tcp_nodelay(handle, 1)
79
+ end
80
+
81
+ def disable_nodelay
82
+ check_result ::Libuv::Ext.tcp_nodelay(handle, 0)
83
+ end
84
+
85
+ def enable_keepalive(delay)
86
+ assert_type(Integer, delay, KEEPALIVE_ARGUMENT_ERROR)
87
+ check_result ::Libuv::Ext.tcp_keepalive(handle, 1, delay)
88
+ end
89
+
90
+ def disable_keepalive
91
+ check_result ::Libuv::Ext.tcp_keepalive(handle, 0, 0)
92
+ end
93
+
94
+ def enable_simultaneous_accepts
95
+ check_result ::Libuv::Ext.tcp_simultaneous_accepts(handle, 1)
96
+ end
97
+
98
+ def disable_simultaneous_accepts
99
+ check_result ::Libuv::Ext.tcp_simultaneous_accepts(handle, 0)
100
+ end
101
+
102
+
103
+ private
104
+
105
+
106
+ def create_socket(ip, port)
107
+ if ip.ipv4?
108
+ Socket4.new(loop, handle, ip.to_s, port)
109
+ else
110
+ Socket6.new(loop, handle, ip.to_s, port)
111
+ end
112
+ end
113
+
114
+ def on_connect(req, status)
115
+ ::Libuv::Ext.free(req)
116
+ @callback.call(self)
117
+ end
118
+
119
+
120
+ class SocketBase
121
+ include Resource
122
+
123
+ def initialize(loop, tcp, ip, port)
124
+ @tcp, @sockaddr = tcp, ip_addr(ip, port)
125
+ end
126
+
127
+ def bind
128
+ check_result!(tcp_bind)
129
+ end
130
+
131
+ def connect(callback)
132
+ check_result!(tcp_connect(callback))
133
+ end
134
+
135
+
136
+ private
137
+
138
+
139
+ def connect_req
140
+ ::Libuv::Ext.create_request(:uv_connect)
141
+ end
142
+ end
143
+
144
+
145
+ class Socket4 < SocketBase
146
+
147
+
148
+ private
149
+
150
+
151
+ def ip_addr(ip, port)
152
+ ::Libuv::Ext.ip4_addr(ip, port)
153
+ end
154
+
155
+ def tcp_bind
156
+ ::Libuv::Ext.tcp_bind(@tcp, @sockaddr)
157
+ end
158
+
159
+ def tcp_connect(callback)
160
+ ::Libuv::Ext.tcp_connect(
161
+ connect_req,
162
+ @tcp,
163
+ @sockaddr,
164
+ callback
165
+ )
166
+ end
167
+ end
168
+
169
+
170
+ class Socket6 < SocketBase
171
+
172
+
173
+ private
174
+
175
+
176
+ def ip_addr(ip, port)
177
+ ::Libuv::Ext.ip6_addr(ip, port)
178
+ end
179
+
180
+ def tcp_bind
181
+ ::Libuv::Ext.tcp_bind6(@tcp, @sockaddr)
182
+ end
183
+
184
+ def tcp_connect(callback)
185
+ ::Libuv::Ext.tcp_connect6(
186
+ connect_req,
187
+ @tcp,
188
+ @sockaddr,
189
+ callback
190
+ )
191
+ end
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,75 @@
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
+ def initialize(loop, callback = nil)
11
+ @loop, @callback = loop, callback
12
+
13
+ timer_ptr = ::Libuv::Ext.create_handle(:uv_timer)
14
+ error = check_result(::Libuv::Ext.timer_init(loop.handle, timer_ptr))
15
+
16
+ super(timer_ptr, error)
17
+ end
18
+
19
+ def start(timeout, repeat = 0)
20
+ return if @closed
21
+
22
+ assert_type(Integer, timeout, TIMEOUT_ERROR)
23
+ assert_type(Integer, repeat, REPEAT_ERROR)
24
+
25
+ error = check_result ::Libuv::Ext.timer_start(handle, callback(:on_timer), timeout, repeat)
26
+ reject(error) if error
27
+ end
28
+
29
+ def stop
30
+ return if @closed
31
+ error = check_result ::Libuv::Ext.timer_stop(handle)
32
+ reject(error) if error
33
+ end
34
+
35
+ def again
36
+ return if @closed
37
+ error = check_result ::Libuv::Ext.timer_again(handle)
38
+ reject(error) if error
39
+ end
40
+
41
+ def repeat=(repeat)
42
+ return if @closed
43
+ assert_type(Integer, repeat, REPEAT_ERROR)
44
+ check_result ::Libuv::Ext.timer_set_repeat(handle, repeat)
45
+ reject(error) if error
46
+ end
47
+
48
+ def repeat
49
+ return if @closed
50
+ ::Libuv::Ext.timer_get_repeat(handle)
51
+ end
52
+
53
+ def progress(callback = nil, &blk)
54
+ @callback = callback || blk
55
+ end
56
+
57
+
58
+ private
59
+
60
+
61
+ def on_timer(handle, status)
62
+ e = check_result(status)
63
+
64
+ if e
65
+ reject(e)
66
+ else
67
+ begin
68
+ @callback.call
69
+ rescue Exception => e
70
+ @loop.log :error, :timer_cb, e
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end