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/net.rb ADDED
@@ -0,0 +1,31 @@
1
+ require 'socket'
2
+
3
+ module UV
4
+ module Net
5
+ private
6
+
7
+ def get_sockaddr_and_len
8
+ sockaddr = FFI::MemoryPointer.new(UV::Sockaddr)
9
+ len = FFI::MemoryPointer.new(:int)
10
+ len.put_int(0, UV::Sockaddr.size)
11
+ [sockaddr, len]
12
+ end
13
+
14
+ def get_ip_and_port(sockaddr, len=nil)
15
+ if sockaddr[:sa_family] == Socket::Constants::AF_INET6
16
+ len ||= Socket::Constants::INET6_ADDRSTRLEN
17
+ sockaddr_in6 = UV::SockaddrIn6.new(sockaddr.pointer)
18
+ ip_ptr = FFI::MemoryPointer.new(:char, len)
19
+ UV.ip6_name(sockaddr_in6, ip_ptr, len)
20
+ port = UV.ntohs(sockaddr_in6[:sin6_port])
21
+ else
22
+ len ||= Socket::Constants::INET_ADDRSTRLEN
23
+ sockaddr_in = UV::SockaddrIn.new(sockaddr.pointer)
24
+ ip_ptr = FFI::MemoryPointer.new(:char, len)
25
+ UV.ip4_name(sockaddr_in, ip_ptr, len)
26
+ port = UV.ntohs(sockaddr_in[:sin_port])
27
+ end
28
+ [ip_ptr.read_string, port]
29
+ end
30
+ end
31
+ end
data/lib/uv/pipe.rb ADDED
@@ -0,0 +1,47 @@
1
+ module UV
2
+ class Pipe
3
+ include Stream
4
+
5
+ def open(fileno)
6
+ assert_type(Integer, fileno, "io#fileno must return an integer file descriptor")
7
+
8
+ check_result! UV.pipe_open(handle, fileno)
9
+
10
+ self
11
+ end
12
+
13
+ def bind(name)
14
+ assert_type(String, name, "name must be a String")
15
+
16
+ check_result! UV.pipe_bind(handle, name)
17
+
18
+ self
19
+ end
20
+
21
+ def connect(name, &block)
22
+ assert_block(block)
23
+ assert_arity(1, block)
24
+ assert_type(String, name, "name must be a String")
25
+
26
+ @connect_block = block
27
+
28
+ UV.pipe_connect(UV.create_request(:uv_connect), handle, name, callback(:on_connect))
29
+
30
+ self
31
+ end
32
+
33
+ def pending_instances=(count)
34
+ assert_type(Integer, count, "count must be an Integer")
35
+
36
+ UV.pipe_pending_instances(handle, count)
37
+
38
+ self
39
+ end
40
+
41
+ private
42
+ def on_connect(req, status)
43
+ UV.free(req)
44
+ @connect_block.call(check_result(status))
45
+ end
46
+ end
47
+ end
data/lib/uv/prepare.rb ADDED
@@ -0,0 +1,27 @@
1
+ module UV
2
+ class Prepare
3
+ include Handle
4
+
5
+ def start(&block)
6
+ assert_block(block)
7
+ assert_arity(1, block)
8
+
9
+ @prepare_block = block
10
+
11
+ check_result! UV.prepare_start(handle, callback(:on_prepare))
12
+
13
+ self
14
+ end
15
+
16
+ def stop
17
+ check_result! UV.prepare_stop(handle)
18
+
19
+ self
20
+ end
21
+
22
+ private
23
+ def on_prepare(handle, status)
24
+ @prepare_block.call(check_result(status))
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,20 @@
1
+ module UV
2
+ module Resource
3
+ def check_result(rc)
4
+ @loop.last_error if rc == -1
5
+ end
6
+
7
+ def check_result!(rc)
8
+ e = check_result(rc)
9
+ raise e if e
10
+ end
11
+
12
+ def to_ptr
13
+ @pointer
14
+ end
15
+
16
+ protected
17
+
18
+ attr_reader :loop
19
+ end
20
+ end
data/lib/uv/stream.rb ADDED
@@ -0,0 +1,105 @@
1
+ module UV
2
+ module Stream
3
+ include Handle
4
+
5
+ def listen(backlog, &block)
6
+ assert_block(block)
7
+ assert_arity(1, block)
8
+ assert_type(Integer, backlog, "backlog must be an Integer")
9
+
10
+ @listen_block = block
11
+
12
+ check_result! UV.listen(handle, Integer(backlog), callback(:on_listen))
13
+
14
+ self
15
+ end
16
+
17
+ def accept
18
+ client = loop.send(handle_name)
19
+
20
+ check_result! UV.accept(handle, client.handle)
21
+
22
+ client
23
+ end
24
+
25
+ def start_read(&block)
26
+ assert_block(block)
27
+ assert_arity(2, block)
28
+
29
+ @read_block = block
30
+
31
+ check_result! UV.read_start(handle, callback(:on_allocate), callback(:on_read))
32
+
33
+ self
34
+ end
35
+
36
+ def stop_read
37
+ check_result! UV.read_stop(handle)
38
+
39
+ self
40
+ end
41
+
42
+ def write(data, &block)
43
+ assert_block(block)
44
+ assert_arity(1, block)
45
+ assert_type(String, data, "data must be a String")
46
+
47
+ @write_block = block
48
+ size = data.respond_to?(:bytesize) ? data.bytesize : data.size
49
+ buffer = UV.buf_init(FFI::MemoryPointer.from_string(data), size)
50
+
51
+ check_result! UV.write(UV.create_request(:uv_write), handle, buffer, 1, callback(:on_write))
52
+
53
+ self
54
+ end
55
+
56
+ def shutdown(&block)
57
+ assert_block(block)
58
+ assert_arity(1, block)
59
+
60
+ @shutdown_block = block
61
+
62
+ check_result! UV.shutdown(UV.create_request(:uv_shutdown), handle, callback(:on_shutdown))
63
+
64
+ self
65
+ end
66
+
67
+ def readable?
68
+ UV.is_readable(handle) > 0
69
+ end
70
+
71
+ def writable?
72
+ UV.is_writable(handle) > 0
73
+ end
74
+
75
+ private
76
+
77
+ def on_listen(server, status)
78
+ @listen_block.call(check_result(status))
79
+ end
80
+
81
+ def on_allocate(client, suggested_size)
82
+ UV.buf_init(UV.malloc(suggested_size), suggested_size)
83
+ end
84
+
85
+ def on_read(handle, nread, buf)
86
+ e = check_result(nread)
87
+ base = buf[:base]
88
+ unless e
89
+ data = base.read_string(nread)
90
+ end
91
+ UV.free(base)
92
+ @read_block.call(e, data)
93
+ end
94
+
95
+ def on_write(req, status)
96
+ UV.free(req)
97
+ @write_block.call(check_result(status))
98
+ end
99
+
100
+ def on_shutdown(req, status)
101
+ UV.free(req)
102
+ @shutdown_block.call(check_result(status))
103
+ end
104
+ end
105
+ end
data/lib/uv/tasks.rb ADDED
@@ -0,0 +1,27 @@
1
+ module FFI::Platform
2
+ def self.ia32?
3
+ ARCH == "i386"
4
+ end
5
+
6
+ def self.x64?
7
+ ARCH == "x86_64"
8
+ end
9
+ end
10
+
11
+ file 'ext/libuv/build' do
12
+ system "git", "submodule", "update", "--init"
13
+ end
14
+
15
+ file 'ext/libuv/build/gyp' => 'ext/libuv/build' do
16
+ system "svn", "export", "-r1214", "http://gyp.googlecode.com/svn/trunk", "ext/libuv/build/gyp"
17
+ end
18
+
19
+ CLEAN.include('ext/libuv/build/gyp')
20
+
21
+ if FFI::Platform.windows?
22
+ require 'uv/tasks/win'
23
+ elsif FFI::Platform.mac?
24
+ require 'uv/tasks/mac'
25
+ else # UNIX
26
+ require 'uv/tasks/unix'
27
+ end
@@ -0,0 +1,23 @@
1
+ file 'ext/libuv/uv.xcodeproj' => 'ext/libuv/build/gyp' do
2
+ target_arch = 'ia32'if FFI::Platform.ia32?
3
+ target_arch = 'x64' if FFI::Platform.x64?
4
+
5
+ abort "Don't know how to build on #{FFI::Platform::ARCH} (yet)" unless target_arch
6
+
7
+ Dir.chdir("ext/libuv") do |path|
8
+ system "./gyp_uv -f xcode -Dtarget_arch=#{target_arch}"
9
+ end
10
+ end
11
+
12
+ file "ext/libuv/build/Release/libuv.#{FFI::Platform::LIBSUFFIX}" => 'ext/libuv/uv.xcodeproj' do
13
+ Dir.chdir("ext/libuv") do |path|
14
+ system 'xcodebuild -project uv.xcodeproj -configuration Release -target All'
15
+ end
16
+ end
17
+
18
+ file "ext/libuv.#{FFI::Platform::LIBSUFFIX}" => "ext/libuv/build/Release/libuv.#{FFI::Platform::LIBSUFFIX}" do
19
+ File.symlink("libuv/build/Release/libuv.#{FFI::Platform::LIBSUFFIX}", "ext/libuv.#{FFI::Platform::LIBSUFFIX}")
20
+ end
21
+
22
+ CLEAN.include('ext/libuv/uv.xcodeproj')
23
+ CLOBBER.include("ext/libuv/build/Release/libuv.#{FFI::Platform::LIBSUFFIX}")
@@ -0,0 +1,23 @@
1
+ file 'ext/libuv/out' => 'ext/libuv/build/gyp' do
2
+ target_arch = 'ia32'if FFI::Platform.ia32?
3
+ target_arch = 'x64' if FFI::Platform.x64?
4
+
5
+ abort "Don't know how to build on #{FFI::Platform::ARCH} (yet)" unless target_arch
6
+
7
+ Dir.chdir("ext/libuv") do |path|
8
+ system "./gyp_uv -f make -Dtarget_arch=#{target_arch}"
9
+ end
10
+ end
11
+
12
+ file "ext/libuv/out/Release/lib.target/libuv.#{FFI::Platform::LIBSUFFIX}" => 'ext/libuv/out' do
13
+ Dir.chdir("ext/libuv") do |path|
14
+ system 'make -C out BUILDTYPE=Release'
15
+ end
16
+ end
17
+
18
+ file "ext/libuv.#{FFI::Platform::LIBSUFFIX}" => "ext/libuv/out/Release/lib.target/libuv.#{FFI::Platform::LIBSUFFIX}" do
19
+ File.symlink("libuv/out/Release/lib.target/libuv.#{FFI::Platform::LIBSUFFIX}", "ext/libuv.#{FFI::Platform::LIBSUFFIX}")
20
+ end
21
+
22
+ CLEAN.include('ext/libuv/out')
23
+ CLOBBER.include("ext/libuv/out/Release/lib.target/libuv.#{FFI::Platform::LIBSUFFIX}")
@@ -0,0 +1,2 @@
1
+ abort "can't build on windows using this rake task (yet)"
2
+ configure_command = 'vcbuild.bat'
data/lib/uv/tcp.rb ADDED
@@ -0,0 +1,162 @@
1
+ require 'ipaddr'
2
+
3
+ module UV
4
+ class TCP
5
+ include Stream, Net
6
+
7
+ def bind(ip, port)
8
+ assert_type(String, ip, "ip must be a String")
9
+ assert_type(Integer, port, "port must be an Integer")
10
+
11
+ @socket = create_socket(IPAddr.new(ip), port)
12
+
13
+ @socket.bind
14
+
15
+ self
16
+ end
17
+
18
+ def connect(ip, port, &block)
19
+ assert_block(block)
20
+ assert_arity(1, block)
21
+ assert_type(String, ip, "ip must be a String")
22
+ assert_type(Integer, port, "port must be an Integer")
23
+
24
+ @connect_block = block
25
+ @socket = create_socket(IPAddr.new(ip), port)
26
+
27
+ @socket.connect(callback(:on_connect))
28
+
29
+ self
30
+ end
31
+
32
+ def sockname
33
+ sockaddr, len = get_sockaddr_and_len
34
+ check_result! UV.tcp_getsockname(handle, sockaddr, len)
35
+ get_ip_and_port(UV::Sockaddr.new(sockaddr), len.get_int(0))
36
+ end
37
+
38
+ def peername
39
+ sockaddr, len = get_sockaddr_and_len
40
+ check_result! UV.tcp_getpeername(handle, sockaddr, len)
41
+ get_ip_and_port(UV::Sockaddr.new(sockaddr), len.get_int(0))
42
+ end
43
+
44
+ def enable_nodelay
45
+ check_result! UV.tcp_nodelay(handle, 1)
46
+
47
+ self
48
+ end
49
+
50
+ def disable_nodelay
51
+ check_result! UV.tcp_nodelay(handle, 0)
52
+
53
+ self
54
+ end
55
+
56
+ def enable_keepalive(delay)
57
+ assert_type(Integer, delay, "delay must be an Integer")
58
+
59
+ check_result! UV.tcp_keepalive(handle, 1, delay)
60
+
61
+ self
62
+ end
63
+
64
+ def disable_keepalive
65
+ check_result! UV.tcp_keepalive(handle, 0, 0)
66
+
67
+ self
68
+ end
69
+
70
+ def enable_simultaneous_accepts
71
+ check_result! UV.tcp_simultaneous_accepts(handle, 1)
72
+
73
+ self
74
+ end
75
+
76
+ def disable_simultaneous_accepts
77
+ check_result! UV.tcp_simultaneous_accepts(handle, 0)
78
+
79
+ self
80
+ end
81
+
82
+ private
83
+ def create_socket(ip, port)
84
+ if ip.ipv4?
85
+ Socket4.new(@loop, handle, ip.to_s, port)
86
+ else
87
+ Socket6.new(@loop, handle, ip.to_s, port)
88
+ end
89
+ end
90
+
91
+ def on_connect(req, status)
92
+ UV.free(req)
93
+ @connect_block.call(check_result(status))
94
+ end
95
+
96
+ module SocketMethods
97
+ include Resource
98
+
99
+ def initialize(loop, tcp, ip, port)
100
+ @loop, @tcp, @sockaddr = loop, tcp, ip_addr(ip, port)
101
+ end
102
+
103
+ def bind
104
+ check_result! tcp_bind
105
+ end
106
+
107
+ def connect(callback)
108
+ check_result! tcp_connect(callback)
109
+ end
110
+
111
+ private
112
+
113
+ def connect_req
114
+ UV.create_request(:uv_connect)
115
+ end
116
+ end
117
+
118
+ class Socket4
119
+ include SocketMethods
120
+
121
+ private
122
+ def ip_addr(ip, port)
123
+ UV.ip4_addr(ip, port)
124
+ end
125
+
126
+ def tcp_bind
127
+ UV.tcp_bind(@tcp, @sockaddr)
128
+ end
129
+
130
+ def tcp_connect(callback)
131
+ UV.tcp_connect(
132
+ connect_req,
133
+ @tcp,
134
+ @sockaddr,
135
+ callback
136
+ )
137
+ end
138
+ end
139
+
140
+ class Socket6
141
+ include SocketMethods
142
+
143
+ private
144
+ def ip_addr(ip, port)
145
+ UV.ip6_addr(ip, port)
146
+ end
147
+
148
+ def tcp_bind
149
+ UV.tcp_bind6(@tcp, @sockaddr)
150
+ end
151
+
152
+ def tcp_connect(callback)
153
+ UV.tcp_connect6(
154
+ connect_req,
155
+ @tcp,
156
+ @sockaddr,
157
+ callback
158
+ )
159
+ end
160
+ end
161
+ end
162
+ end