spread-client 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/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Tim Lossen
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # spread_client
2
+
3
+ portable ruby bindings for the [spread toolkit](http://www.spread.org), version 3.17.x
4
+
5
+ ## usage
6
+
7
+ sudo gem install spread-client -s http://gemcutter.org
8
+
9
+ then
10
+
11
+ require 'rubygems'
12
+ require 'spread_client'
13
+
14
+ c = SpreadClient::connect('bob')
15
+ c.join('chat')
16
+ c.multicast('chat', 'hello folks!')
17
+ c.leave('chat')
18
+ c.disconnect
19
+
20
+ ## setup instructions
21
+
22
+ 1. install the spread toolkit:
23
+
24
+ $ sudo port install spread
25
+
26
+ or
27
+
28
+ $ sudo apt-get install spread
29
+
30
+ or see <http://www.spread.org> for instructions on how to install from source.
31
+
32
+ 2. create a simple `spread.conf`:
33
+
34
+ # one spread daemon running on port 4803 on localhost
35
+ Spread_Segment 127.0.0.255:4803 {
36
+ localhost 127.0.0.1
37
+ }
38
+
39
+ 3. start the spread daemon:
40
+
41
+ $ spread -n localhost -c spread.conf
42
+
43
+ ## Copyright
44
+
45
+ Copyright (c) 2009 Tim Lossen. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,39 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "spread-client"
8
+ gem.summary = "ruby bindings for libspread (built with ffi)"
9
+ gem.description = "portable ruby bindings for libspread (built with ffi)."
10
+ gem.email = "tim@lossen.de"
11
+ gem.homepage = "http://github.com/tlossen/spread_client"
12
+ gem.authors = ["Tim Lossen"]
13
+ gem.files.include('lib/**/*.rb')
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
19
+ end
20
+
21
+ require 'rake/testtask'
22
+ Rake::TestTask.new(:test) do |test|
23
+ test.libs << 'lib' << 'test'
24
+ test.pattern = 'test/**/test_*.rb'
25
+ test.verbose = true
26
+ end
27
+
28
+ require 'rake/rdoctask'
29
+ Rake::RDocTask.new do |rdoc|
30
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
31
+
32
+ rdoc.rdoc_dir = 'rdoc'
33
+ rdoc.title = "spread_client #{version}"
34
+ rdoc.rdoc_files.include('README*')
35
+ rdoc.rdoc_files.include('lib/**/*.rb')
36
+ end
37
+
38
+ task :test => :check_dependencies
39
+ task :default => :test
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/example/demo.rb ADDED
@@ -0,0 +1,10 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'spread_client')
2
+
3
+ c = SpreadClient::connect('bob')
4
+ c.join('chat')
5
+ puts c.receive().inspect
6
+ c.multicast('chat', 'hello folks!')
7
+ puts c.receive().inspect
8
+ c.leave('chat')
9
+ puts c.receive().inspect
10
+ c.disconnect
@@ -0,0 +1,4 @@
1
+ # one spread daemon running on localhost:4803
2
+ Spread_Segment 127.0.0.255:4803 {
3
+ localhost 127.0.0.1
4
+ }
data/example/start.sh ADDED
@@ -0,0 +1 @@
1
+ spread -n localhost -c spread.conf
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'ffi'
3
+
4
+ require File.join(File.dirname(__FILE__), 'spread_client', 'ffi')
5
+ require File.join(File.dirname(__FILE__), 'spread_client', 'connection')
6
+ require File.join(File.dirname(__FILE__), 'spread_client', 'errors')
7
+ require File.join(File.dirname(__FILE__), 'spread_client', 'messages')
8
+
9
+
10
+
@@ -0,0 +1,163 @@
1
+ module SpreadClient
2
+
3
+ class Connection
4
+
5
+ UNRELIABLE_MESS = 0x00000001
6
+ RELIABLE_MESS = 0x00000002
7
+ FIFO_MESS = 0x00000004
8
+ CAUSAL_MESS = 0x00000008
9
+ AGREED_MESS = 0x00000010
10
+ SAFE_MESS = 0x00000020
11
+ REGULAR_MESS = 0x0000003f
12
+
13
+ SELF_DISCARD = 0x00000040
14
+ DROP_RECV = 0x01000000
15
+
16
+ REG_MEMB_MESS = 0x00001000
17
+ TRANSITION_MESS = 0x00002000
18
+ CAUSED_BY_JOIN = 0x00000100
19
+ CAUSED_BY_LEAVE = 0x00000200
20
+ CAUSED_BY_DISCONNECT = 0x00000400
21
+ CAUSED_BY_NETWORK = 0x00000800
22
+ MEMBERSHIP_MESS = 0x00003f00
23
+
24
+ ENDIAN_RESERVED = 0x80000080
25
+ RESERVED = 0x003fc000
26
+ REJECT_MESS = 0x00400000
27
+
28
+ SERVICE_TYPE = {
29
+ :unreliable => UNRELIABLE_MESS,
30
+ :reliable => RELIABLE_MESS,
31
+ :fifo => FIFO_MESS,
32
+ :causal => CAUSAL_MESS,
33
+ :agreed => AGREED_MESS,
34
+ :safe => SAFE_MESS
35
+ }
36
+
37
+ DEFAULT_SERVER = 'localhost'
38
+ DEFAULT_PORT = 4803
39
+ DEFAULT_NOTIFY = true
40
+ DEFAULT_PRIORITY = 0
41
+ DEFAULT_SERVICE_TYPE = :safe
42
+ DEFAULT_SELF_DISCARD = false
43
+ DEFAULT_MESSAGE_TYPE = 0
44
+
45
+ MAX_GROUPS = 16
46
+ MAX_GROUP_LENGTH = 32
47
+ MAX_MESSAGE_LENGTH = 512
48
+
49
+ def initialize(name, options = {}) #:nodoc:
50
+ @mbox, @name = *connect(name, options)
51
+ end
52
+
53
+ # the private group name of this connection.
54
+ def name
55
+ @name
56
+ end
57
+
58
+ # disconnect from the spread server.
59
+ def disconnect
60
+ result = SpreadClient.SP_disconnect(@mbox)
61
+ raise SpreadClient.error_for(result) unless result == 0
62
+ end
63
+
64
+ # join the given group.
65
+ def join(group)
66
+ result = SpreadClient.SP_join(@mbox, group)
67
+ raise SpreadClient.error_for(result) unless result == 0
68
+ end
69
+
70
+ # leave the given group.
71
+ def leave(group)
72
+ result = SpreadClient.SP_leave(@mbox, group)
73
+ raise SpreadClient.error_for(result) unless result == 0
74
+ end
75
+
76
+ # send a message to a group.
77
+ #
78
+ # options:
79
+ # * :service_type -- can be one of
80
+ # * :unreliable
81
+ # * :reliable
82
+ # * :fifo
83
+ # * :causal
84
+ # * :agreed
85
+ # * :safe (default)
86
+ # * :self_discard -- set this to true if you do not want to receive your own message (default is false)
87
+ def multicast(group, message, options = {})
88
+ options = { :service_type => DEFAULT_SERVICE_TYPE, :self_discard => DEFAULT_SELF_DISCARD }.merge(options)
89
+ service_type = SERVICE_TYPE[options[:service_type]] | (options[:self_discard] ? SELF_DISCARD : 0)
90
+ result = SpreadClient.SP_multicast(@mbox, service_type, group, DEFAULT_MESSAGE_TYPE,
91
+ message.length, message)
92
+ raise SpreadClient.error_for(result) if result < 0
93
+ end
94
+
95
+ # receive the next message or notification.
96
+ #
97
+ # this method blocks until a message is available.
98
+ def receive
99
+ service_type = FFI::MemoryPointer.new(:int)
100
+ sender = FFI::MemoryPointer.new(:char, MAX_GROUP_LENGTH)
101
+ num_groups = FFI::MemoryPointer.new(:int)
102
+ groups = FFI::MemoryPointer.new(:char, MAX_GROUPS * MAX_GROUP_LENGTH)
103
+ message_type = FFI::MemoryPointer.new(:int)
104
+ endian_mismatch = FFI::MemoryPointer.new(:int)
105
+ message = FFI::MemoryPointer.new(:char, MAX_MESSAGE_LENGTH)
106
+ result = SpreadClient.SP_receive(@mbox, service_type, sender, MAX_GROUPS, num_groups, groups,
107
+ message_type, endian_mismatch, MAX_MESSAGE_LENGTH, message)
108
+ raise SpreadClient.error_for(result) if result < 0
109
+ service_type = service_type.read_int
110
+ sender = sender.read_string
111
+ num_groups = num_groups.read_int
112
+ groups = read_groups(groups, num_groups)
113
+ message = message.read_string
114
+ case
115
+ when regularMessage?(service_type)
116
+ Message.new(sender, message)
117
+ when membershipMessage?(service_type)
118
+ Notification.new(sender, groups, causedBy(service_type))
119
+ end
120
+ end
121
+
122
+ private
123
+
124
+ def regularMessage?(type)
125
+ (type & REGULAR_MESS > 0) && !(type & REJECT_MESS > 0)
126
+ end
127
+
128
+ def membershipMessage?(type)
129
+ (type & MEMBERSHIP_MESS > 0) && !(type & REJECT_MESS > 0)
130
+ end
131
+
132
+ def causedBy(type)
133
+ case
134
+ when type & CAUSED_BY_JOIN > 0 then :join
135
+ when type & CAUSED_BY_LEAVE > 0 && type & REG_MEMB_MESS == 0 then :self_leave
136
+ when type & CAUSED_BY_LEAVE > 0 then :leave
137
+ when type & CAUSED_BY_DISCONNECT > 0 then :disconnect
138
+ when type & CAUSED_BY_NETWORK > 0 then :network
139
+ end
140
+ end
141
+
142
+ def connect(name, options = {})
143
+ options = { :server => DEFAULT_SERVER, :port => DEFAULT_PORT, :notify => DEFAULT_NOTIFY }.merge(options)
144
+ spread_server = "#{options[:port]}@#{options[:server]}"
145
+ notify = options[:notify] ? 1 : 0
146
+ mbox = FFI::MemoryPointer.new(:int)
147
+ private_group = FFI::MemoryPointer.new(:char, MAX_GROUP_LENGTH)
148
+ result = SpreadClient.SP_connect(spread_server, name, DEFAULT_PRIORITY, notify, mbox, private_group)
149
+ raise SpreadClient.error_for(result) unless result == 1
150
+ [mbox.read_int, private_group.read_string]
151
+ end
152
+
153
+ def read_groups(pointer, number)
154
+ groups = []
155
+ number.times do |i|
156
+ groups << pointer[i * MAX_GROUP_LENGTH].read_string
157
+ end
158
+ groups
159
+ end
160
+
161
+ end
162
+
163
+ end
@@ -0,0 +1,35 @@
1
+ module SpreadClient
2
+
3
+ class Error < ::RuntimeError; end
4
+
5
+ class IllegalSpread < Error; end
6
+ class CouldNotConnect < Error; end
7
+ class RejectQuota < Error; end
8
+ class RejectNoName < Error; end
9
+ class RejectIllegalName < Error; end
10
+ class RejectNotUnique < Error; end
11
+ class RejectVersion < Error; end
12
+ class ConnectionClosed < Error; end
13
+ class RejectAuth < Error; end
14
+
15
+ class IllegalSession < Error; end
16
+ class IllegalService < Error; end
17
+ class IllegalMessage < Error; end
18
+ class IllegalGroup < Error; end
19
+ class BufferTooShort < Error; end
20
+ class GroupsTooShort < Error; end
21
+ class MessageTooLong < Error; end
22
+
23
+ private
24
+
25
+ def self.error_for(code)
26
+ errors = [nil,
27
+ IllegalSpread, CouldNotConnect, RejectQuota, RejectNoName, RejectIllegalName,
28
+ RejectNotUnique, RejectVersion, ConnectionClosed, RejectAuth,
29
+ nil,
30
+ IllegalSession, IllegalService, IllegalMessage, IllegalGroup, BufferTooShort,
31
+ GroupsTooShort, MessageTooLong]
32
+ errors.at(code.abs) || Error
33
+ end
34
+
35
+ end
@@ -0,0 +1,41 @@
1
+ module SpreadClient
2
+ extend FFI::Library
3
+ ffi_lib "libspread"
4
+
5
+ # open a connection to the given spread server.
6
+ #
7
+ # options:
8
+ # * :server (default is 'localhost')
9
+ # * :port (default is 4803)
10
+ # * :notify -- set this to false if you do not want to receive any group
11
+ # membership notifications (default is true)
12
+ def self.connect(name, options = {})
13
+ Connection.new(name, options)
14
+ end
15
+
16
+ private
17
+
18
+ # int SP_connect(const char* spread name, const char* private name, int priority, int group_membership,
19
+ # mailbox* mbox, char* private group);
20
+ attach_function :SP_connect, [:string, :string, :int, :int, :pointer, :pointer], :int
21
+
22
+ # int SP_disconnect(mailbox mbox);
23
+ attach_function :SP_disconnect, [:int], :int
24
+
25
+ # int SP_join(mailbox mbox, const char* group);
26
+ attach_function :SP_join, [:int, :string], :int
27
+
28
+ # int SP_leave(mailbox mbox, const char* group);
29
+ attach_function :SP_leave, [:int, :string], :int
30
+
31
+ # int SP_multicast(mailbox mbox, service service_type, const char* group, int16 mess_type,
32
+ # int mess_len, const char* mess);
33
+ attach_function :SP_multicast, [:int, :int, :string, :int16, :int, :string], :int
34
+
35
+ # int SP_receive(mailbox mbox, service* service_type, char sender[MAX_GROUP_NAME], int max_groups,
36
+ # int* num groups, char groups[][MAX_GROUP_NAME], int16* mess_type, int* endian_mismatch,
37
+ # int max_mess_len, char* mess);
38
+ attach_function :SP_receive, [:int, :pointer, :pointer, :int, :pointer, :pointer, :pointer, :pointer,
39
+ :int, :pointer], :int
40
+
41
+ end
@@ -0,0 +1,22 @@
1
+ module SpreadClient
2
+
3
+ class Message
4
+ attr_reader :sender, :text
5
+
6
+ def initialize(sender, text) #:nodoc:
7
+ @sender = sender
8
+ @text = text
9
+ end
10
+ end
11
+
12
+ class Notification
13
+ attr_reader :group, :members, :cause
14
+
15
+ def initialize(group, members, cause) #:nodoc:
16
+ @group = group
17
+ @members = members
18
+ @cause = cause
19
+ end
20
+ end
21
+
22
+ end
@@ -0,0 +1,62 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{spread-client}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Tim Lossen"]
12
+ s.date = %q{2009-12-11}
13
+ s.description = %q{portable ruby bindings for libspread (built with ffi).}
14
+ s.email = %q{tim@lossen.de}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.md"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.md",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "example/demo.rb",
27
+ "example/spread.conf",
28
+ "example/start.sh",
29
+ "lib/spread_client.rb",
30
+ "lib/spread_client/connection.rb",
31
+ "lib/spread_client/errors.rb",
32
+ "lib/spread_client/ffi.rb",
33
+ "lib/spread_client/messages.rb",
34
+ "spread-client.gemspec",
35
+ "test/helper.rb",
36
+ "test/test_connection.rb",
37
+ "test/test_connection_no_notify.rb",
38
+ "test/test_errors.rb"
39
+ ]
40
+ s.homepage = %q{http://github.com/tlossen/spread_client}
41
+ s.rdoc_options = ["--charset=UTF-8"]
42
+ s.require_paths = ["lib"]
43
+ s.rubygems_version = %q{1.3.5}
44
+ s.summary = %q{ruby bindings for libspread (built with ffi)}
45
+ s.test_files = [
46
+ "test/helper.rb",
47
+ "test/test_connection.rb",
48
+ "test/test_connection_no_notify.rb",
49
+ "test/test_errors.rb"
50
+ ]
51
+
52
+ if s.respond_to? :specification_version then
53
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
54
+ s.specification_version = 3
55
+
56
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
57
+ else
58
+ end
59
+ else
60
+ end
61
+ end
62
+
data/test/helper.rb ADDED
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+
4
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'spread_client')
5
+
6
+ class Test::Unit::TestCase
7
+ end
@@ -0,0 +1,51 @@
1
+ require 'helper'
2
+
3
+ class TestConnection < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @c = SpreadClient::connect('bob')
7
+ rescue
8
+ raise "this test expects a spread server running at localhost:4803"
9
+ end
10
+
11
+ def teardown
12
+ @c.disconnect if @c
13
+ end
14
+
15
+ def test_self_join_message
16
+ @c.join('chat')
17
+ message = @c.receive
18
+ assert_equal SpreadClient::Notification, message.class
19
+ assert_equal :join, message.cause
20
+ end
21
+
22
+ def test_self_leave_message
23
+ @c.join('chat')
24
+ @c.receive
25
+ @c.leave('chat')
26
+ message = @c.receive
27
+ assert_equal SpreadClient::Notification, message.class
28
+ assert_equal :self_leave, message.cause
29
+ end
30
+
31
+ def test_multicast
32
+ @c.join('chat')
33
+ @c.receive
34
+ @c.multicast('chat', 'hello folks!')
35
+ message = @c.receive
36
+ assert_equal SpreadClient::Message, message.class
37
+ assert_equal @c.name, message.sender
38
+ assert_equal 'hello folks!', message.text
39
+ end
40
+
41
+ def test_multicast_with_self_discard
42
+ @c.join('chat')
43
+ @c.receive
44
+ @c.multicast('chat', 'one', :self_discard => true)
45
+ @c.multicast('chat', 'two')
46
+ message = @c.receive
47
+ assert_equal 'two', message.text
48
+ end
49
+
50
+
51
+ end
@@ -0,0 +1,22 @@
1
+ require 'helper'
2
+
3
+ class TestConnectionNoNotify < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @c = SpreadClient::connect('bob', :notify => false)
7
+ rescue
8
+ raise "this test expects a spread server running at localhost:4803"
9
+ end
10
+
11
+ def teardown
12
+ @c.disconnect if @c
13
+ end
14
+
15
+ def test_regular_message
16
+ @c.join('chat')
17
+ @c.multicast('chat', 'hello folks!')
18
+ message = @c.receive
19
+ assert_equal SpreadClient::Message, message.class
20
+ end
21
+
22
+ end
@@ -0,0 +1,31 @@
1
+ require 'helper'
2
+
3
+ class TestErrors < Test::Unit::TestCase
4
+
5
+ def test_error_for
6
+ assert_equal SpreadClient::IllegalSpread, SpreadClient.error_for(-1)
7
+ assert_equal SpreadClient::CouldNotConnect, SpreadClient.error_for(-2)
8
+ assert_equal SpreadClient::RejectQuota, SpreadClient.error_for(-3)
9
+ assert_equal SpreadClient::RejectNoName, SpreadClient.error_for(-4)
10
+ assert_equal SpreadClient::RejectIllegalName, SpreadClient.error_for(-5)
11
+ assert_equal SpreadClient::RejectNotUnique, SpreadClient.error_for(-6)
12
+ assert_equal SpreadClient::RejectVersion, SpreadClient.error_for(-7)
13
+ assert_equal SpreadClient::ConnectionClosed, SpreadClient.error_for(-8)
14
+ assert_equal SpreadClient::RejectAuth, SpreadClient.error_for(-9)
15
+
16
+ assert_equal SpreadClient::IllegalSession, SpreadClient.error_for(-11)
17
+ assert_equal SpreadClient::IllegalService, SpreadClient.error_for(-12)
18
+ assert_equal SpreadClient::IllegalMessage, SpreadClient.error_for(-13)
19
+ assert_equal SpreadClient::IllegalGroup, SpreadClient.error_for(-14)
20
+ assert_equal SpreadClient::BufferTooShort, SpreadClient.error_for(-15)
21
+ assert_equal SpreadClient::GroupsTooShort, SpreadClient.error_for(-16)
22
+ assert_equal SpreadClient::MessageTooLong, SpreadClient.error_for(-17)
23
+ end
24
+
25
+ def test_error_for_fallback
26
+ assert_equal SpreadClient::Error, SpreadClient.error_for(0)
27
+ assert_equal SpreadClient::Error, SpreadClient.error_for(-10)
28
+ assert_equal SpreadClient::Error, SpreadClient.error_for(-100)
29
+ end
30
+
31
+ end
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spread-client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Tim Lossen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-12-11 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: portable ruby bindings for libspread (built with ffi).
17
+ email: tim@lossen.de
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - LICENSE
24
+ - README.md
25
+ files:
26
+ - .document
27
+ - .gitignore
28
+ - LICENSE
29
+ - README.md
30
+ - Rakefile
31
+ - VERSION
32
+ - example/demo.rb
33
+ - example/spread.conf
34
+ - example/start.sh
35
+ - lib/spread_client.rb
36
+ - lib/spread_client/connection.rb
37
+ - lib/spread_client/errors.rb
38
+ - lib/spread_client/ffi.rb
39
+ - lib/spread_client/messages.rb
40
+ - spread-client.gemspec
41
+ - test/helper.rb
42
+ - test/test_connection.rb
43
+ - test/test_connection_no_notify.rb
44
+ - test/test_errors.rb
45
+ has_rdoc: true
46
+ homepage: http://github.com/tlossen/spread_client
47
+ licenses: []
48
+
49
+ post_install_message:
50
+ rdoc_options:
51
+ - --charset=UTF-8
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ version:
66
+ requirements: []
67
+
68
+ rubyforge_project:
69
+ rubygems_version: 1.3.5
70
+ signing_key:
71
+ specification_version: 3
72
+ summary: ruby bindings for libspread (built with ffi)
73
+ test_files:
74
+ - test/helper.rb
75
+ - test/test_connection.rb
76
+ - test/test_connection_no_notify.rb
77
+ - test/test_errors.rb