stomp 1.3.5 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -9,59 +9,83 @@ module Stomp
9
9
 
10
10
  class Connection
11
11
 
12
- private
13
-
14
- # Really read from the wire.
15
- def _receive(read_socket, connread = false)
16
- @read_semaphore.synchronize do
17
- line = nil
18
- if connread
19
- begin
20
- Timeout::timeout(@connread_timeout, Stomp::Error::ConnectReadTimeout) do
21
- line = _init_line_read(read_socket)
22
- end
23
- rescue Stomp::Error::ConnectReadTimeout => ex
24
- if @reliable
25
- _reconn_prep()
12
+ private
13
+
14
+ # Really read from the wire.
15
+ def _receive(read_socket, connread = false)
16
+ # p [ "ioscheck", @iosto, connread ]
17
+ # _dump_callstack()
18
+ # drdbg = true
19
+ drdbg = false
20
+ @read_semaphore.synchronize do
21
+ line = nil
22
+ if connread
23
+ begin
24
+ Timeout::timeout(@connread_timeout, Stomp::Error::ConnectReadTimeout) do
25
+ line = _init_line_read(read_socket)
26
+ end
27
+ rescue Stomp::Error::ConnectReadTimeout => ex
28
+ if @reliable
29
+ _reconn_prep()
30
+ end
31
+ raise ex
26
32
  end
27
- raise ex
33
+ else
34
+ p [ "CONR01" ] if drdbg
35
+ _dump_callstack() if drdbg
36
+ line = _init_line_read(read_socket)
28
37
  end
29
- else
30
- line = _init_line_read(read_socket)
31
- end
32
- #
33
- return nil if line.nil?
34
- #An extra \n at the beginning of the frame, possibly not caught by is_ready?
35
- line = '' if line == "\n"
36
- # p [ "wiredatain_01", line ]
37
- line = _normalize_line_end(line) if @protocol >= Stomp::SPL_12
38
- # If the reading hangs for more than X seconds, abort the parsing process.
39
- # X defaults to 5. Override allowed in connection hash parameters.
40
- Timeout::timeout(@parse_timeout, Stomp::Error::PacketParsingTimeout) do
38
+ #
39
+ p [ "nilcheck", line.nil? ] if drdbg
40
+ return nil if line.nil?
41
+ #An extra \n at the beginning of the frame, possibly not caught by is_ready?
42
+ line = '' if line == "\n"
43
+ p [ "wiredatain_01A", line, Time.now ] if drdbg
44
+ line = _normalize_line_end(line) if @protocol >= Stomp::SPL_12
45
+ p [ "wiredatain_01B", line, Time.now ] if drdbg
41
46
  # Reads the beginning of the message until it runs into a empty line
42
47
  message_header = ''
43
48
  begin
44
49
  message_header += line
50
+ p [ "wiredatain_02A", line, Time.now ] if drdbg
51
+ unless connread
52
+ raise Stomp::Error::ReceiveTimeout unless IO.select([read_socket], nil, nil, @iosto)
53
+ end
54
+ p [ "wiredatain_02B", line, Time.now ] if drdbg
45
55
  line = read_socket.gets
46
- # p [ "wiredatain_02", line ]
47
- raise Stomp::Error::StompServerError if line.nil?
56
+ p [ "wiredatain_02C", line ] if drdbg
57
+ raise if line.nil?
48
58
  line = _normalize_line_end(line) if @protocol >= Stomp::SPL_12
59
+ p [ "wiredatain_02D", line ] if drdbg
49
60
  end until line =~ /^\s?\n$/
50
-
61
+ p [ "wiredatain_03A" ] if drdbg
51
62
  # Checks if it includes content_length header
52
- content_length = message_header.match /content-length\s?:\s?(\d+)\s?\n/
63
+ content_length = message_header.match(/content-length\s?:\s?(\d+)\s?\n/)
53
64
  message_body = ''
54
65
 
66
+ p [ "wiredatain_03B", content_length ] if drdbg
55
67
  # If content_length is present, read the specified amount of bytes
56
68
  if content_length
69
+ unless connread
70
+ raise Stomp::Error::ReceiveTimeout unless IO.select([read_socket], nil, nil, @iosto)
71
+ end
72
+ p [ "CL01" ] if drdbg
57
73
  message_body = read_socket.read content_length[1].to_i
74
+ unless connread
75
+ raise Stomp::Error::ReceiveTimeout unless IO.select([read_socket], nil, nil, @iosto)
76
+ end
58
77
  raise Stomp::Error::InvalidMessageLength unless parse_char(read_socket.getc) == "\0"
59
78
  # Else read the rest of the message until the first \0
60
79
  else
80
+ unless connread
81
+ raise Stomp::Error::ReceiveTimeout unless IO.select([read_socket], nil, nil, @iosto)
82
+ end
83
+ p [ "NOCL01" ] if drdbg
61
84
  message_body = read_socket.readline("\0")
62
85
  message_body.chop!
63
86
  end
64
87
 
88
+ p [ "wiredatain_04" ] if drdbg
65
89
  # If the buffer isn't empty, reads trailing new lines.
66
90
  #
67
91
  # Note: experiments with JRuby seem to show that socket.ready? never
@@ -73,7 +97,12 @@ module Stomp
73
97
  # is read. Do _not_ leave them on the wire and attempt to drain them
74
98
  # at the start of the next read. Attempting to do that breaks the
75
99
  # asynchronous nature of the 'poll' method.
100
+ p [ "wiredatain_05_prep", "isr", _is_ready?(read_socket) ] if drdbg
76
101
  while _is_ready?(read_socket)
102
+ unless connread
103
+ raise Stomp::Error::ReceiveTimeout unless IO.select([read_socket], nil, nil, @iosto)
104
+ end
105
+ p [ "WHIR01" ] if drdbg
77
106
  last_char = read_socket.getc
78
107
  break unless last_char
79
108
  if parse_char(last_char) != "\n"
@@ -81,337 +110,383 @@ module Stomp
81
110
  break
82
111
  end
83
112
  end
84
-
113
+ p [ "wiredatain_05A" ] if drdbg
85
114
  if @protocol >= Stomp::SPL_11
86
115
  @lr = Time.now.to_f if @hbr
87
116
  end
88
117
  # Adds the excluded \n and \0 and tries to create a new message with it
118
+ p [ "wiredatain_05B" ] if drdbg
89
119
  msg = Message.new(message_header + "\n" + message_body + "\0", @protocol >= Stomp::SPL_11)
120
+ p [ "wiredatain_06", msg.command, msg.headers ] if drdbg
90
121
  #
91
122
  if @protocol >= Stomp::SPL_11 && msg.command != Stomp::CMD_CONNECTED
92
123
  msg.headers = _decodeHeaders(msg.headers)
93
124
  end
125
+ p [ "wiredatain_99", msg.command, msg.headers ] if drdbg
94
126
  msg
95
127
  end
96
128
  end
97
- end
98
129
 
99
- # Check if the socket is ready, i.e. there is data to read.
100
- def _is_ready?(s)
101
- rdy = s.ready?
102
- if @jruby
103
- rdy = rdy.class == Fixnum ? true : false
104
- end
105
- rdy
106
- end
107
-
108
- # Normalize line ends because 1.2+ brokers can send 'mixed mode' headers, i.e.:
109
- # - Some headers end with '\n'
110
- # - Other headers end with '\r\n'
111
- def _normalize_line_end(line)
112
- return line unless @usecrlf
113
- # p [ "nleln", line ]
114
- line_len = line.respond_to?(:bytesize) ? line.bytesize : line.length
115
- last2 = line[line_len-2...line_len]
116
- # p [ "nlel2", last2 ]
117
- return line unless last2 == "\r\n"
118
- return line[0...line_len-2] + "\n"
119
- end
120
-
121
- # transmit logically puts a Message on the wire.
122
- def transmit(command, headers = {}, body = '')
123
- # The transmit may fail so we may need to retry.
124
- while TRUE
125
- begin
126
- used_socket = socket()
127
- _transmit(used_socket, command, headers, body)
128
- return
129
- rescue Stomp::Error::MaxReconnectAttempts => e
130
- raise
131
- rescue
132
- @failure = $!
133
- raise unless @reliable
134
- errstr = "transmit to #{@host} failed: #{$!}\n"
135
- unless slog(:on_miscerr, log_params, "es_trans: " + errstr)
136
- $stderr.print errstr
137
- end
138
- # !!! This loop initiates a re-connect !!!
139
- _reconn_prep()
130
+ #
131
+ # This is a total hack, to try and guess how JRuby will behave today.
132
+ #
133
+ def _is_ready?(s)
134
+ rdy = s.ready?
135
+ ### p [ "isr?", rdy ]
136
+ return rdy unless @jruby
137
+ ### p [ "jrdychk", rdy.class ]
138
+ if rdy.class == NilClass
139
+ # rdy = true
140
+ rdy = false # A test
141
+ else
142
+ rdy = (rdy.class == Fixnum || rdy.class == TrueClass) ? true : false
140
143
  end
144
+ ### p [ "isr?_last", rdy ]
145
+ rdy
141
146
  end
142
- end
143
147
 
144
- # _transmit is the real wire write logic.
145
- def _transmit(used_socket, command, headers = {}, body = '')
146
- if @protocol >= Stomp::SPL_11 && command != Stomp::CMD_CONNECT
147
- headers = _encodeHeaders(headers)
148
+
149
+ # Normalize line ends because 1.2+ brokers can send 'mixed mode' headers, i.e.:
150
+ # - Some headers end with '\n'
151
+ # - Other headers end with '\r\n'
152
+ def _normalize_line_end(line)
153
+ return line unless @usecrlf
154
+ # p [ "nleln", line ]
155
+ line_len = line.respond_to?(:bytesize) ? line.bytesize : line.length
156
+ last2 = line[line_len-2...line_len]
157
+ # p [ "nlel2", last2 ]
158
+ return line unless last2 == "\r\n"
159
+ return line[0...line_len-2] + "\n"
148
160
  end
149
- @transmit_semaphore.synchronize do
150
- # Handle nil body
151
- body = '' if body.nil?
152
- # The content-length should be expressed in bytes.
153
- # Ruby 1.8: String#length => # of bytes; Ruby 1.9: String#length => # of characters
154
- # With Unicode strings, # of bytes != # of characters. So, use String#bytesize when available.
155
- body_length_bytes = body.respond_to?(:bytesize) ? body.bytesize : body.length
156
-
157
- # ActiveMQ interprets every message as a BinaryMessage
158
- # if content_length header is included.
159
- # Using :suppress_content_length => true will suppress this behaviour
160
- # and ActiveMQ will interpret the message as a TextMessage.
161
- # For more information refer to http://juretta.com/log/2009/05/24/activemq-jms-stomp/
162
- # Lets send this header in the message, so it can maintain state when using unreceive
163
- headers[:'content-length'] = "#{body_length_bytes}" unless headers[:suppress_content_length]
164
- headers[:'content-type'] = "text/plain; charset=UTF-8" unless headers[:'content-type']
165
- _wire_write(used_socket,command)
166
- headers.each do |k,v|
167
- if v.is_a?(Array)
168
- v.each do |e|
169
- _wire_write(used_socket,"#{k}:#{e}")
161
+
162
+ # transmit logically puts a Message on the wire.
163
+ def transmit(command, headers = {}, body = '')
164
+ # The transmit may fail so we may need to retry.
165
+ while TRUE
166
+ begin
167
+ used_socket = socket()
168
+ _transmit(used_socket, command, headers, body)
169
+ return
170
+ rescue Stomp::Error::MaxReconnectAttempts => e
171
+ _ = e
172
+ raise
173
+ rescue
174
+ @failure = $!
175
+ raise unless @reliable
176
+ errstr = "transmit to #{@host} failed: #{$!}\n"
177
+ unless slog(:on_miscerr, log_params, "es_trans: " + errstr)
178
+ $stderr.print errstr
170
179
  end
171
- else
172
- _wire_write(used_socket,"#{k}:#{v}")
180
+ # !!! This loop initiates a re-connect !!!
181
+ _reconn_prep()
173
182
  end
174
183
  end
175
- _wire_write(used_socket,"")
176
- used_socket.write body unless body == ''
177
- used_socket.write "\0"
178
- used_socket.flush if autoflush
184
+ end
179
185
 
180
- if @protocol >= Stomp::SPL_11
181
- @ls = Time.now.to_f if @hbs
186
+ # _transmit is the real wire write logic.
187
+ def _transmit(used_socket, command, headers = {}, body = '')
188
+
189
+ # p [ "wirewrite" ]
190
+ # _dump_callstack()
191
+
192
+ if @protocol >= Stomp::SPL_11 && command != Stomp::CMD_CONNECT
193
+ headers = _encodeHeaders(headers)
182
194
  end
195
+ @transmit_semaphore.synchronize do
196
+ # Handle nil body
197
+ body = '' if body.nil?
198
+ # The content-length should be expressed in bytes.
199
+ # Ruby 1.8: String#length => # of bytes; Ruby 1.9: String#length => # of characters
200
+ # With Unicode strings, # of bytes != # of characters. So, use String#bytesize when available.
201
+ body_length_bytes = body.respond_to?(:bytesize) ? body.bytesize : body.length
202
+
203
+ # ActiveMQ interprets every message as a BinaryMessage
204
+ # if content_length header is included.
205
+ # Using :suppress_content_length => true will suppress this behaviour
206
+ # and ActiveMQ will interpret the message as a TextMessage.
207
+ # For more information refer to http://juretta.com/log/2009/05/24/activemq-jms-stomp/
208
+ # Lets send this header in the message, so it can maintain state when using unreceive
209
+ headers[:'content-length'] = "#{body_length_bytes}" unless headers[:suppress_content_length]
210
+ headers[:'content-type'] = "text/plain; charset=UTF-8" unless headers[:'content-type']
211
+ _wire_write(used_socket,command)
212
+ headers.each do |k,v|
213
+ if v.is_a?(Array)
214
+ v.each do |e|
215
+ _wire_write(used_socket,"#{k}:#{e}")
216
+ end
217
+ else
218
+ _wire_write(used_socket,"#{k}:#{v}")
219
+ end
220
+ end
221
+ _wire_write(used_socket,"")
222
+ used_socket.write body unless body == ''
223
+ used_socket.write "\0"
224
+ used_socket.flush if autoflush
225
+
226
+ if @protocol >= Stomp::SPL_11
227
+ @ls = Time.now.to_f if @hbs
228
+ end
183
229
 
230
+ end
184
231
  end
185
- end
186
-
187
- # Use CRLF if protocol is >= 1.2, and the client requested CRLF
188
- def _wire_write(sock, data)
189
- # p [ "debug_01", @protocol, @usecrlf ]
190
- if @protocol >= Stomp::SPL_12 && @usecrlf
191
- wiredata = "#{data}#{Stomp::CR}#{Stomp::LF}"
192
- # p [ "wiredataout_01:", wiredata ]
193
- sock.write(wiredata)
194
- else
195
- # p [ "wiredataout_02:", "#{data}\n" ]
196
- sock.puts data
232
+
233
+ # Use CRLF if protocol is >= 1.2, and the client requested CRLF
234
+ def _wire_write(sock, data)
235
+ # p [ "debug_01", @protocol, @usecrlf ]
236
+ if @protocol >= Stomp::SPL_12 && @usecrlf
237
+ wiredata = "#{data}#{Stomp::CR}#{Stomp::LF}"
238
+ # p [ "wiredataout_01:", wiredata ]
239
+ sock.write(wiredata)
240
+ else
241
+ # p [ "wiredataout_02:", "#{data}\n" ]
242
+ sock.puts data
243
+ end
197
244
  end
198
- end
199
-
200
- # open_tcp_socket opens a TCP socket.
201
- def open_tcp_socket()
202
- tcp_socket = nil
203
- slog(:on_connecting, log_params)
204
- Timeout::timeout(@connect_timeout, Stomp::Error::SocketOpenTimeout) do
205
- tcp_socket = TCPSocket.open(@host, @port)
245
+
246
+ # open_tcp_socket opens a TCP socket.
247
+ def open_tcp_socket()
248
+
249
+ ## $stderr.print("h: #{@host}, p: #{@port}\n")
250
+
251
+ tcp_socket = nil
252
+ slog(:on_connecting, log_params)
253
+ Timeout::timeout(@connect_timeout, Stomp::Error::SocketOpenTimeout) do
254
+ tcp_socket = TCPSocket.open(@host, @port)
255
+ end
256
+ tcp_socket
206
257
  end
207
- tcp_socket
208
- end
209
-
210
- # open_ssl_socket opens an SSL socket.
211
- def open_ssl_socket()
212
- require 'openssl' unless defined?(OpenSSL)
213
- begin # Any raised SSL exceptions
214
- ctx = @sslctx_newparm ? OpenSSL::SSL::SSLContext.new(@sslctx_newparm) : OpenSSL::SSL::SSLContext.new
215
- ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE # Assume for now
216
- #
217
- # Note: if a client uses :ssl => true this would result in the gem using
218
- # the _default_ Ruby ciphers list. This is _known_ to fail in later
219
- # Ruby releases. The gem now detects :ssl => true, and replaces that
220
- # with:
221
- # * :ssl => Stomp::SSLParams.new
222
- #
223
- # The above results in the use of Stomp default parameters.
224
- #
225
- # To specifically request Stomp default parameters, use:
226
- # * :ssl => Stomp::SSLParams.new(..., :ciphers => Stomp::DEFAULT_CIPHERS)
227
- #
228
- # If connecting with an SSLParams instance, and the _default_ Ruby
229
- # ciphers list is actually required, use:
230
- # * :ssl => Stomp::SSLParams.new(..., :use_ruby_ciphers => true)
231
- #
232
- # If a custom ciphers list is required, connect with:
233
- # * :ssl => Stomp::SSLParams.new(..., :ciphers => custom_ciphers_list)
234
- #
235
- if @ssl != true
258
+
259
+ # open_ssl_socket opens an SSL socket.
260
+ def open_ssl_socket()
261
+ require 'openssl' unless defined?(OpenSSL)
262
+ begin # Any raised SSL exceptions
263
+ ctx = @sslctx_newparm ? OpenSSL::SSL::SSLContext.new(@sslctx_newparm) : OpenSSL::SSL::SSLContext.new
264
+ ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE # Assume for now
236
265
  #
237
- # Here @ssl is:
238
- # * an instance of Stomp::SSLParams
239
- # Control would not be here if @ssl == false or @ssl.nil?.
266
+ # Note: if a client uses :ssl => true this would result in the gem using
267
+ # the _default_ Ruby ciphers list. This is _known_ to fail in later
268
+ # Ruby releases. The gem now detects :ssl => true, and replaces that
269
+ # with:
270
+ # * :ssl => Stomp::SSLParams.new
240
271
  #
272
+ # The above results in the use of Stomp default parameters.
273
+ #
274
+ # To specifically request Stomp default parameters, use:
275
+ # * :ssl => Stomp::SSLParams.new(..., :ciphers => Stomp::DEFAULT_CIPHERS)
276
+ #
277
+ # If connecting with an SSLParams instance, and the _default_ Ruby
278
+ # ciphers list is actually required, use:
279
+ # * :ssl => Stomp::SSLParams.new(..., :use_ruby_ciphers => true)
280
+ #
281
+ # If a custom ciphers list is required, connect with:
282
+ # * :ssl => Stomp::SSLParams.new(..., :ciphers => custom_ciphers_list)
283
+ #
284
+ if @ssl != true
285
+ #
286
+ # Here @ssl is:
287
+ # * an instance of Stomp::SSLParams
288
+ # Control would not be here if @ssl == false or @ssl.nil?.
289
+ #
290
+
291
+ # Back reference the SSLContext
292
+ @ssl.ctx = ctx
293
+
294
+ # Server authentication parameters if required
295
+ if @ssl.ts_files
296
+ ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
297
+ truststores = OpenSSL::X509::Store.new
298
+ fl = @ssl.ts_files.split(",")
299
+ fl.each do |fn|
300
+ # Add next cert file listed
301
+ raise Stomp::Error::SSLNoTruststoreFileError if !File::exists?(fn)
302
+ raise Stomp::Error::SSLUnreadableTruststoreFileError if !File::readable?(fn)
303
+ truststores.add_file(fn)
304
+ end
305
+ ctx.cert_store = truststores
306
+ end
241
307
 
242
- # Back reference the SSLContext
243
- @ssl.ctx = ctx
244
-
245
- # Server authentication parameters if required
246
- if @ssl.ts_files
247
- ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
248
- truststores = OpenSSL::X509::Store.new
249
- fl = @ssl.ts_files.split(",")
250
- fl.each do |fn|
251
- # Add next cert file listed
252
- raise Stomp::Error::SSLNoTruststoreFileError if !File::exists?(fn)
253
- raise Stomp::Error::SSLUnreadableTruststoreFileError if !File::readable?(fn)
254
- truststores.add_file(fn)
308
+ # Client authentication parameters.
309
+ # Both cert file and key file must be present or not, it can not be a mix.
310
+ raise Stomp::Error::SSLClientParamsError if @ssl.cert_file.nil? && !@ssl.key_file.nil?
311
+ raise Stomp::Error::SSLClientParamsError if !@ssl.cert_file.nil? && @ssl.key_file.nil?
312
+ if @ssl.cert_file # Any check will do here
313
+ raise Stomp::Error::SSLNoCertFileError if !File::exists?(@ssl.cert_file)
314
+ raise Stomp::Error::SSLUnreadableCertFileError if !File::readable?(@ssl.cert_file)
315
+ ctx.cert = OpenSSL::X509::Certificate.new(File.read(@ssl.cert_file))
316
+ raise Stomp::Error::SSLNoKeyFileError if !File::exists?(@ssl.key_file)
317
+ raise Stomp::Error::SSLUnreadableKeyFileError if !File::readable?(@ssl.key_file)
318
+ ctx.key = OpenSSL::PKey::RSA.new(File.read(@ssl.key_file), @ssl.key_password)
319
+ end
320
+
321
+ # Cipher list
322
+ # As of this writing, there are numerous problems with supplying
323
+ # cipher lists to jruby. So we do not attempt to do that here.
324
+ if !@ssl.use_ruby_ciphers # No Ruby ciphers (the default)
325
+ if @ssl.ciphers # User ciphers list?
326
+ ctx.ciphers = @ssl.ciphers # Accept user supplied ciphers
327
+ else
328
+ ctx.ciphers = Stomp::DEFAULT_CIPHERS # Just use Stomp defaults
329
+ end
330
+ end unless @jruby
331
+
332
+ # Set SSLContext Options if user asks for it in Stomp::SSLParams
333
+ # and SSL supports it.
334
+ if @ssl.ssl_ctxopts && ctx.respond_to?(:options=)
335
+ ctx.options = @ssl.ssl_ctxopts
255
336
  end
256
- ctx.cert_store = truststores
257
- end
258
337
 
259
- # Client authentication parameters.
260
- # Both cert file and key file must be present or not, it can not be a mix.
261
- raise Stomp::Error::SSLClientParamsError if @ssl.cert_file.nil? && !@ssl.key_file.nil?
262
- raise Stomp::Error::SSLClientParamsError if !@ssl.cert_file.nil? && @ssl.key_file.nil?
263
- if @ssl.cert_file # Any check will do here
264
- raise Stomp::Error::SSLNoCertFileError if !File::exists?(@ssl.cert_file)
265
- raise Stomp::Error::SSLUnreadableCertFileError if !File::readable?(@ssl.cert_file)
266
- ctx.cert = OpenSSL::X509::Certificate.new(File.read(@ssl.cert_file))
267
- raise Stomp::Error::SSLNoKeyFileError if !File::exists?(@ssl.key_file)
268
- raise Stomp::Error::SSLUnreadableKeyFileError if !File::readable?(@ssl.key_file)
269
- ctx.key = OpenSSL::PKey::RSA.new(File.read(@ssl.key_file), @ssl.key_password)
270
338
  end
271
339
 
272
- # Cipher list
273
- if !@ssl.use_ruby_ciphers # No Ruby ciphers (the default)
274
- if @ssl.ciphers # User ciphers list?
275
- ctx.ciphers = @ssl.ciphers # Accept user supplied ciphers
340
+ #
341
+ ssl = nil
342
+ slog(:on_ssl_connecting, log_params)
343
+ # _dump_ctx(ctx)
344
+ Timeout::timeout(@connect_timeout, Stomp::Error::SocketOpenTimeout) do
345
+ tcp_socket = TCPSocket.open(@host, @port)
346
+ ssl = OpenSSL::SSL::SSLSocket.new(tcp_socket, ctx)
347
+ ssl.hostname = @host if ssl.respond_to? :hostname=
348
+ ssl.sync_close = true # Sync ssl close with underlying TCP socket
349
+ ssl.connect
350
+ end
351
+ def ssl.ready?
352
+ ! @rbuffer.empty? || @io.ready?
353
+ end
354
+ if @ssl != true
355
+ # Pass back results if possible
356
+ if RUBY_VERSION =~ /1\.8\.[56]/
357
+ @ssl.verify_result = "N/A for Ruby #{RUBY_VERSION}"
276
358
  else
277
- ctx.ciphers = Stomp::DEFAULT_CIPHERS # Just use Stomp defaults
359
+ @ssl.verify_result = ssl.verify_result
278
360
  end
361
+ @ssl.peer_cert = ssl.peer_cert
279
362
  end
280
-
281
- # Set SSLContext Options if user asks for it in Stomp::SSLParams
282
- # and SSL supports it.
283
- if @ssl.ssl_ctxopts && ctx.respond_to?(:options=)
284
- ctx.options = @ssl.ssl_ctxopts
363
+ slog(:on_ssl_connected, log_params)
364
+ ssl
365
+ rescue Exception => ex
366
+ lp = log_params.clone
367
+ lp[:ssl_exception] = ex
368
+ slog(:on_ssl_connectfail, lp)
369
+ if ssl
370
+ # shut down the TCP socket - we just failed to do the SSL handshake in time
371
+ ssl.close
285
372
  end
286
-
373
+ #
374
+ puts ex.backtrace
375
+ $sdtout.flush
376
+ raise # Reraise
287
377
  end
378
+ end
288
379
 
289
- #
290
- ssl = nil
291
- slog(:on_ssl_connecting, log_params)
292
- # _dump_ctx(ctx)
293
- Timeout::timeout(@connect_timeout, Stomp::Error::SocketOpenTimeout) do
294
- tcp_socket = TCPSocket.open(@host, @port)
295
- ssl = OpenSSL::SSL::SSLSocket.new(tcp_socket, ctx)
296
- ssl.hostname = @host if ssl.respond_to? :hostname=
297
- ssl.sync_close = true # Sync ssl close with underlying TCP socket
298
- ssl.connect
299
- end
300
- def ssl.ready?
301
- ! @rbuffer.empty? || @io.ready?
302
- end
303
- if @ssl != true
304
- # Pass back results if possible
305
- if RUBY_VERSION =~ /1\.8\.[56]/
306
- @ssl.verify_result = "N/A for Ruby #{RUBY_VERSION}"
307
- else
308
- @ssl.verify_result = ssl.verify_result
380
+ # close_socket closes the current open socket, and hence the connection.
381
+ def close_socket()
382
+ begin
383
+ # Need to set @closed = true before closing the socket
384
+ # within the @read_semaphore thread
385
+ @closed = true
386
+ @read_semaphore.synchronize do
387
+ @socket.close
309
388
  end
310
- @ssl.peer_cert = ssl.peer_cert
311
- end
312
- slog(:on_ssl_connected, log_params)
313
- ssl
314
- rescue Exception => ex
315
- lp = log_params.clone
316
- lp[:ssl_exception] = ex
317
- slog(:on_ssl_connectfail, lp)
318
- if ssl
319
- # shut down the TCP socket - we just failed to do the SSL handshake in time
320
- ssl.close
389
+ rescue
390
+ #Ignoring if already closed
321
391
  end
322
- #
323
- raise # Reraise
392
+ @closed
324
393
  end
325
- end
326
-
327
- # close_socket closes the current open socket, and hence the connection.
328
- def close_socket()
329
- begin
330
- # Need to set @closed = true before closing the socket
331
- # within the @read_semaphore thread
332
- @closed = true
333
- @read_semaphore.synchronize do
334
- @socket.close
394
+
395
+ # open_socket opens a TCP or SSL soclet as required.
396
+ def open_socket()
397
+ used_socket = @ssl ? open_ssl_socket : open_tcp_socket
398
+ # try to close the old connection if any
399
+ close_socket
400
+
401
+ @closed = false
402
+ if @parameters # nil in some rspec tests
403
+ unless @reconnect_delay
404
+ @reconnect_delay = @parameters[:initial_reconnect_delay] || iosto1
405
+ end
335
406
  end
336
- rescue
337
- #Ignoring if already closed
407
+ # Use keepalive
408
+ used_socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true)
409
+
410
+ # TCP_NODELAY option (disables Nagle's algorithm)
411
+ used_socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, !!(@parameters && @parameters[:tcp_nodelay]))
412
+
413
+ @iosto = @parse_timeout ? @parse_timeout.to_f : 0.0
414
+
415
+ used_socket
338
416
  end
339
- @closed
340
- end
341
-
342
- # open_socket opens a TCP or SSL soclet as required.
343
- def open_socket()
344
- used_socket = @ssl ? open_ssl_socket : open_tcp_socket
345
- # try to close the old connection if any
346
- close_socket
347
-
348
- @closed = false
349
- if @parameters # nil in some rspec tests
350
- unless @reconnect_delay
351
- @reconnect_delay = @parameters[:initial_reconnect_delay] || 0.01
417
+
418
+ # connect performs a basic STOMP CONNECT operation.
419
+ def connect(used_socket)
420
+ @connect_headers = {} unless @connect_headers # Caller said nil/false
421
+ headers = @connect_headers.clone
422
+ headers[:login] = @login unless @login.to_s.empty?
423
+ headers[:passcode] = @passcode unless @login.to_s.empty?
424
+ _pre_connect
425
+ if !@hhas10 && @stompconn
426
+ _transmit(used_socket, Stomp::CMD_STOMP, headers)
427
+ else
428
+ _transmit(used_socket, Stomp::CMD_CONNECT, headers)
352
429
  end
430
+ @connection_frame = _receive(used_socket, true)
431
+ _post_connect
432
+ @disconnect_receipt = nil
433
+ @session = @connection_frame.headers["session"] if @connection_frame
434
+ # replay any subscriptions.
435
+ @subscriptions.each {|k,v|
436
+ _transmit(used_socket, Stomp::CMD_SUBSCRIBE, v)
437
+ }
353
438
  end
354
- # Use keepalive
355
- used_socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true)
356
-
357
- # TCP_NODELAY option (disables Nagle's algorithm)
358
- used_socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, !!(@parameters && @parameters[:tcp_nodelay]))
359
-
360
- used_socket
361
- end
362
-
363
- # connect performs a basic STOMP CONNECT operation.
364
- def connect(used_socket)
365
- @connect_headers = {} unless @connect_headers # Caller said nil/false
366
- headers = @connect_headers.clone
367
- headers[:login] = @login unless @login.to_s.empty?
368
- headers[:passcode] = @passcode unless @login.to_s.empty?
369
- _pre_connect
370
- if !@hhas10 && @stompconn
371
- _transmit(used_socket, Stomp::CMD_STOMP, headers)
372
- else
373
- _transmit(used_socket, Stomp::CMD_CONNECT, headers)
374
- end
375
- @connection_frame = _receive(used_socket, true)
376
- _post_connect
377
- @disconnect_receipt = nil
378
- @session = @connection_frame.headers["session"] if @connection_frame
379
- # replay any subscriptions.
380
- @subscriptions.each {|k,v|
381
- _transmit(used_socket, Stomp::CMD_SUBSCRIBE, v)
382
- }
383
- end
384
-
385
- def _init_line_read(read_socket)
386
- line = ''
387
- if @protocol == Stomp::SPL_10 || (@protocol >= Stomp::SPL_11 && !@hbr)
388
- if @jruby
389
- # Handle JRuby specific behavior.
439
+
440
+ def _init_line_read(read_socket)
441
+ line = ''
442
+ if @protocol == Stomp::SPL_10 || (@protocol >= Stomp::SPL_11 && !@hbr)
443
+ if @jruby
444
+ # Handle JRuby specific behavior.
445
+ ### p [ "ilrjr00", _is_ready?(read_socket), RUBY_VERSION ]
446
+ if RUBY_VERSION < "2"
447
+ while true
448
+ ### p [ "ilrjr01A1", _is_ready?(read_socket) ]
449
+ line = read_socket.gets # Data from wire
450
+ break unless line == "\n"
451
+ line = ''
452
+ end
453
+ else # RUBY_VERSION >= "2"
454
+ while _is_ready?(read_socket)
455
+ ### p [ "ilrjr01B2", _is_ready?(read_socket) ]
456
+ line = read_socket.gets # Data from wire
457
+ break unless line == "\n"
458
+ line = ''
459
+ end
460
+ end
461
+ else
462
+ line = read_socket.gets # The old way
463
+ end
464
+ else # We are >= 1.1 *AND* receiving heartbeats.
390
465
  while true
391
466
  line = read_socket.gets # Data from wire
392
467
  break unless line == "\n"
393
468
  line = ''
469
+ @lr = Time.now.to_f
394
470
  end
395
- else
396
- line = read_socket.gets # The old way
397
- end
398
- else # We are >= 1.1 *AND* receiving heartbeats.
399
- while true
400
- line = read_socket.gets # Data from wire
401
- break unless line == "\n"
402
- line = ''
403
- @lr = Time.now.to_f
404
471
  end
472
+ line
473
+ end
474
+
475
+ # Used for debugging
476
+ def _dump_ctx(ctx)
477
+ p [ "dc01", ctx.inspect ]
478
+ p [ "dc02ciphers", ctx.ciphers ]
479
+ end
480
+
481
+ # used for debugging
482
+ def _dump_callstack()
483
+ i = 0
484
+ caller.each do |c|
485
+ p [ "csn", i, c ]
486
+ i += 1
405
487
  end
406
- line
407
- end
408
-
409
- # Used for debugging
410
- def _dump_ctx(ctx)
411
- p [ "dc01", ctx.inspect ]
412
- p [ "dc02ciphers", ctx.ciphers ]
413
- end
488
+ end # _dump_callstack
489
+
414
490
  end # class Connection
415
491
 
416
492
  end # module Stomp
417
-