tipcsocket 0.1

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/CHANGELOG ADDED
@@ -0,0 +1,7 @@
1
+ = TIPCSocket Changelog
2
+
3
+ == Version 0.0.1
4
+
5
+ === January 14, 2008
6
+
7
+ * Initial creation.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2007 Corey Burrows
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 ADDED
@@ -0,0 +1,77 @@
1
+ = TIPCSocket
2
+
3
+ Ruby bindings for the TIPC[http://tipc.sourceforge.net] native socket API.
4
+
5
+ = Installing TIPCSocket
6
+
7
+ Get TIPCSocket from RubyForge.
8
+
9
+ $ gem install tipcsocket
10
+
11
+ = Example
12
+
13
+ Server:
14
+
15
+ require 'rubygems'
16
+ require 'tipcsocket'
17
+
18
+ include TIPCSocket::Constants
19
+
20
+ server_addr = TIPCNameSeq.new(18888, 17, 17, TIPC_ZONE_SCOPE)
21
+
22
+ s = TIPCSocket.new(:rdm)
23
+ s.bind(server_addr)
24
+
25
+ data, client = s.recvfrom(65535)
26
+
27
+ client = TIPCSocket.unpack_sockaddr(client)
28
+
29
+ p client
30
+
31
+ puts "server: message received: #{data}"
32
+
33
+ s.send("hello client!", 0, client)
34
+
35
+ s.close
36
+
37
+ Client:
38
+
39
+ require 'rubygems'
40
+ require 'tipcsocket'
41
+
42
+ include TIPCSocket::Constants
43
+
44
+ server_addr = TIPCName.new(18888, 17, TIPC_NODE_SCOPE)
45
+
46
+ s = TIPCSocket.new(:rdm)
47
+ s.send("hello server!", 0, server_addr)
48
+
49
+ msg = s.recv(65535)
50
+
51
+ puts "client: received response: #{msg}"
52
+
53
+ s.close
54
+
55
+ Server Output:
56
+
57
+ $ ruby server.rb
58
+ #<TIPCPortId:0xb79c89a4 @family=30, @ref=2292940796, @scope=0, @addrtype=3, @node=0>
59
+ server: message received: hello server!
60
+
61
+ Client Output:
62
+
63
+ $ ruby client.rb
64
+ client: received response: hello client!
65
+
66
+ = More Examples
67
+
68
+ See the demo/ directory for more examples.
69
+
70
+ = Project Page
71
+
72
+ http://rubyforge.org/projects/tipcsocket
73
+
74
+ = Author
75
+
76
+ Corey Burrows (mailto:corey.burrows@gmail.com)
77
+
data/Rakefile ADDED
@@ -0,0 +1,56 @@
1
+
2
+ require 'rubygems'
3
+ Gem::manage_gems
4
+ require 'rake/gempackagetask'
5
+ require 'rake/clean'
6
+ require 'rake/rdoctask'
7
+
8
+ NAME = 'tipcsocket'
9
+ VERS = '0.1'
10
+ RUBYFORGE_USER = "burrows"
11
+ WWW = "#{RUBYFORGE_USER}@rubyforge.org:/var/www/gforge-projects/#{NAME}/"
12
+
13
+ RDOC_MAIN = "README"
14
+
15
+ spec = Gem::Specification.new do |s|
16
+ s.name = NAME
17
+ s.version = VERS
18
+ s.author = "Corey Burrows"
19
+ s.email = "corey.burrows@gmail.com"
20
+ s.platform = Gem::Platform::RUBY
21
+ s.summary = "Ruby bindings for the TIPC socket API."
22
+ s.files = %w{README CHANGELOG LICENSE Rakefile} +
23
+ Dir.glob("lib/**/*.{rb}") +
24
+ Dir.glob("test/**/*.rb") +
25
+ Dir.glob("demo/**/*.rb")
26
+ s.require_path = "lib"
27
+ s.autorequire = "tipcsocket"
28
+ #s.test_file = ""
29
+ s.has_rdoc = true
30
+ end
31
+
32
+ Rake::GemPackageTask.new(spec) do |pkg|
33
+ pkg.need_tar = true
34
+ end
35
+
36
+ Rake::RDocTask.new do |rd|
37
+ rd.main = RDOC_MAIN
38
+ rd.rdoc_files.include(RDOC_MAIN, "lib/**/*.rb", "CHANGELOG", "LICENSE")
39
+ rd.options << "--all"
40
+ end
41
+
42
+ CLEAN += FileList["ext/**/*.o", "ext/**/*.so", "ext/**/*.bundle", "ext/**/mkmf.log"]
43
+
44
+ task :test => :build do
45
+ end
46
+
47
+ task :install do
48
+ name = "#{NAME}-#{VERS}.gem"
49
+ sh %{rake pkg/#{name}}
50
+ sh %{sudo gem install pkg/#{name}}
51
+ end
52
+
53
+ task :uninstall do
54
+ sh %{sudo gem uninstall #{NAME}}
55
+ end
56
+
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), '..', '..', 'lib')
4
+
5
+ require 'tipcsocket'
6
+ include TIPCSocket::Constants
7
+
8
+ puts "****** TIPC client hello world program started ******\n"
9
+
10
+ $server_type = 18888
11
+ $server_inst = 17
12
+
13
+ def wait_for_server(name, wait)
14
+ puts "Client: waiting for server #{name.type}, #{name.instance}..."
15
+
16
+ topsrv = TIPCName.new(TIPC_TOP_SRV, TIPC_TOP_SRV)
17
+ subscr = TIPCSubscr.new(
18
+ TIPCNameSeq.new(name.type, name.instance, name.instance),
19
+ wait,
20
+ TIPC_SUB_SERVICE)
21
+
22
+ s = TIPCSocket.new(:seqpacket)
23
+ s.connect(topsrv)
24
+ s.send(subscr.pack, 0)
25
+
26
+ rsp = s.recv(65535)
27
+
28
+ event = TIPCEvent.unpack(rsp)
29
+
30
+ if event.event != TIPC_PUBLISHED
31
+ puts "Client: server #{name.type}, #{name.instance} not published within #{wait/1000} [s]"
32
+ exit 1
33
+ end
34
+
35
+ s.close
36
+ end
37
+
38
+ s = TIPCSocket.new(:rdm)
39
+
40
+ # send a message to the server
41
+ server_addr = TIPCName.new($server_type, $server_inst, TIPC_NODE_SCOPE)
42
+
43
+ wait_for_server(server_addr, 10000)
44
+
45
+ s.send("Hello World", 0, server_addr)
46
+
47
+ # wait for a response
48
+ msg = s.recv(65535)
49
+
50
+ puts "Client: Received response: #{msg}"
51
+
52
+ s.close
53
+
54
+ puts "****** TIPC client hello program finished ******"
55
+
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), '..', '..', 'lib')
4
+
5
+ require 'tipcsocket'
6
+ include TIPCSocket::Constants
7
+
8
+ $server_type = 18888
9
+ $server_inst = 17
10
+
11
+ puts "****** TIPC server hello world program started ******\n\n"
12
+
13
+ server_addr = TIPCNameSeq.new($server_type, $server_inst, $server_inst, TIPC_ZONE_SCOPE)
14
+
15
+ s = TIPCSocket.new(:rdm)
16
+ s.bind(server_addr)
17
+
18
+ data, client = s.recvfrom(65535)
19
+
20
+ client = TIPCSocket.unpack_sockaddr(client)
21
+
22
+ puts "Server: Message received: #{data} !"
23
+
24
+ s.send("Uh ?", 0, client)
25
+
26
+ s.close
27
+
28
+ puts "\n****** TIPC server hello program finished ******"
29
+
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), '..', '..', 'lib')
4
+
5
+ require 'tipcsocket'
6
+ include TIPCSocket::Constants
7
+
8
+ $server_type = 8888
9
+ $server_inst = 17
10
+
11
+ $buf_size = 2000
12
+ $msg_size = 80
13
+
14
+ def wait_for_server(name, wait)
15
+ puts "Client: waiting for server #{name.type}, #{name.instance}..."
16
+
17
+ topsrv = TIPCName.new(TIPC_TOP_SRV, TIPC_TOP_SRV)
18
+ subscr = TIPCSubscr.new(
19
+ TIPCNameSeq.new(name.type, name.instance, name.instance),
20
+ wait,
21
+ TIPC_SUB_SERVICE)
22
+
23
+ s = TIPCSocket.new(:seqpacket)
24
+ s.connect(topsrv)
25
+ s.send(subscr.pack, 0)
26
+
27
+ rsp = s.recv(65535)
28
+
29
+ event = TIPCEvent.unpack(rsp)
30
+
31
+ if event.event != TIPC_PUBLISHED
32
+ puts "Client: server #{name.type}, #{name.instance} not published within #{wait/1000} [s]"
33
+ exit 1
34
+ end
35
+
36
+ s.close
37
+ end
38
+
39
+ puts "****** TIPC stream demo client started ******"
40
+
41
+ server_addr = TIPCName.new($server_type, $server_inst)
42
+
43
+ wait_for_server(server_addr, 10000)
44
+
45
+ s = TIPCSocket.new(:stream)
46
+
47
+ begin
48
+ s.connect(server_addr)
49
+ rescue Exception => e
50
+ puts "Client: connect failed: #{e}"
51
+ exit 1
52
+ end
53
+
54
+ # create buffer containing numerous (size,data) records
55
+
56
+ tot_size = 0
57
+ rec_size = 1
58
+ rec_num = 0
59
+ buf = ""
60
+
61
+ while tot_size + 4 + rec_size < $buf_size
62
+ rec_num += 1
63
+ buf += [rec_size].pack("N")
64
+ rec_size.times do
65
+ buf += [rec_size].pack("C")
66
+ end
67
+ puts "Client: creating record #{rec_num} of size #{rec_size} bytes"
68
+
69
+ tot_size += (4 + rec_size)
70
+ rec_size = (rec_size + 147) & 0xFF;
71
+
72
+ rec_size = 1 if (rec_size == 0) # record size must me 1-255 bytes
73
+ end
74
+
75
+ # now send records using messages that break record boundaries
76
+
77
+ puts "Client: sending records using #{$msg_size} byte messages"
78
+
79
+ sent_size = 0
80
+ while sent_size < tot_size
81
+ if (sent_size + $msg_size) <= tot_size
82
+ msg_size = $msg_size
83
+ else
84
+ msg_size = (tot_size - sent_size)
85
+ end
86
+
87
+ if (0 > s.send(buf[sent_size, msg_size], 0))
88
+ puts "Client: failed to send"
89
+ exit 1
90
+ end
91
+
92
+ sent_size += msg_size
93
+ end
94
+
95
+ # now grab set of one-byte client acknowledgements all at once
96
+
97
+ puts "Client: waiting for server acknowledgements"
98
+ rsp = s.recv(rec_num, Socket::MSG_WAITALL)
99
+ if rsp.length != rec_num
100
+ puts "Client: acknowledge error 1"
101
+ exit 1
102
+ end
103
+
104
+ rsp = nil
105
+ begin
106
+ rsp = s.recv_nonblock(1)
107
+ rescue Errno::EAGAIN => e
108
+ end
109
+
110
+ if rsp
111
+ puts "Client: acknowledge error 2"
112
+ exit 1
113
+ end
114
+
115
+ puts "Client: received #{rec_num} acknowledgements"
116
+
117
+ s.shutdown(Socket::SHUT_RDWR)
118
+ s.close
119
+
120
+ puts "****** TIPC stream demo client finished ******"
121
+ exit 0
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), '..', '..', 'lib')
4
+
5
+ require 'tipcsocket'
6
+ include TIPCSocket::Constants
7
+
8
+ $server_type = 8888
9
+ $server_inst = 17
10
+
11
+ puts "****** TIPC stream demo server started ******"
12
+
13
+ listener = TIPCSocket.new(:stream)
14
+
15
+ server_addr = TIPCNameSeq.new($server_type, $server_inst, $server_inst, TIPC_ZONE_SCOPE)
16
+
17
+ listener.bind(server_addr)
18
+ listener.listen(0)
19
+
20
+ peer, peer_addr = listener.accept
21
+
22
+ rec_num = 0
23
+
24
+ loop do
25
+ begin
26
+ puts "calling peer.recv..."
27
+ msg = peer.recv(4, Socket::MSG_WAITALL)
28
+ puts "recieved #{msg.length} bytes"
29
+ rescue Exception => e
30
+ puts "Server: client terminated abnormally: #{e}"
31
+ exit 1
32
+ end
33
+
34
+ if msg.length == 0
35
+ puts "Server: client terminated normally"
36
+ break
37
+ end
38
+
39
+ rec_num += 1
40
+
41
+ rec_size = msg.unpack("N")[0]
42
+ puts "Server: receiving record #{rec_num} of #{rec_size} bytes"
43
+
44
+ msg = peer.recv(rec_size, Socket::MSG_WAITALL)
45
+
46
+ if msg.length != rec_size
47
+ puts "Server: receive error, got #{msg.length} bytes"
48
+ exit 1
49
+ end
50
+
51
+ msg.each_byte do |b|
52
+ if b != rec_size
53
+ puts "Server: record content error"
54
+ exit 1
55
+ end
56
+ end
57
+
58
+ puts "Server: record #{rec_num} received"
59
+
60
+ # send 1 byte acknowledgement (value is irrelevant)
61
+ peer.send("X", 0)
62
+
63
+ puts "Server: record #{rec_num} acknowledged"
64
+ end
65
+
66
+ puts "****** TIPC stream demo server finished ******"
67
+
68
+ exit 0
69
+
data/lib/tipcsocket.rb ADDED
@@ -0,0 +1,514 @@
1
+
2
+ require 'socket'
3
+
4
+ module Socket::Constants
5
+ AF_TIPC = 30
6
+ PF_TIPC = AF_TIPC
7
+ SOL_TIPC = 271
8
+ end
9
+
10
+ # Represents a TIPC port identifier.
11
+ #
12
+ # From the {TIPC Programmer's Guide}[http://tipc.sourceforge.net/doc/Programmers_Guide.txt]:
13
+ #
14
+ # Each port in a TIPC network has a unique "port identifier" or "port ID",
15
+ # which is typically denoted as <Z.C.N:ref>. The port ID is assigned
16
+ # automatically by TIPC when the port is created, and consists of the 32-bit
17
+ # network address of the port's node and a 32-bit reference value. The
18
+ # reference value is guaranteed to be unique on a per-node basis and will not
19
+ # be reused for a long time once the port ceases to exist.
20
+ class TIPCPortId
21
+ attr_reader :family, :addrtype
22
+ attr_accessor :ref, :node, :scope
23
+
24
+ # Create a new TIPCPortId instance.
25
+ #
26
+ # === Parameters
27
+ # * ref - 32 bit reference value
28
+ # * node - 32 bit network address of the port's node
29
+ # * scope - the scope (zone, cluster, or node) to use when packing this port
30
+ # id as a TIPC address (optional)
31
+ def initialize(ref, node, scope = TIPCSocket::Constants::TIPC_NODE_SCOPE)
32
+ @family = Socket::Constants::AF_TIPC
33
+ @addrtype = TIPCSocket::Constants::TIPC_ADDR_ID
34
+ @ref = ref
35
+ @node = node
36
+ @scope = scope
37
+ end
38
+
39
+ # Pack an instance of a TIPCPortId as a 16 byte TIPC network address suitable
40
+ # for passing to one of the standard Socket methods (connect, send, etc.).
41
+ #
42
+ # Produces a 16 byte binary string with the following format:
43
+ # * family - unsigned short (2 bytes)
44
+ # * addrtype - unsigned char (1 byte)
45
+ # * scope - signed char (1 byte)
46
+ # * ref - uint32 (4 bytes)
47
+ # * node - uint32 (4 bytes)
48
+ # * padding - uint32 (4 bytes)
49
+ def pack_addr
50
+ [
51
+ self.family,
52
+ self.addrtype,
53
+ self.scope,
54
+ self.ref,
55
+ self.node,
56
+ 0
57
+ ].pack("SCcL3")
58
+ end
59
+
60
+ # Pack an instance of a TIPCPortId.
61
+ #
62
+ # Produces an 8 byte string with the following format:
63
+ # * ref - uint32 (4 bytes)
64
+ # * node - uint32 (4 bytes)
65
+ def pack
66
+ [
67
+ self.ref,
68
+ self.node,
69
+ ].pack("L2")
70
+ end
71
+
72
+ # Create a new TIPCPortId instance from a 16 byte binary string containing a
73
+ # TIPC address.
74
+ #
75
+ # === Parameters
76
+ # * bytes - 16 byte string containing TIPC address
77
+ def self.unpack_addr(bytes)
78
+ data = bytes.unpack("SCcL3")
79
+ self.new(data[3], data[4], data[2])
80
+ end
81
+
82
+ # Create a new TIPCPortId instance from an 8 byte binary string containing
83
+ # a TIPC port indentifier.
84
+ #
85
+ # === Parameters
86
+ # * bytes - 8 byte string containing TIPC port identifier
87
+ def self.unpack(bytes)
88
+ data = bytes.unpack("L2")
89
+ self.new(data[0], data[1])
90
+ end
91
+ end
92
+
93
+ # Represents a TIPC name address of the form <type, instance>.
94
+ #
95
+ # From the {TIPC Programmer's Guide}[http://tipc.sourceforge.net/doc/Programmers_Guide.txt]:
96
+ #
97
+ # The basic unit of functional addressing within TIPC is the "port name", which
98
+ # is typically denoted as {type,instance}. A port name consists of a 32-bit
99
+ # type field and a 32-bit instance field, both of which are chosen by the
100
+ # application. Typically, the type field is used to indicate the class of
101
+ # service provided by the port, while the instance field can be used as a sub-
102
+ # class indicator.
103
+ class TIPCName
104
+ attr_reader :family, :addrtype
105
+ attr_accessor :type, :instance, :scope, :domain
106
+
107
+ # Create a new TIPCName instance.
108
+ #
109
+ # === Parameters
110
+ # * type - arbitrary 32 bit type value
111
+ # * instance - arbitrary 32 bit instance value
112
+ # * scope - the scope (zone, cluster, or node) to use when packing
113
+ # this name as a TIPC address (optional)
114
+ # * domain - indicates the search domain used during the name lookup
115
+ # process (optional)
116
+ def initialize(type, instance, scope = TIPCSocket::Constants::TIPC_NODE_SCOPE, domain = 0)
117
+ @family = Socket::Constants::AF_TIPC
118
+ @addrtype = TIPCSocket::Constants::TIPC_ADDR_NAME
119
+ @type = type
120
+ @instance = instance
121
+ @scope = scope
122
+ @domain = 0
123
+ end
124
+
125
+ # Pack an instance of a TIPCName as a 16 byte TIPC network address suitable
126
+ # for passing to one of the standard Socket methods (connect, send, etc.).
127
+ #
128
+ # Produces a 16 byte binary string with the following format:
129
+ # * family - unsigned short (2 bytes)
130
+ # * addrtype - unsigned char (1 byte)
131
+ # * scope - signed char (1 byte)
132
+ # * type - uint32 (4 bytes)
133
+ # * instance - uint32 (4 bytes)
134
+ # * domain - uint32 (4 bytes)
135
+ def pack_addr
136
+ [
137
+ self.family,
138
+ self.addrtype,
139
+ self.scope,
140
+ self.type,
141
+ self.instance,
142
+ self.domain
143
+ ].pack("SCcL3")
144
+ end
145
+
146
+ # Pack an instance of a TIPCName.
147
+ #
148
+ # Produces an 8 byte string with the following format:
149
+ # * type - uint32 (4 bytes)
150
+ # * instance - uint32 (4 bytes)
151
+ def pack
152
+ [
153
+ self.type,
154
+ self.instance
155
+ ].pack("L2")
156
+ end
157
+
158
+ # Create a new TIPCName instance from a 16 byte binary string containing a
159
+ # TIPC address.
160
+ #
161
+ # === Parameters
162
+ # * bytes - 16 byte string containing TIPC address
163
+ def self.unpack_addr(bytes)
164
+ data = bytes.unpack("SCcL3")
165
+ self.new(data[3], data[4], data[2], data[5])
166
+ end
167
+
168
+ # Create a new TIPCName instance from an 8 byte binary string containing
169
+ # a TIPC name.
170
+ #
171
+ # === Parameters
172
+ # * bytes - 8 byte string containing TIPC name
173
+ def self.unpack(bytes)
174
+ data = bytes.unpack("L2")
175
+ self.new(data[0], data[1])
176
+ end
177
+ end
178
+
179
+ # Represents a TIPC port name sequence address of the form
180
+ # <type, lower bound, upper bound>.
181
+ #
182
+ # From the {TIPC Programmer's Guide}[http://tipc.sourceforge.net/doc/Programmers_Guide.txt]:
183
+ #
184
+ # A port name sequence consists of a 32-bit type field and a pair of 32-bit
185
+ # instance fields, and represents the set of port names from {type,lower bound}
186
+ # through {type,upper bound}, inclusive. The lower bound of a name sequence
187
+ # cannot be larger than the upper bound.
188
+ class TIPCNameSeq
189
+ attr_reader :family, :addrtype
190
+ attr_accessor :type, :lower, :upper, :scope
191
+
192
+ # Create a new TIPCNameSeq instance.
193
+ #
194
+ # === Parameters
195
+ # * type - arbitrary 32 bit type value
196
+ # * lower - 32-bit lower bound of the name sequence
197
+ # * upper - 32-bit upper bound of the name sequence
198
+ # * scope - the scope (zone, cluster, or node) to use when packing
199
+ # this name as a TIPC address (optional)
200
+ def initialize(type, lower, upper, scope = TIPCSocket::Constants::TIPC_NODE_SCOPE)
201
+ @family = Socket::Constants::AF_TIPC
202
+ @addrtype = TIPCSocket::Constants::TIPC_ADDR_NAMESEQ
203
+ @type = type
204
+ @lower = lower
205
+ @upper = upper
206
+ @scope = scope
207
+ end
208
+
209
+ # Pack an instance of a TIPCNameSeq as a 16 byte TIPC network address suitable
210
+ # for passing to one of the standard Socket methods (connect, send, etc.).
211
+ #
212
+ # Produces a 16 byte binary string with the following format:
213
+ # * family - unsigned short (2 bytes)
214
+ # * addrtype - unsigned char (1 byte)
215
+ # * scope - signed char (1 byte)
216
+ # * type - uint32 (4 bytes)
217
+ # * lower - uint32 (4 bytes)
218
+ # * upper - uint32 (4 bytes)
219
+ def pack_addr
220
+ [
221
+ self.family,
222
+ self.addrtype,
223
+ self.scope,
224
+ self.type,
225
+ self.lower,
226
+ self.upper
227
+ ].pack("SCcL3")
228
+ end
229
+
230
+ # Pack an instance of a TIPCNameSeq.
231
+ #
232
+ # Produces an 12 byte string with the following format:
233
+ # * type - uint32 (4 bytes)
234
+ # * lower - uint32 (4 bytes)
235
+ # * upper - uint32 (4 bytes)
236
+ def pack
237
+ [
238
+ self.type,
239
+ self.lower,
240
+ self.upper
241
+ ].pack("L3")
242
+ end
243
+
244
+ # Create a new TIPCNameSeq instance from a 16 byte binary string containing a
245
+ # TIPC address.
246
+ #
247
+ # === Parameters
248
+ # * bytes - 16 byte string containing TIPC address
249
+ def self.unpack_addr(bytes)
250
+ data = bytes.unpack("SCcL3")
251
+ self.new(data[3], data[4], data[5], data[2])
252
+ end
253
+
254
+ # Create a new TIPCNameSeq instance from a 12 byte binary string containing
255
+ # a TIPC name sequence.
256
+ #
257
+ # === Parameters
258
+ # * bytes - 12 byte string containing TIPC name sequence
259
+ def self.unpack(bytes)
260
+ data = bytes.unpack("L3")
261
+ self.new(data[0], data[1], data[2])
262
+ end
263
+ end
264
+
265
+ # Represents a TIPC subscription.
266
+ #
267
+ # From the {TIPC Programmer's Guide}[http://tipc.sourceforge.net/doc/Programmers_Guide.txt]:
268
+ #
269
+ # TIPC provides a network topology service that applications can use to receive
270
+ # information about what port names exist within the application's network zone.
271
+ #
272
+ # An application accesses the topology service by opening a message-based
273
+ # connection to port name {1,1} and then sending "subscription" messages to the
274
+ # topology service that indicate the port names of interest to the application;
275
+ # in return, the topology service sends "event" messages to the application when
276
+ # these names are published or withdrawn by ports within the network.
277
+ class TIPCSubscr
278
+ attr_accessor :name_seq, :timeout, :filter, :usr_handle
279
+
280
+ # Create a new TIPCSubscr instance.
281
+ #
282
+ # === Parameters
283
+ # * name_seq - the port name sequence of interest, must be an instance of
284
+ # TIPCNameSeq
285
+ # * timeout - subscription timeout value in milliseconds, use the constant
286
+ # TIPC_WAIT_FOREVER to specify no timeout
287
+ # * filter - a bitmask containing one or more event filters, see below
288
+ # for a description of filter types
289
+ # * usr_handle - 8 byte string that is application defined, this value is
290
+ # returned to the application as part of all events associated
291
+ # with the subscription event
292
+ #
293
+ # === Filter Types
294
+ # * TIPC_SUB_PORTS - causes the topology service to generate a TIPC_PUBLISHED
295
+ # event for each port name or port name sequence it finds
296
+ # that overlaps the specified port name sequence; a
297
+ # TIPC_WITHDRAWN event is issued each time a previously
298
+ # reported name becomes unavailable
299
+ # * TIPC_SUB_SERVICE - causes the topology service to generate a single publish
300
+ # event for the first port it finds with an overlapping
301
+ # name and a single withdraw event when the last such port
302
+ # becomes unavailable
303
+ # * TIPC_SUB_CANCEL - cancels and existing topology service subscription, all
304
+ # other parameters should match the original subscription
305
+ # request
306
+ def initialize(name_seq, timeout, filter, usr_handle = '')
307
+ @name_seq = name_seq
308
+ @timeout = timeout
309
+ @filter = filter
310
+ @usr_handle = usr_handle
311
+ end
312
+
313
+ # Pack an instance of a TIPCSubscr.
314
+ #
315
+ # Produces a 28 byte string with the following format:
316
+ # * name_seq (12 bytes)
317
+ # * timeout - uint32 (4 bytes)
318
+ # * filter - uint32 (4 bytes)
319
+ # * usr_handle - char[8] (8 bytes)
320
+ def pack
321
+ [
322
+ self.name_seq.pack,
323
+ self.timeout,
324
+ self.filter,
325
+ self.usr_handle
326
+ ].pack("a12L2a8")
327
+ end
328
+
329
+ # Create a new TIPCSubscr instance from a 28 byte binary string containing
330
+ # a TIPC name sequence.
331
+ #
332
+ # === Parameters
333
+ # * bytes - 28 byte string containing TIPC name sequence
334
+ def self.unpack(bytes)
335
+ data = bytes.unpack("a12L2a8")
336
+ self.new(TIPCNameSeq.unpack(data[0]), data[1], data[2], data[3])
337
+ end
338
+ end
339
+
340
+ # Represents a TIPC event message.
341
+ #
342
+ # TIPC event messages are returned by the TIPC topology server when subscribed
343
+ # to events occur.
344
+ class TIPCEvent
345
+ attr_accessor :event, :found_lower, :found_upper, :port, :subscr
346
+
347
+ # Create a new TIPCEvent instance.
348
+ #
349
+ # === Parameters
350
+ # * event - 32-bit event type, may be either TIPC_PUBLISHED, TIPC_WITHDRAWN,
351
+ # or TIPC_SUBSCR_TIMEOUT
352
+ # * found_lower - 32-bit lower bound of the port name sequence that overlaps
353
+ # the name sequence specified by the subscription
354
+ # * found_upper - 32-bit upper bound of the port name sequence that overlaps
355
+ # the name sequence specified by the subscription
356
+ # * port - an instance of TIPCPortId that represents the port ID of the
357
+ # associated port
358
+ # * subscr - an instance of TIPCSubscr that represents the subscription
359
+ # request associated with the event
360
+ def initialize(event, found_lower, found_upper, port, subscr)
361
+ @event = event
362
+ @found_lower = found_lower
363
+ @found_upper = found_upper
364
+ @port = port
365
+ @subscr = subscr
366
+ end
367
+
368
+ # Pack an instance of a TIPCEvent.
369
+ #
370
+ # Produces an 48 byte string with the following format:
371
+ # * event - uint32 = 4
372
+ # * found_lower - uint32 = 4
373
+ # * found_upper - uint32 = 4
374
+ # * port_id = 8
375
+ # * subscr = 28
376
+ def pack
377
+ [
378
+ self.event,
379
+ self.found_lower,
380
+ self.found_upper,
381
+ port.pack,
382
+ subscr.pack
383
+ ].pack("L3a8a28")
384
+ end
385
+
386
+ # Create a new TIPCEvent instance from a 48 byte binary string containing a
387
+ # TIPC event.
388
+ #
389
+ # === Parameters
390
+ # * bytes - 48 byte string containing TIPC address
391
+ def self.unpack(bytes)
392
+ data = bytes.unpack("L3a8a28")
393
+ self.new(data[0], data[1], data[2], TIPCPortId.unpack(data[3]),
394
+ TIPCSubscr.unpack(data[4]))
395
+ end
396
+ end
397
+
398
+ # Provides access to a TIPC[http://tipc.sourceforge.net] socket. Subclass of
399
+ # the standard ruby Socket class.
400
+ class TIPCSocket < Socket
401
+ module Constants
402
+ # application accessible port name types
403
+ TIPC_CFG_SRV = 0
404
+ TIPC_TOP_SRV = 1
405
+ TIPC_RESERVED_TYPES = 64
406
+
407
+ # publication scopes when binding port names and port name sequences
408
+ TIPC_ZONE_SCOPE = 1
409
+ TIPC_CLUSTER_SCOPE = 2
410
+ TIPC_NODE_SCOPE = 3
411
+
412
+ # limiting values for messages
413
+ TIPC_MAX_USER_MSG_SIZE = 66000
414
+
415
+ # message importance levels
416
+ TIPC_LOW_IMPORTANCE = 0
417
+ TIPC_MEDIUM_IMPORTANCE = 1
418
+ TIPC_HIGH_IMPORTANCE = 2
419
+ TIPC_CRITICAL_IMPORTANCE = 3
420
+
421
+ # message rejection/connection shutdown reasons
422
+ TIPC_OK = 0
423
+ TIPC_ERR_NO_NAME = 1
424
+ TIPC_ERR_NO_PORT = 2
425
+ TIPC_ERR_NO_NODE = 3
426
+ TIPC_ERR_OVERLOAD = 4
427
+ TIPC_CONN_SHUTDOWN = 5
428
+
429
+ # topology subscription service definitions
430
+ TIPC_SUB_PORTS = 0x01
431
+ TIPC_SUB_SERVICE = 0x02
432
+ TIPC_SUB_CANCEL = 0x04
433
+
434
+ TIPC_WAIT_FOREVER = -1
435
+
436
+ # address types
437
+ TIPC_ADDR_NAMESEQ = 1
438
+ TIPC_ADDR_MCAST = 1
439
+ TIPC_ADDR_NAME = 2
440
+ TIPC_ADDR_ID = 3
441
+
442
+ # events
443
+ TIPC_PUBLISHED = 1
444
+ TIPC_WITHDRAWN = 2
445
+ TIPC_SUBSCR_TIMEOUT = 3
446
+ end
447
+
448
+ # Create a new TIPCSocket instance from a 16 byte binary string containing a
449
+ # TIPC address. Returns one of the following depending on the addrtype
450
+ # field: TIPCNameSeq, TIPCName, TIPCPortId.
451
+ #
452
+ # === Parameters
453
+ # * bytes - 16 byte string containing TIPC address
454
+ def self.unpack_sockaddr(bytes)
455
+ family, addrtype = bytes.unpack("SC")
456
+
457
+ case
458
+ when addrtype == Constants::TIPC_ADDR_NAMESEQ
459
+ TIPCNameSeq.unpack_addr(bytes)
460
+ when addrtype == Constants::TIPC_ADDR_NAME
461
+ TIPCName.unpack_addr(bytes)
462
+ when addrtype == Constants::TIPC_ADDR_ID
463
+ TIPCPortId.unpack_addr(bytes)
464
+ else
465
+ raise ArgumentError, "invalid address type (#{addrtype})"
466
+ end
467
+ end
468
+
469
+ # Create a new instance of a TIPCSocket.
470
+ #
471
+ # === Parameters
472
+ # - type: must be one of the following
473
+ # * :stream - for reliable connection-oriented byte streams
474
+ # * :seqpacket - for reliable connection-oriented messages
475
+ # * :rdm - for reliable connectionless messages
476
+ # * :dgram - for unreliable connectionless messages
477
+ # - protocol: passed directly to Socket.new (optional)
478
+ def initialize(type, protocol = 0)
479
+ case type.to_s.downcase
480
+ when 'stream'
481
+ type = Socket::Constants::SOCK_STREAM
482
+ when 'seqpacket'
483
+ type = Socket::Constants::SOCK_SEQPACKET
484
+ when 'rdm'
485
+ type = Socket::Constants::SOCK_RDM
486
+ when 'dgram'
487
+ type = Socket::Constants::SOCK_DGRAM
488
+ else
489
+ raise TypeError, "invalid TIPC socket type (#{type})"
490
+ end
491
+
492
+ super(Socket::Constants::AF_TIPC, type, protocol)
493
+ end
494
+
495
+ def send(msg, flags, tipc_addr = nil)
496
+ if tipc_addr
497
+ tipc_addr = tipc_addr.is_a?(String) ? tipc_addr : tipc_addr.pack_addr
498
+ super(msg, flags, tipc_addr)
499
+ else
500
+ super(msg, flags)
501
+ end
502
+ end
503
+
504
+ def bind(tipc_addr)
505
+ tipc_addr = tipc_addr.is_a?(String) ? tipc_addr : tipc_addr.pack_addr
506
+ super(tipc_addr)
507
+ end
508
+
509
+ def connect(tipc_addr)
510
+ tipc_addr = tipc_addr.is_a?(String) ? tipc_addr : tipc_addr.pack_addr
511
+ super(tipc_addr)
512
+ end
513
+ end
514
+
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.4
3
+ specification_version: 1
4
+ name: tipcsocket
5
+ version: !ruby/object:Gem::Version
6
+ version: "0.1"
7
+ date: 2008-01-14 00:00:00 -06:00
8
+ summary: Ruby bindings for the TIPC socket API.
9
+ require_paths:
10
+ - lib
11
+ email: corey.burrows@gmail.com
12
+ homepage:
13
+ rubyforge_project:
14
+ description:
15
+ autorequire: tipcsocket
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Corey Burrows
31
+ files:
32
+ - README
33
+ - CHANGELOG
34
+ - LICENSE
35
+ - Rakefile
36
+ - lib/tipcsocket.rb
37
+ - demo/hello_world/client.rb
38
+ - demo/hello_world/server.rb
39
+ - demo/stream_demo/client.rb
40
+ - demo/stream_demo/server.rb
41
+ test_files: []
42
+
43
+ rdoc_options: []
44
+
45
+ extra_rdoc_files: []
46
+
47
+ executables: []
48
+
49
+ extensions: []
50
+
51
+ requirements: []
52
+
53
+ dependencies: []
54
+