tipcsocket 0.1

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