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.
- data/.gitignore +17 -0
- data/.gitmodules +3 -0
- data/.rspec +2 -0
- data/.travis.yml +13 -0
- data/Formula/libuv.rb +20 -0
- data/Gemfile +3 -0
- data/LICENSE +24 -0
- data/README.rdoc +70 -0
- data/Rakefile +29 -0
- data/examples/example +0 -0
- data/examples/example.c +37 -0
- data/examples/example.rb +29 -0
- data/examples/example_oop.rb +26 -0
- data/examples/python.py +1 -0
- data/examples/ruby.rb +1 -0
- data/examples/tcp_client_oop.rb +31 -0
- data/examples/tcp_example +0 -0
- data/examples/tcp_example.c +68 -0
- data/examples/tcp_example.rb +41 -0
- data/examples/tcp_example_oop.rb +43 -0
- data/examples/tcp_example_plain.rb +19 -0
- data/examples/tty_example.rb +20 -0
- data/features/async.feature +38 -0
- data/features/idle.feature +44 -0
- data/features/pipe.feature +150 -0
- data/features/prepare_and_check.feature +49 -0
- data/features/step_definitions/additional_cli_steps.rb +20 -0
- data/features/support/env.rb +6 -0
- data/lib/uv.rb +248 -0
- data/lib/uv/assertions.rb +24 -0
- data/lib/uv/async.rb +24 -0
- data/lib/uv/check.rb +27 -0
- data/lib/uv/error.rb +58 -0
- data/lib/uv/file.rb +221 -0
- data/lib/uv/file/stat.rb +35 -0
- data/lib/uv/filesystem.rb +335 -0
- data/lib/uv/fs_event.rb +21 -0
- data/lib/uv/handle.rb +65 -0
- data/lib/uv/idle.rb +27 -0
- data/lib/uv/listener.rb +26 -0
- data/lib/uv/loop.rb +326 -0
- data/lib/uv/net.rb +31 -0
- data/lib/uv/pipe.rb +47 -0
- data/lib/uv/prepare.rb +27 -0
- data/lib/uv/resource.rb +20 -0
- data/lib/uv/stream.rb +105 -0
- data/lib/uv/tasks.rb +27 -0
- data/lib/uv/tasks/mac.rb +23 -0
- data/lib/uv/tasks/unix.rb +23 -0
- data/lib/uv/tasks/win.rb +2 -0
- data/lib/uv/tcp.rb +162 -0
- data/lib/uv/timer.rb +48 -0
- data/lib/uv/tty.rb +30 -0
- data/lib/uv/types.rb +249 -0
- data/lib/uv/types/darwin_x64.rb +10 -0
- data/lib/uv/types/linux.rb +6 -0
- data/lib/uv/types/unix.rb +12 -0
- data/lib/uv/types/windows.rb +13 -0
- data/lib/uv/udp.rb +215 -0
- data/lib/uv/version.rb +3 -0
- data/lib/uvrb.rb +1 -0
- data/spec/shared_examples/handle.rb +54 -0
- data/spec/shared_examples/stream.rb +109 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/uv/async_spec.rb +18 -0
- data/spec/uv/check_spec.rb +30 -0
- data/spec/uv/file_spec.rb +177 -0
- data/spec/uv/filesystem_spec.rb +246 -0
- data/spec/uv/fs_event_spec.rb +10 -0
- data/spec/uv/idle_spec.rb +30 -0
- data/spec/uv/loop_spec.rb +241 -0
- data/spec/uv/pipe_spec.rb +54 -0
- data/spec/uv/prepare_spec.rb +30 -0
- data/spec/uv/tcp_spec.rb +134 -0
- data/spec/uv/timer_spec.rb +61 -0
- data/spec/uv/tty_spec.rb +53 -0
- data/spec/uv/udp_spec.rb +190 -0
- data/uvrb.gemspec +28 -0
- metadata +247 -0
data/.gitignore
ADDED
data/.gitmodules
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Formula/libuv.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'formula'
|
2
|
+
|
3
|
+
class Libuv < Formula
|
4
|
+
homepage 'https://github.com/joyent/libuv'
|
5
|
+
head 'https://github.com/avalanche123/libuv.git'
|
6
|
+
|
7
|
+
def install
|
8
|
+
system "svn", "co", "http://gyp.googlecode.com/svn/trunk", "build/gyp"
|
9
|
+
system './gyp_uv -f xcode -Dtarget_arch=x64'
|
10
|
+
system 'xcodebuild', '-project', 'uv.xcodeproj', '-configuration', 'Release', '-target', 'All'
|
11
|
+
|
12
|
+
cd 'include' do
|
13
|
+
include.install Dir['*.h']
|
14
|
+
(include+"uv-private").install Dir['uv-private/*.h']
|
15
|
+
end
|
16
|
+
|
17
|
+
lib.install 'build/Release/libuv.a'
|
18
|
+
lib.install 'build/Release/libuv.dylib'
|
19
|
+
end
|
20
|
+
end
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
Copyright (c) 2004-2012 Bulat Shakirzyanov
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is furnished
|
8
|
+
to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
11
|
+
copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
20
|
+
|
21
|
+
===
|
22
|
+
|
23
|
+
This license applies to all parts of uvrb (Ruby FFI bindings for libuv only)
|
24
|
+
Libuv itself [is using Node license](https://github.com/joyent/libuv/blob/master/LICENSE)
|
data/README.rdoc
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
= uv.rb - libuv FFI bindings for Ruby
|
2
|
+
{<img src="https://secure.travis-ci.org/avalanche123/uvrb.png?branch=master" alt="Build Status" />}[http://travis-ci.org/avalanche123/uvrb]
|
3
|
+
|
4
|
+
{Libuv}[https://github.com/joyent/libuv] is a cross platform asynchronous IO implementation that powers NodeJS. It supports sockets, both UDP and TCP, filesystem operations, TTY, Pipes and other asynchronous primitives like timer, check, prepare and idle.
|
5
|
+
|
6
|
+
UV.rb is FFI Ruby bindings for libuv.
|
7
|
+
|
8
|
+
== Usage
|
9
|
+
|
10
|
+
Create a uv loop or use a default one
|
11
|
+
|
12
|
+
require 'uv'
|
13
|
+
|
14
|
+
loop = UV::Loop.default
|
15
|
+
# or
|
16
|
+
# loop = UV::Loop.new
|
17
|
+
|
18
|
+
timer = loop.timer
|
19
|
+
timer.start(50000, 0) do |error|
|
20
|
+
p error if error
|
21
|
+
puts "50 seconds passed"
|
22
|
+
timer.close
|
23
|
+
end
|
24
|
+
|
25
|
+
loop.run
|
26
|
+
|
27
|
+
Find more examples in examples directory
|
28
|
+
|
29
|
+
== Installation
|
30
|
+
|
31
|
+
gem install uvrb
|
32
|
+
|
33
|
+
or
|
34
|
+
|
35
|
+
git clone ...
|
36
|
+
cd ...
|
37
|
+
bundle install
|
38
|
+
|
39
|
+
Make sure you have libuv compiled and a shared library (`.dylib`|`.so`|`.dll`) file available in your lib path.
|
40
|
+
|
41
|
+
To compile libuv from a local submodule version:
|
42
|
+
|
43
|
+
git submodule update --init
|
44
|
+
rake libuv
|
45
|
+
|
46
|
+
Or to compile libuv on mac, you can install provided Homebrew formula by running:
|
47
|
+
|
48
|
+
brew install Formula/libuv.rb --HEAD
|
49
|
+
|
50
|
+
== What's supported
|
51
|
+
|
52
|
+
* TCP
|
53
|
+
* UDP
|
54
|
+
* TTY
|
55
|
+
* Pipe
|
56
|
+
* Timer
|
57
|
+
* Prepare
|
58
|
+
* Check
|
59
|
+
* Idle
|
60
|
+
* Async
|
61
|
+
* Filesystem
|
62
|
+
* File
|
63
|
+
* FSEvent
|
64
|
+
* Errors
|
65
|
+
|
66
|
+
== TODO
|
67
|
+
|
68
|
+
* Port rest of libuv - ares, getaddrinfo, process, work queue, mutexes and locks
|
69
|
+
* Tests tests tests
|
70
|
+
* Docs docs docs
|
data/Rakefile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
require 'cucumber'
|
6
|
+
require 'cucumber/rake/task'
|
7
|
+
require 'rdoc/task'
|
8
|
+
require 'ffi'
|
9
|
+
require 'rake/clean'
|
10
|
+
require 'uv/tasks'
|
11
|
+
|
12
|
+
RSpec::Core::RakeTask.new
|
13
|
+
|
14
|
+
Cucumber::Rake::Task.new(:features)
|
15
|
+
|
16
|
+
RDoc::Task.new(:rdoc => "rdoc", :clobber_rdoc => "rdoc:clean", :rerdoc => "rdoc:force") do |rd|
|
17
|
+
rd.main = "README.rdoc"
|
18
|
+
rd.rdoc_files.include("README.rdoc", "lib/**/*.rb")
|
19
|
+
rd.options << "--title=UV.rb - libuv bindings for Ruby"
|
20
|
+
rd.options << "--markup=tomdoc"
|
21
|
+
end
|
22
|
+
|
23
|
+
task :test => [:spec, :features]
|
24
|
+
task :default => :test
|
25
|
+
|
26
|
+
desc "Compile libuv from submodule"
|
27
|
+
task :libuv => ["ext/libuv.#{FFI::Platform::LIBSUFFIX}"]
|
28
|
+
|
29
|
+
CLOBBER.include("ext/libuv.#{FFI::Platform::LIBSUFFIX}")
|
data/examples/example
ADDED
Binary file
|
data/examples/example.c
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# include <uv.h>
|
2
|
+
# include <stdio.h>
|
3
|
+
|
4
|
+
static int count = 0;
|
5
|
+
|
6
|
+
void close_cb(uv_handle_t* handle)
|
7
|
+
{
|
8
|
+
// free(handle);
|
9
|
+
}
|
10
|
+
|
11
|
+
void timer_cb(uv_timer_t* timer, int status)
|
12
|
+
{
|
13
|
+
puts("1");
|
14
|
+
if (count >= 10) {
|
15
|
+
// uv_unref(uv_default_loop());
|
16
|
+
// uv_timer_stop(timer);
|
17
|
+
uv_close((uv_handle_t*)timer, close_cb);
|
18
|
+
}
|
19
|
+
count++;
|
20
|
+
}
|
21
|
+
|
22
|
+
int main(int argc, char* argv[])
|
23
|
+
{
|
24
|
+
uv_timer_t timer;
|
25
|
+
printf("sizeof timer is %ld\n", sizeof(uv_timer_t));
|
26
|
+
printf("sizeof tcp is %ld\n", sizeof(uv_tcp_t));
|
27
|
+
printf("sizeof handle is %ld\n", sizeof(uv_handle_t));
|
28
|
+
printf("sizeof tty is %ld\n", sizeof(uv_tty_t));
|
29
|
+
printf("sizeof udp is %ld\n", sizeof(uv_udp_t));
|
30
|
+
// printf("sizeof timer is %ld\n", sizeof(uv_timer_t));
|
31
|
+
// printf("sizeof timer is %ld\n", sizeof(uv_timer_t));
|
32
|
+
|
33
|
+
uv_timer_init(uv_default_loop(), &timer);
|
34
|
+
uv_timer_start(&timer, timer_cb, 1, 1);
|
35
|
+
uv_run(uv_default_loop());
|
36
|
+
uv_loop_delete(uv_default_loop());
|
37
|
+
}
|
data/examples/example.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
require 'uvrb'
|
4
|
+
|
5
|
+
start = Time.now
|
6
|
+
|
7
|
+
loop = UV.default_loop
|
8
|
+
|
9
|
+
timer = UV.create_handle(:uv_timer)
|
10
|
+
# timer = FFI::MemoryPointer.new(UV::Timer, UV::Timer.size, 1)
|
11
|
+
count = 0
|
12
|
+
UV.timer_init(loop, timer)
|
13
|
+
$stdout << "\r\n"
|
14
|
+
|
15
|
+
close_cb = proc {|ptr| UV.free(ptr); $stdout << "\n"; }
|
16
|
+
|
17
|
+
timer_cb = Proc.new do |ptr, status|
|
18
|
+
$stdout << "#{count}\r"
|
19
|
+
if count >= 10000
|
20
|
+
UV.close(ptr, close_cb)
|
21
|
+
end
|
22
|
+
count += 1
|
23
|
+
end
|
24
|
+
|
25
|
+
UV.timer_start(timer, timer_cb, 1, 1)
|
26
|
+
UV.run(loop)
|
27
|
+
UV.loop_delete(loop)
|
28
|
+
|
29
|
+
puts Time.now - start
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
require 'uvrb'
|
4
|
+
|
5
|
+
start = Time.now
|
6
|
+
|
7
|
+
loop = UV::Loop.default
|
8
|
+
|
9
|
+
count = 0
|
10
|
+
timer = loop.timer
|
11
|
+
$stdout << "\r\n"
|
12
|
+
|
13
|
+
timer.start(1, 1) do |status|
|
14
|
+
$stdout << "\r#{count}"
|
15
|
+
if count >= 10000
|
16
|
+
timer.close do
|
17
|
+
$stdout << "\n"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
count += 1
|
21
|
+
end
|
22
|
+
|
23
|
+
loop.run
|
24
|
+
$stdout << "\n"
|
25
|
+
|
26
|
+
puts Time.now - start
|
data/examples/python.py
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
print('hello world')
|
data/examples/ruby.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
puts 'hello world'
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
require 'uvrb'
|
4
|
+
|
5
|
+
loop = UV::Loop.default
|
6
|
+
|
7
|
+
client = loop.tcp
|
8
|
+
|
9
|
+
client.connect("127.0.0.1", 10000) do |err|
|
10
|
+
if err
|
11
|
+
p err
|
12
|
+
exit 1
|
13
|
+
end
|
14
|
+
client.write("GET /\r\nHost: localhost:10000\r\nAccept: *\r\n\r\n\n") do |err|
|
15
|
+
if err
|
16
|
+
p err
|
17
|
+
exit 1
|
18
|
+
end
|
19
|
+
client.start_read do |data, err|
|
20
|
+
if err
|
21
|
+
p err
|
22
|
+
exit 1
|
23
|
+
end
|
24
|
+
puts data
|
25
|
+
client.close
|
26
|
+
end
|
27
|
+
end
|
28
|
+
# client.close
|
29
|
+
end
|
30
|
+
|
31
|
+
loop.run
|
Binary file
|
@@ -0,0 +1,68 @@
|
|
1
|
+
#include <uv.h>
|
2
|
+
#include <stdio.h>
|
3
|
+
#include <stdlib.h>
|
4
|
+
|
5
|
+
#define RESPONSE \
|
6
|
+
"HTTP/1.1 200 OK\r\n" \
|
7
|
+
"Content-Type: text/plain\r\n" \
|
8
|
+
"Content-Length: 12\r\n" \
|
9
|
+
"\r\n" \
|
10
|
+
"hello world\n"
|
11
|
+
|
12
|
+
static uv_buf_t resbuf;
|
13
|
+
|
14
|
+
void on_close(uv_handle_t* handle)
|
15
|
+
{
|
16
|
+
free(handle);
|
17
|
+
}
|
18
|
+
|
19
|
+
void after_shutdown(uv_shutdown_t* req, int status) {
|
20
|
+
free(req);
|
21
|
+
uv_close((uv_handle_t*)req->handle, on_close);
|
22
|
+
}
|
23
|
+
|
24
|
+
void after_write(uv_write_t* req, int status) {
|
25
|
+
uv_shutdown_t* shutdown_req = malloc(sizeof(uv_shutdown_t));
|
26
|
+
|
27
|
+
free(req);
|
28
|
+
// uv_shutdown(shutdown_req, req->handle, after_shutdown);
|
29
|
+
uv_close((uv_handle_t*)req->handle, on_close);
|
30
|
+
}
|
31
|
+
|
32
|
+
void on_read(uv_stream_t* tcp, ssize_t nread, uv_buf_t buf)
|
33
|
+
{
|
34
|
+
uv_write_t* write_req = malloc(sizeof(uv_write_t));
|
35
|
+
|
36
|
+
uv_write(write_req, tcp, &resbuf, 1, after_write);
|
37
|
+
}
|
38
|
+
|
39
|
+
uv_buf_t on_alloc(uv_handle_t* client, size_t suggested_size)
|
40
|
+
{
|
41
|
+
return uv_buf_init(malloc(suggested_size), suggested_size);
|
42
|
+
}
|
43
|
+
|
44
|
+
void on_connect(uv_stream_t* server, int status)
|
45
|
+
{
|
46
|
+
uv_tcp_t* client = malloc(sizeof(uv_tcp_t));
|
47
|
+
|
48
|
+
uv_tcp_init(uv_default_loop(), client);
|
49
|
+
uv_accept(server, (uv_stream_t*) client);
|
50
|
+
uv_read_start((uv_stream_t*) client, on_alloc, on_read);
|
51
|
+
}
|
52
|
+
|
53
|
+
int main(int argc, char* argv[])
|
54
|
+
{
|
55
|
+
uv_tcp_t tcp;
|
56
|
+
|
57
|
+
resbuf.base = RESPONSE;
|
58
|
+
resbuf.len = sizeof(RESPONSE);
|
59
|
+
|
60
|
+
uv_tcp_init(uv_default_loop(), &tcp);
|
61
|
+
|
62
|
+
struct sockaddr_in address = uv_ip4_addr("0.0.0.0", 10000);
|
63
|
+
uv_tcp_bind(&tcp, address);
|
64
|
+
uv_listen((uv_stream_t*)&tcp, 128, on_connect);
|
65
|
+
|
66
|
+
uv_run(uv_default_loop());
|
67
|
+
uv_loop_delete(uv_default_loop());
|
68
|
+
}
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
require 'uvrb'
|
4
|
+
|
5
|
+
def on_read(client, nread, buf)
|
6
|
+
if nread == -1
|
7
|
+
ptr = UV.last_error(@loop)
|
8
|
+
p [UV.err_name(ptr), UV.strerror(ptr)]
|
9
|
+
else
|
10
|
+
puts buf[:base].read_string(nread)
|
11
|
+
end
|
12
|
+
UV.free(buf[:base])
|
13
|
+
UV.close(client, proc {|client| })
|
14
|
+
end
|
15
|
+
|
16
|
+
def on_alloc(handle, suggested_size)
|
17
|
+
UV.buf_init(UV.malloc(suggested_size), suggested_size)
|
18
|
+
end
|
19
|
+
|
20
|
+
def on_connect(server, status)
|
21
|
+
client = FFI::AutoPointer.new(UV.create_handle(:uv_tcp), UV.method(:free))
|
22
|
+
UV.tcp_init(@loop, client)
|
23
|
+
|
24
|
+
UV.accept(server, client)
|
25
|
+
UV.read_start(client, method(:on_alloc), method(:on_read))
|
26
|
+
end
|
27
|
+
|
28
|
+
def main
|
29
|
+
@loop = UV.default_loop
|
30
|
+
|
31
|
+
server = FFI::AutoPointer.new(UV.create_handle(:uv_tcp), UV.method(:free))
|
32
|
+
UV.tcp_init(@loop, server)
|
33
|
+
|
34
|
+
UV.tcp_bind(server, UV.ip4_addr('0.0.0.0', 10000))
|
35
|
+
UV.listen(server, 128, method(:on_connect))
|
36
|
+
|
37
|
+
UV.run(@loop)
|
38
|
+
UV.loop_delete(@loop)
|
39
|
+
end
|
40
|
+
|
41
|
+
main
|