uvrb 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|