stomp 1.3.5 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
-