bunny 0.6.3.rc2 → 0.7
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/.gitignore +8 -0
- data/.rspec +3 -0
- data/.travis.yml +15 -0
- data/.yardopts +9 -0
- data/CHANGELOG +3 -0
- data/Gemfile +39 -0
- data/Gemfile.lock +34 -0
- data/LICENSE +5 -4
- data/README.textile +54 -0
- data/Rakefile +15 -13
- data/bunny.gemspec +42 -61
- data/examples/simple_08.rb +4 -2
- data/examples/simple_09.rb +4 -2
- data/examples/simple_ack_08.rb +3 -1
- data/examples/simple_ack_09.rb +3 -1
- data/examples/simple_consumer_08.rb +4 -2
- data/examples/simple_consumer_09.rb +4 -2
- data/examples/simple_fanout_08.rb +3 -1
- data/examples/simple_fanout_09.rb +3 -1
- data/examples/simple_headers_08.rb +5 -3
- data/examples/simple_headers_09.rb +5 -3
- data/examples/simple_publisher_08.rb +3 -1
- data/examples/simple_publisher_09.rb +3 -1
- data/examples/simple_topic_08.rb +5 -3
- data/examples/simple_topic_09.rb +5 -3
- data/ext/amqp-0.8.json +616 -0
- data/ext/amqp-0.9.1.json +388 -0
- data/ext/config.yml +4 -0
- data/ext/qparser.rb +463 -0
- data/lib/bunny.rb +88 -66
- data/lib/bunny/channel08.rb +38 -38
- data/lib/bunny/channel09.rb +37 -37
- data/lib/bunny/client08.rb +184 -206
- data/lib/bunny/client09.rb +277 -363
- data/lib/bunny/consumer.rb +35 -0
- data/lib/bunny/exchange08.rb +37 -41
- data/lib/bunny/exchange09.rb +106 -124
- data/lib/bunny/queue08.rb +216 -202
- data/lib/bunny/queue09.rb +256 -326
- data/lib/bunny/subscription08.rb +30 -29
- data/lib/bunny/subscription09.rb +84 -83
- data/lib/bunny/version.rb +5 -0
- data/lib/qrack/amq-client-url.rb +165 -0
- data/lib/qrack/channel.rb +19 -17
- data/lib/qrack/client.rb +152 -151
- data/lib/qrack/errors.rb +5 -0
- data/lib/qrack/protocol/protocol08.rb +132 -130
- data/lib/qrack/protocol/protocol09.rb +133 -131
- data/lib/qrack/protocol/spec08.rb +2 -0
- data/lib/qrack/protocol/spec09.rb +2 -0
- data/lib/qrack/qrack08.rb +7 -10
- data/lib/qrack/qrack09.rb +7 -10
- data/lib/qrack/queue.rb +27 -40
- data/lib/qrack/subscription.rb +102 -101
- data/lib/qrack/transport/buffer08.rb +266 -264
- data/lib/qrack/transport/buffer09.rb +268 -264
- data/lib/qrack/transport/frame08.rb +13 -11
- data/lib/qrack/transport/frame09.rb +9 -7
- data/spec/spec_08/bunny_spec.rb +48 -45
- data/spec/spec_08/connection_spec.rb +10 -7
- data/spec/spec_08/exchange_spec.rb +145 -143
- data/spec/spec_08/queue_spec.rb +161 -161
- data/spec/spec_09/bunny_spec.rb +46 -44
- data/spec/spec_09/connection_spec.rb +15 -8
- data/spec/spec_09/exchange_spec.rb +147 -145
- data/spec/spec_09/queue_spec.rb +182 -184
- metadata +60 -41
- data/README.rdoc +0 -66
data/lib/qrack/client.rb
CHANGED
@@ -1,166 +1,161 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "qrack/amq-client-url"
|
4
|
+
|
1
5
|
module Qrack
|
2
|
-
|
3
|
-
|
6
|
+
|
7
|
+
class ClientTimeout < Timeout::Error; end
|
4
8
|
class ConnectionTimeout < Timeout::Error; end
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
9
|
+
|
10
|
+
# Client ancestor class
|
11
|
+
class Client
|
12
|
+
|
13
|
+
CONNECT_TIMEOUT = 5.0
|
10
14
|
RETRY_DELAY = 10.0
|
11
15
|
|
12
16
|
attr_reader :status, :host, :vhost, :port, :logging, :spec, :heartbeat
|
13
|
-
attr_accessor :channel, :logfile, :exchanges, :queues, :channels, :message_in, :message_out,
|
14
|
-
|
17
|
+
attr_accessor :channel, :logfile, :exchanges, :queues, :channels, :message_in, :message_out, :connecting
|
18
|
+
|
15
19
|
|
16
|
-
|
17
|
-
|
20
|
+
def initialize(connection_string_or_opts = Hash.new, opts = Hash.new)
|
21
|
+
opts = case connection_string_or_opts
|
22
|
+
when String then
|
23
|
+
AMQ::Client::Settings.parse_amqp_url(connection_string_or_opts)
|
24
|
+
when Hash then
|
25
|
+
connection_string_or_opts
|
26
|
+
else
|
27
|
+
Hash.new
|
28
|
+
end.merge(opts)
|
29
|
+
|
30
|
+
@host = opts[:host] || 'localhost'
|
18
31
|
@user = opts[:user] || 'guest'
|
19
32
|
@pass = opts[:pass] || 'guest'
|
20
33
|
@vhost = opts[:vhost] || '/'
|
21
|
-
|
22
|
-
|
23
|
-
|
34
|
+
@logfile = opts[:logfile] || nil
|
35
|
+
@logging = opts[:logging] || false
|
36
|
+
@ssl = opts[:ssl] || false
|
24
37
|
@verify_ssl = opts[:verify_ssl].nil? || opts[:verify_ssl]
|
25
38
|
@status = :not_connected
|
26
|
-
|
27
|
-
|
28
|
-
|
39
|
+
@frame_max = opts[:frame_max] || 131072
|
40
|
+
@channel_max = opts[:channel_max] || 0
|
41
|
+
@heartbeat = opts[:heartbeat] || 0
|
29
42
|
@connect_timeout = opts[:connect_timeout] || CONNECT_TIMEOUT
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
43
|
+
@read_write_timeout = opts[:socket_timeout]
|
44
|
+
@read_write_timeout = nil if @read_write_timeout == 0
|
45
|
+
@disconnect_timeout = @read_write_timeout || @connect_timeout
|
46
|
+
@logger = nil
|
47
|
+
create_logger if @logging
|
48
|
+
@message_in = false
|
49
|
+
@message_out = false
|
50
|
+
@connecting = false
|
51
|
+
@channels ||= []
|
52
|
+
# Create channel 0
|
37
53
|
@channel = create_channel()
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
@logging = bool
|
86
|
-
create_logger if @logging
|
87
|
-
end
|
88
|
-
|
54
|
+
@exchanges ||= {}
|
55
|
+
@queues ||= {}
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
# Closes all active communication channels and connection. If an error occurs a @Bunny::ProtocolError@ is raised. If successful, @Client.status@ is set to @:not_connected@.
|
60
|
+
|
61
|
+
# @return [Symbol] @:not_connected@ if successful.
|
62
|
+
def close
|
63
|
+
return if @socket.nil? || @socket.closed?
|
64
|
+
|
65
|
+
# Close all active channels
|
66
|
+
channels.each do |c|
|
67
|
+
Bunny::Timer::timeout(@disconnect_timeout) { c.close } if c.open?
|
68
|
+
end
|
69
|
+
|
70
|
+
# Close connection to AMQP server
|
71
|
+
Bunny::Timer::timeout(@disconnect_timeout) { close_connection }
|
72
|
+
|
73
|
+
rescue Exception
|
74
|
+
# http://cheezburger.com/Asset/View/4033311488
|
75
|
+
ensure
|
76
|
+
# Clear the channels
|
77
|
+
@channels = []
|
78
|
+
|
79
|
+
# Create channel 0
|
80
|
+
@channel = create_channel()
|
81
|
+
|
82
|
+
# Close TCP Socket
|
83
|
+
close_socket
|
84
|
+
end
|
85
|
+
|
86
|
+
alias stop close
|
87
|
+
|
88
|
+
def connected?
|
89
|
+
status == :connected
|
90
|
+
end
|
91
|
+
|
92
|
+
def connecting?
|
93
|
+
connecting
|
94
|
+
end
|
95
|
+
|
96
|
+
def logging=(bool)
|
97
|
+
@logging = bool
|
98
|
+
create_logger if @logging
|
99
|
+
end
|
100
|
+
|
89
101
|
def next_payload(options = {})
|
90
|
-
next_frame(options)
|
102
|
+
res = next_frame(options)
|
103
|
+
res.payload if res
|
91
104
|
end
|
92
105
|
|
93
|
-
|
106
|
+
alias next_method next_payload
|
94
107
|
|
95
108
|
def read(*args)
|
96
|
-
|
97
|
-
send_command(:read, *args)
|
109
|
+
send_command(:read, *args)
|
98
110
|
# Got a SIGINT while waiting; give any traps a chance to run
|
99
|
-
|
100
|
-
|
111
|
+
rescue Errno::EINTR
|
112
|
+
retry
|
113
|
+
end
|
114
|
+
|
115
|
+
# Checks to see whether or not an undeliverable message has been returned as a result of a publish
|
116
|
+
# with the <tt>:immediate</tt> or <tt>:mandatory</tt> options.
|
117
|
+
|
118
|
+
# @param [Hash] opts Options.
|
119
|
+
# @option opts [Numeric] :timeout (0.1) The method will wait for a return message until this timeout interval is reached.
|
120
|
+
# @return [Hash] @{:header => nil, :payload => :no_return, :return_details => nil}@ if message is not returned before timeout. @{:header, :return_details, :payload}@ if message is returned. @:return_details@ is a hash @{:reply_code, :reply_text, :exchange, :routing_key}@.
|
121
|
+
def returned_message(opts = {})
|
122
|
+
|
123
|
+
begin
|
124
|
+
frame = next_frame(:timeout => opts[:timeout] || 0.1)
|
125
|
+
rescue Qrack::ClientTimeout
|
126
|
+
return {:header => nil, :payload => :no_return, :return_details => nil}
|
127
|
+
end
|
128
|
+
|
129
|
+
method = frame.payload
|
130
|
+
header = next_payload
|
131
|
+
|
132
|
+
# If maximum frame size is smaller than message payload body then message
|
133
|
+
# will have a message header and several message bodies
|
134
|
+
msg = ''
|
135
|
+
while msg.length < header.size
|
136
|
+
msg << next_payload
|
137
|
+
end
|
138
|
+
|
139
|
+
# Return the message and related info
|
140
|
+
{:header => header, :payload => msg, :return_details => method.arguments}
|
141
|
+
end
|
142
|
+
|
143
|
+
def switch_channel(chann)
|
144
|
+
if (0...channels.size).include? chann
|
145
|
+
@channel = channels[chann]
|
146
|
+
chann
|
147
|
+
else
|
148
|
+
raise RuntimeError, "Invalid channel number - #{chann}"
|
101
149
|
end
|
102
|
-
|
103
150
|
end
|
104
151
|
|
105
|
-
|
106
|
-
|
107
|
-
=== DESCRIPTION:
|
108
|
-
|
109
|
-
Checks to see whether or not an undeliverable message has been returned as a result of a publish
|
110
|
-
with the <tt>:immediate</tt> or <tt>:mandatory</tt> options.
|
111
|
-
|
112
|
-
==== OPTIONS:
|
113
|
-
|
114
|
-
* <tt>:timeout => number of seconds (default = 0.1) - The method will wait for a return
|
115
|
-
message until this timeout interval is reached.
|
116
|
-
|
117
|
-
==== RETURNS:
|
118
|
-
|
119
|
-
<tt>{:header => nil, :payload => :no_return, :return_details => nil}</tt> if message is
|
120
|
-
not returned before timeout.
|
121
|
-
<tt>{:header, :return_details, :payload}</tt> if message is returned. <tt>:return_details</tt> is
|
122
|
-
a hash <tt>{:reply_code, :reply_text, :exchange, :routing_key}</tt>.
|
123
|
-
|
124
|
-
=end
|
125
|
-
|
126
|
-
def returned_message(opts = {})
|
127
|
-
|
128
|
-
begin
|
129
|
-
frame = next_frame(:timeout => opts[:timeout] || 0.1)
|
130
|
-
rescue Qrack::ClientTimeout
|
131
|
-
return {:header => nil, :payload => :no_return, :return_details => nil}
|
132
|
-
end
|
133
|
-
|
134
|
-
method = frame.payload
|
135
|
-
header = next_payload
|
136
|
-
|
137
|
-
# If maximum frame size is smaller than message payload body then message
|
138
|
-
# will have a message header and several message bodies
|
139
|
-
msg = ''
|
140
|
-
while msg.length < header.size
|
141
|
-
msg += next_payload
|
142
|
-
end
|
143
|
-
|
144
|
-
# Return the message and related info
|
145
|
-
{:header => header, :payload => msg, :return_details => method.arguments}
|
146
|
-
end
|
147
|
-
|
148
|
-
def switch_channel(chann)
|
149
|
-
if (0...channels.size).include? chann
|
150
|
-
@channel = channels[chann]
|
151
|
-
chann
|
152
|
-
else
|
153
|
-
raise RuntimeError, "Invalid channel number - #{chann}"
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
def write(*args)
|
152
|
+
def write(*args)
|
158
153
|
send_command(:write, *args)
|
159
154
|
end
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
155
|
+
|
156
|
+
private
|
157
|
+
|
158
|
+
def close_socket(reason=nil)
|
164
159
|
# Close the socket. The server is not considered dead.
|
165
160
|
@socket.close if @socket and not @socket.closed?
|
166
161
|
@socket = nil
|
@@ -168,16 +163,22 @@ a hash <tt>{:reply_code, :reply_text, :exchange, :routing_key}</tt>.
|
|
168
163
|
end
|
169
164
|
|
170
165
|
def create_logger
|
171
|
-
|
172
|
-
|
173
|
-
|
166
|
+
@logfile ? @logger = Logger.new("#{logfile}") : @logger = Logger.new(STDOUT)
|
167
|
+
@logger.level = Logger::INFO
|
168
|
+
@logger.datetime_format = "%Y-%m-%d %H:%M:%S"
|
174
169
|
end
|
175
|
-
|
176
|
-
|
170
|
+
|
171
|
+
def send_command(cmd, *args)
|
177
172
|
begin
|
178
|
-
|
179
|
-
@
|
180
|
-
|
173
|
+
raise Bunny::ConnectionError, 'No connection - socket has not been created' if !@socket
|
174
|
+
if @read_write_timeout
|
175
|
+
Bunny::Timer::timeout(@read_write_timeout, Qrack::ClientTimeout) do
|
176
|
+
@socket.__send__(cmd, *args)
|
177
|
+
end
|
178
|
+
else
|
179
|
+
@socket.__send__(cmd, *args)
|
180
|
+
end
|
181
|
+
rescue Errno::EPIPE, Errno::EAGAIN, Qrack::ClientTimeout, IOError => e
|
181
182
|
# Ensure we close the socket when we are down to prevent further
|
182
183
|
# attempts to write to a closed socket
|
183
184
|
close_socket
|
@@ -190,7 +191,7 @@ a hash <tt>{:reply_code, :reply_text, :exchange, :routing_key}</tt>.
|
|
190
191
|
|
191
192
|
begin
|
192
193
|
# Attempt to connect.
|
193
|
-
@socket = timeout(@connect_timeout, ConnectionTimeout) do
|
194
|
+
@socket = Bunny::Timer::timeout(@connect_timeout, ConnectionTimeout) do
|
194
195
|
TCPSocket.new(host, port)
|
195
196
|
end
|
196
197
|
|
@@ -213,7 +214,7 @@ a hash <tt>{:reply_code, :reply_text, :exchange, :routing_key}</tt>.
|
|
213
214
|
|
214
215
|
@socket
|
215
216
|
end
|
216
|
-
|
217
|
-
|
218
|
-
|
217
|
+
|
218
|
+
end
|
219
|
+
|
219
220
|
end
|
data/lib/qrack/errors.rb
ADDED
@@ -1,132 +1,134 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
module Qrack
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
4
|
+
module Protocol
|
5
|
+
#:stopdoc:
|
6
|
+
class Class::Method
|
7
|
+
def initialize *args
|
8
|
+
opts = args.pop if args.last.is_a? Hash
|
9
|
+
opts ||= {}
|
10
|
+
|
11
|
+
if args.size == 1 and args.first.is_a? Transport::Buffer
|
12
|
+
buf = args.shift
|
13
|
+
else
|
14
|
+
buf = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
self.class.arguments.each do |type, name|
|
18
|
+
val = buf ? buf.read(type) :
|
19
|
+
args.shift || opts[name] || opts[name.to_s]
|
20
|
+
instance_variable_set("@#{name}", val)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def arguments
|
25
|
+
self.class.arguments.inject({}) do |hash, (type, name)|
|
26
|
+
hash.update name => instance_variable_get("@#{name}")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_binary
|
31
|
+
buf = Transport::Buffer.new
|
32
|
+
buf.write :short, self.class.parent.id
|
33
|
+
buf.write :short, self.class.id
|
34
|
+
|
35
|
+
bits = []
|
36
|
+
|
37
|
+
self.class.arguments.each do |type, name|
|
38
|
+
val = instance_variable_get("@#{name}")
|
39
|
+
if type == :bit
|
40
|
+
bits << (val || false)
|
41
|
+
else
|
42
|
+
unless bits.empty?
|
43
|
+
buf.write :bit, bits
|
44
|
+
bits = []
|
45
|
+
end
|
46
|
+
buf.write type, val
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
buf.write :bit, bits unless bits.empty?
|
51
|
+
buf.rewind
|
52
|
+
|
53
|
+
buf
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_s
|
57
|
+
to_binary.to_s
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_frame channel = 0
|
61
|
+
Transport::Method.new(self, channel)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class Header
|
66
|
+
def initialize *args
|
67
|
+
opts = args.pop if args.last.is_a? Hash
|
68
|
+
opts ||= {}
|
69
|
+
|
70
|
+
first = args.shift
|
71
|
+
|
72
|
+
if first.is_a? ::Class and first.ancestors.include? Protocol::Class
|
73
|
+
@klass = first
|
74
|
+
@size = args.shift || 0
|
75
|
+
@weight = args.shift || 0
|
76
|
+
@properties = opts
|
77
|
+
|
78
|
+
elsif first.is_a? Transport::Buffer or first.is_a? String
|
79
|
+
buf = first
|
80
|
+
buf = Transport::Buffer.new(buf) unless buf.is_a? Transport::Buffer
|
81
|
+
|
82
|
+
@klass = Protocol.classes[buf.read(:short)]
|
83
|
+
@weight = buf.read(:short)
|
84
|
+
@size = buf.read(:longlong)
|
85
|
+
|
86
|
+
props = buf.read(:properties, *klass.properties.map{|type,_| type })
|
87
|
+
@properties = Hash[*klass.properties.map{|_,name| name }.zip(props).reject{|k,v| v.nil? }.flatten]
|
88
|
+
|
89
|
+
else
|
90
|
+
raise ArgumentError, 'Invalid argument'
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
attr_accessor :klass, :size, :weight, :properties
|
95
|
+
|
96
|
+
def to_binary
|
97
|
+
buf = Transport::Buffer.new
|
98
|
+
buf.write :short, klass.id
|
99
|
+
buf.write :short, weight # XXX rabbitmq only supports weight == 0
|
100
|
+
buf.write :longlong, size
|
101
|
+
buf.write :properties, (klass.properties.map do |type, name|
|
102
|
+
[ type, properties[name] || properties[name.to_s] ]
|
103
|
+
end)
|
104
|
+
buf.rewind
|
105
|
+
buf
|
106
|
+
end
|
107
|
+
|
108
|
+
def to_s
|
109
|
+
to_binary.to_s
|
110
|
+
end
|
111
|
+
|
112
|
+
def to_frame channel = 0
|
113
|
+
Transport::Header.new(self, channel)
|
114
|
+
end
|
115
|
+
|
116
|
+
def == header
|
117
|
+
[ :klass, :size, :weight, :properties ].inject(true) do |eql, field|
|
118
|
+
eql and __send__(field) == header.__send__(field)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def method_missing meth, *args, &blk
|
123
|
+
@properties.has_key?(meth) || @klass.properties.find{|_,name| name == meth } ? @properties[meth] : super
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def self.parse buf
|
128
|
+
buf = Transport::Buffer.new(buf) unless buf.is_a? Transport::Buffer
|
129
|
+
class_id, method_id = buf.read(:short, :short)
|
130
|
+
classes[class_id].methods[method_id].new(buf)
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
132
134
|
end
|