ffi-rxs 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/.travis.yml +10 -0
- data/.yardopts +9 -0
- data/CHANGELOG +11 -0
- data/LICENSE +20 -0
- data/README.textile +86 -0
- data/examples/LICENSE +18 -0
- data/examples/README +2 -0
- data/examples/durable_pub.rb +34 -0
- data/examples/durable_sub.rb +29 -0
- data/examples/latency_measurement.rb +140 -0
- data/examples/reply.rb +25 -0
- data/examples/req_rep_poll.rb +71 -0
- data/examples/request.rb +24 -0
- data/examples/task_sink.rb +31 -0
- data/examples/task_vent.rb +34 -0
- data/examples/task_worker.rb +36 -0
- data/examples/throughput_measurement.rb +169 -0
- data/examples/weather_upd_client.rb +47 -0
- data/examples/weather_upd_server.rb +35 -0
- data/examples/xreq_xrep_poll.rb +101 -0
- data/ffi-rxs.gemspec +3 -5
- data/lib/ffi-rxs/constants.rb +15 -11
- data/lib/ffi-rxs/context.rb +54 -60
- data/lib/ffi-rxs/exceptions.rb +7 -5
- data/lib/ffi-rxs/libc.rb +1 -0
- data/lib/ffi-rxs/libxs.rb +2 -0
- data/lib/ffi-rxs/message.rb +79 -50
- data/lib/ffi-rxs/poll.rb +54 -12
- data/lib/ffi-rxs/poll_items.rb +2 -1
- data/lib/ffi-rxs/socket.rb +243 -184
- data/lib/ffi-rxs/util.rb +25 -16
- data/lib/ffi-rxs/version.rb +3 -1
- data/lib/ffi-rxs.rb +8 -14
- data/spec/socket_spec.rb +63 -0
- metadata +31 -19
- data/README.rdoc +0 -86
data/lib/ffi-rxs/util.rb
CHANGED
@@ -1,39 +1,42 @@
|
|
1
|
+
# encoding: utf-8
|
1
2
|
|
2
3
|
module XS
|
3
4
|
|
4
5
|
# These methods don't belong to any specific class. They get included
|
5
6
|
# in the #Context, #Socket and #Poller classes.
|
6
|
-
#
|
7
7
|
module Util
|
8
8
|
|
9
|
-
#
|
9
|
+
# @return true when +rc+ is greater than or equal to 0
|
10
|
+
# @return false otherwise
|
10
11
|
#
|
11
12
|
# We use the >= test because xs_poll() returns the number of sockets
|
12
13
|
# that had a read or write event triggered. So, a >= 0 result means
|
13
14
|
# it succeeded.
|
14
|
-
#
|
15
15
|
def self.resultcode_ok? rc
|
16
16
|
rc >= 0
|
17
17
|
end
|
18
18
|
|
19
|
-
# Returns
|
19
|
+
# Returns error number
|
20
20
|
#
|
21
|
+
# @return errno as set by the libxs library.
|
21
22
|
def self.errno
|
22
23
|
LibXS.xs_errno
|
23
24
|
end
|
24
25
|
|
25
|
-
# Returns
|
26
|
-
#
|
27
|
-
#
|
26
|
+
# Returns error string
|
27
|
+
#
|
28
|
+
# @return string corresponding to the currently set #errno. These
|
29
|
+
# error strings are defined by libxs.
|
28
30
|
def self.error_string
|
29
31
|
LibXS.xs_strerror(errno).read_string
|
30
32
|
end
|
31
33
|
|
32
|
-
# Returns
|
33
|
-
# version of libxs.
|
34
|
+
# Returns libxs version number
|
34
35
|
#
|
35
|
-
#
|
36
|
+
# @return array of the form [major, minor, patch] to represent the
|
37
|
+
# version of libxs
|
36
38
|
#
|
39
|
+
# Class method! Invoke as: XS::Util.version
|
37
40
|
def self.version
|
38
41
|
major = FFI::MemoryPointer.new :int
|
39
42
|
minor = FFI::MemoryPointer.new :int
|
@@ -43,8 +46,10 @@ module XS
|
|
43
46
|
end
|
44
47
|
|
45
48
|
# Attempts to bind to a random tcp port on +host+ up to +max_tries+
|
46
|
-
# times.
|
49
|
+
# times.
|
47
50
|
#
|
51
|
+
# @return port number upon success
|
52
|
+
# @return nil upon failure
|
48
53
|
def self.bind_to_random_tcp_port host = '127.0.0.1', max_tries = 500
|
49
54
|
tries = 0
|
50
55
|
rc = -1
|
@@ -61,18 +66,18 @@ module XS
|
|
61
66
|
|
62
67
|
private
|
63
68
|
|
64
|
-
#
|
69
|
+
# Generate a random port between 10_000 and 65534
|
70
|
+
#
|
71
|
+
# @return port number
|
65
72
|
def self.random_port
|
66
73
|
rand(55534) + 10_000
|
67
74
|
end
|
68
75
|
|
69
|
-
# :doc:
|
70
76
|
# Called by most library methods to verify there were no errors during
|
71
77
|
# operation. If any are found, raise the appropriate #XSError.
|
72
78
|
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
79
|
+
# @return true when no error is found which is behavior used internally
|
80
|
+
# by #send and #recv.
|
76
81
|
def error_check source, result_code
|
77
82
|
if -1 == result_code
|
78
83
|
raise_error source, result_code
|
@@ -82,6 +87,10 @@ module XS
|
|
82
87
|
true
|
83
88
|
end
|
84
89
|
|
90
|
+
# Raises error
|
91
|
+
#
|
92
|
+
# @param source
|
93
|
+
# @param result_code
|
85
94
|
def raise_error source, result_code
|
86
95
|
if 'xs_init' == source || 'xs_socket' == source
|
87
96
|
raise ContextError.new source, result_code, XS::Util.errno, XS::Util.error_string
|
data/lib/ffi-rxs/version.rb
CHANGED
data/lib/ffi-rxs.rb
CHANGED
@@ -1,21 +1,18 @@
|
|
1
|
+
# encoding: utf-8
|
1
2
|
|
2
3
|
module XS
|
3
4
|
|
4
|
-
# :stopdoc:
|
5
5
|
LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
|
6
6
|
PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
|
7
|
-
# :startdoc:
|
8
7
|
|
9
|
-
# Returns the version string for the library.
|
10
|
-
#
|
8
|
+
# Returns the version string for the library.
|
11
9
|
def self.version
|
12
10
|
@version ||= File.read(path('version.txt')).strip
|
13
11
|
end
|
14
12
|
|
15
13
|
# Returns the library path for the module. If any arguments are given,
|
16
|
-
# they will be joined to the end of the
|
17
|
-
#
|
18
|
-
#
|
14
|
+
# they will be joined to the end of the library path using
|
15
|
+
# _File.join_.
|
19
16
|
def self.libpath( *args, &block )
|
20
17
|
rv = args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten)
|
21
18
|
if block
|
@@ -31,8 +28,7 @@ module XS
|
|
31
28
|
|
32
29
|
# Returns the lpath for the module. If any arguments are given,
|
33
30
|
# they will be joined to the end of the path using
|
34
|
-
#
|
35
|
-
#
|
31
|
+
# _File.join_.
|
36
32
|
def self.path( *args, &block )
|
37
33
|
rv = args.empty? ? PATH : ::File.join(PATH, args.flatten)
|
38
34
|
if block
|
@@ -50,7 +46,6 @@ module XS
|
|
50
46
|
# directory below this file that has the same name as the filename passed
|
51
47
|
# in. Optionally, a specific _directory_ name can be passed in such that
|
52
48
|
# the _filename_ does not have to be equivalent to the directory.
|
53
|
-
#
|
54
49
|
def self.require_all_libs_relative_to( fname, dir = nil )
|
55
50
|
dir ||= ::File.basename(fname, '.*')
|
56
51
|
search_me = ::File.expand_path(
|
@@ -61,14 +56,13 @@ module XS
|
|
61
56
|
|
62
57
|
end # module XS
|
63
58
|
|
64
|
-
#
|
65
|
-
#
|
66
|
-
|
59
|
+
# Conditional code execution depending upon which ruby engine we are
|
60
|
+
# using
|
67
61
|
RBX = defined?(RUBY_ENGINE) && RUBY_ENGINE =~ /rbx/ ? true : false
|
68
62
|
|
69
63
|
require 'ffi' unless RBX
|
70
64
|
|
71
|
-
#
|
65
|
+
# The order that files are required in is important
|
72
66
|
%w(libc libxs constants util exceptions context message socket poll_items poll).each do |file|
|
73
67
|
require XS.libpath(['ffi-rxs', file])
|
74
68
|
end
|
data/spec/socket_spec.rb
CHANGED
@@ -340,6 +340,69 @@ module XS
|
|
340
340
|
array[0].should == value
|
341
341
|
end
|
342
342
|
end # context using option XS::BACKLOG
|
343
|
+
|
344
|
+
|
345
|
+
context "using option XS::KEEPALIVE" do
|
346
|
+
it "should enable use of protocol keepalives if set to 1" do
|
347
|
+
value = 1
|
348
|
+
socket.setsockopt XS::KEEPALIVE, value
|
349
|
+
array = []
|
350
|
+
rc = socket.getsockopt(XS::KEEPALIVE, array)
|
351
|
+
rc.should == 0
|
352
|
+
array[0].should == value
|
353
|
+
end
|
354
|
+
|
355
|
+
it "should default to a value of 0" do
|
356
|
+
value = 0
|
357
|
+
array = []
|
358
|
+
rc = socket.getsockopt(XS::KEEPALIVE, array)
|
359
|
+
rc.should == 0
|
360
|
+
array[0].should == value
|
361
|
+
end
|
362
|
+
|
363
|
+
it "returns -1 given a negative value" do
|
364
|
+
value = -1
|
365
|
+
rc = socket.setsockopt XS::KEEPALIVE, value
|
366
|
+
rc.should == -1
|
367
|
+
end
|
368
|
+
|
369
|
+
it "returns -1 given a value > 1" do
|
370
|
+
value = 2
|
371
|
+
rc = socket.setsockopt XS::KEEPALIVE, value
|
372
|
+
rc.should == -1
|
373
|
+
end
|
374
|
+
end # context using option XS::KEEPALIVE
|
375
|
+
|
376
|
+
context "using option XS::IPV4ONLY" do
|
377
|
+
it "should enable use of IPV6 sockets when set to 0" do
|
378
|
+
value = 0
|
379
|
+
socket.setsockopt XS::IPV4ONLY, value
|
380
|
+
array = []
|
381
|
+
rc = socket.getsockopt(XS::IPV4ONLY, array)
|
382
|
+
rc.should == 0
|
383
|
+
array[0].should == value
|
384
|
+
end
|
385
|
+
|
386
|
+
it "should default to a value of 1" do
|
387
|
+
value = 1
|
388
|
+
array = []
|
389
|
+
rc = socket.getsockopt(XS::IPV4ONLY, array)
|
390
|
+
rc.should == 0
|
391
|
+
array[0].should == value
|
392
|
+
end
|
393
|
+
|
394
|
+
it "returns -1 given a negative value" do
|
395
|
+
value = -1
|
396
|
+
rc = socket.setsockopt XS::IPV4ONLY, value
|
397
|
+
rc.should == -1
|
398
|
+
end
|
399
|
+
|
400
|
+
it "returns -1 given a value > 1" do
|
401
|
+
value = 2
|
402
|
+
rc = socket.setsockopt XS::IPV4ONLY, value
|
403
|
+
rc.should == -1
|
404
|
+
end
|
405
|
+
end # context using option XS::IPV4ONLY
|
343
406
|
end # context #setsockopt
|
344
407
|
|
345
408
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ffi-rxs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-03-
|
12
|
+
date: 2012-03-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ffi
|
16
|
-
requirement: &
|
16
|
+
requirement: &73901550 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *73901550
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec
|
27
|
-
requirement: &
|
27
|
+
requirement: &73901000 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '2.6'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *73901000
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rake
|
38
|
-
requirement: &
|
38
|
+
requirement: &73900740 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,15 +43,8 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
47
|
-
description:
|
48
|
-
FFI (foreign
|
49
|
-
|
50
|
-
function interface). It''s a pure ruby wrapper so this gem can be loaded
|
51
|
-
|
52
|
-
and run by any ruby runtime that supports FFI. That''s all of them:
|
53
|
-
|
54
|
-
MRI 1.9.x, Rubinius and JRuby.'
|
46
|
+
version_requirements: *73900740
|
47
|
+
description: Ruby FFI bindings for Crossroads I/O networking library.
|
55
48
|
email:
|
56
49
|
- celldee@gmail.com
|
57
50
|
executables: []
|
@@ -59,10 +52,29 @@ extensions: []
|
|
59
52
|
extra_rdoc_files: []
|
60
53
|
files:
|
61
54
|
- .gitignore
|
55
|
+
- .travis.yml
|
56
|
+
- .yardopts
|
62
57
|
- AUTHORS.txt
|
58
|
+
- CHANGELOG
|
63
59
|
- Gemfile
|
64
|
-
-
|
60
|
+
- LICENSE
|
61
|
+
- README.textile
|
65
62
|
- Rakefile
|
63
|
+
- examples/LICENSE
|
64
|
+
- examples/README
|
65
|
+
- examples/durable_pub.rb
|
66
|
+
- examples/durable_sub.rb
|
67
|
+
- examples/latency_measurement.rb
|
68
|
+
- examples/reply.rb
|
69
|
+
- examples/req_rep_poll.rb
|
70
|
+
- examples/request.rb
|
71
|
+
- examples/task_sink.rb
|
72
|
+
- examples/task_vent.rb
|
73
|
+
- examples/task_worker.rb
|
74
|
+
- examples/throughput_measurement.rb
|
75
|
+
- examples/weather_upd_client.rb
|
76
|
+
- examples/weather_upd_server.rb
|
77
|
+
- examples/xreq_xrep_poll.rb
|
66
78
|
- ext/README
|
67
79
|
- ffi-rxs.gemspec
|
68
80
|
- lib/ffi-rxs.rb
|
@@ -121,6 +133,6 @@ rubyforge_project:
|
|
121
133
|
rubygems_version: 1.8.6
|
122
134
|
signing_key:
|
123
135
|
specification_version: 3
|
124
|
-
summary:
|
125
|
-
function interface).
|
136
|
+
summary: Ruby FFI bindings for Crossroads I/O networking library.
|
126
137
|
test_files: []
|
138
|
+
has_rdoc:
|
data/README.rdoc
DELETED
@@ -1,86 +0,0 @@
|
|
1
|
-
ffi-rxs
|
2
|
-
by Chris Duncan
|
3
|
-
|
4
|
-
== DESCRIPTION:
|
5
|
-
|
6
|
-
This gem wraps the Crossroads I/O networking library using the Ruby FFI (foreign
|
7
|
-
function interface). It's a pure Ruby wrapper so this gem can be loaded
|
8
|
-
and run by any Ruby runtime that supports FFI. That's all of them:
|
9
|
-
MRI 1.9.x, Rubinius and JRuby.
|
10
|
-
|
11
|
-
Crossroads I/O is a fork of ZeroMQ. This gem is a re-working of the ffi-rzmq gem
|
12
|
-
created by Chuck Remes to provide bindings for the Crossroads I/O libxs C library
|
13
|
-
instead of the ZeroMQ libzmq library. The gem auto-configures itself to expose
|
14
|
-
the API conforming to the loaded C library.
|
15
|
-
|
16
|
-
== FEATURES/PROBLEMS:
|
17
|
-
|
18
|
-
This gem needs to be tested in the wild. Please kick its tyres and give it a
|
19
|
-
good thrashing. It is inevitable that bugs will be discovered, so please open
|
20
|
-
issues for them here or fork this project, fix them, and send me a pull
|
21
|
-
request.
|
22
|
-
|
23
|
-
The 'ffi' gem has dropped support for MRI 1.8.x. Since this project relies
|
24
|
-
on that gem to load and run this code, then this project does not support
|
25
|
-
MRI 1.8.x. I recommend JRuby for the best performance and stability.
|
26
|
-
|
27
|
-
== REQUIREMENTS:
|
28
|
-
|
29
|
-
* Crossroads I/O version 1.0.0 or later.
|
30
|
-
|
31
|
-
The Crossroads I/O library must be installed on your system in a well-known location
|
32
|
-
like /usr/local/lib. This is the default for new Crossroads I/O installs.
|
33
|
-
|
34
|
-
Future releases may include the library as a C extension built at
|
35
|
-
time of installation.
|
36
|
-
|
37
|
-
* ffi (>= 1.0.0)
|
38
|
-
|
39
|
-
Do *not* run this gem under MRI with an old 'ffi' gem. It will crash randomly and
|
40
|
-
you will be sad.
|
41
|
-
|
42
|
-
== INSTALL:
|
43
|
-
|
44
|
-
A full gem has been released to Rubygems.org as of release 1.0.0.
|
45
|
-
Make sure the Crossroads I/O library is already installed on your system.
|
46
|
-
|
47
|
-
% gem install ffi-rxs # should grab the latest release
|
48
|
-
|
49
|
-
|
50
|
-
To build from git master:
|
51
|
-
|
52
|
-
% git clone git://github.com/celldee/ffi-rxs
|
53
|
-
% cd ffi-rxs
|
54
|
-
% gem build ffi-rxs.gemspec
|
55
|
-
% gem install ffi-rxs-*.gem
|
56
|
-
|
57
|
-
|
58
|
-
NOTE for Windows users!
|
59
|
-
In order for this gem to find the libxs.dll, it *must* be on the Windows PATH. Google
|
60
|
-
for "modify windows path" for instructions on how to do that if you are unfamiliar with
|
61
|
-
that activity.
|
62
|
-
|
63
|
-
== LICENSE:
|
64
|
-
|
65
|
-
(The MIT License)
|
66
|
-
|
67
|
-
Copyright (c) 2011 - 2012 Chuck Remes, Chris Duncan and contributors
|
68
|
-
|
69
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
70
|
-
a copy of this software and associated documentation files (the
|
71
|
-
'Software'), to deal in the Software without restriction, including
|
72
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
73
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
74
|
-
permit persons to whom the Software is furnished to do so, subject to
|
75
|
-
the following conditions:
|
76
|
-
|
77
|
-
The above copyright notice and this permission notice shall be
|
78
|
-
included in all copies or substantial portions of the Software.
|
79
|
-
|
80
|
-
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
81
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
82
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
83
|
-
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
84
|
-
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
85
|
-
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
86
|
-
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|