stomp 1.2.0 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +9 -0
- data/examples/logexamp_ssl.rb +66 -0
- data/examples/slogger.rb +17 -1
- data/examples/ssl_uc1.rb +19 -0
- data/examples/ssl_uc1_ciphers.rb +30 -0
- data/examples/ssl_uc2.rb +30 -0
- data/examples/ssl_uc2_ciphers.rb +38 -0
- data/examples/ssl_uc3.rb +29 -0
- data/examples/ssl_uc3_ciphers.rb +37 -0
- data/examples/ssl_uc4.rb +29 -0
- data/examples/ssl_uc4_ciphers.rb +38 -0
- data/examples/ssl_ucx_default_ciphers.rb +25 -0
- data/lib/stomp/client.rb +2 -7
- data/lib/stomp/connection.rb +157 -87
- data/lib/stomp/constants.rb +3 -0
- data/lib/stomp/errors.rb +30 -0
- data/lib/stomp/message.rb +1 -1
- data/lib/stomp/sslparams.rb +50 -0
- data/lib/stomp/version.rb +1 -1
- data/lib/stomp.rb +2 -1
- data/stomp.gemspec +20 -7
- data/test/test_connection.rb +7 -0
- data/test/test_connection1p.rb +8 -0
- data/test/test_helper.rb +15 -0
- data/test/test_ssl.rb +51 -0
- metadata +67 -33
data/lib/stomp/connection.rb
CHANGED
@@ -21,7 +21,7 @@ module Stomp
|
|
21
21
|
def self.default_port(ssl)
|
22
22
|
ssl ? 61612 : 61613
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
# A new Connection object accepts the following parameters:
|
26
26
|
#
|
27
27
|
# login (String, default : '')
|
@@ -87,23 +87,24 @@ module Stomp
|
|
87
87
|
@parse_timeout = 5 # To override, use hashed parameters
|
88
88
|
@connect_timeout = 0 # To override, use hashed parameters
|
89
89
|
@logger = nil # To override, use hashed parameters
|
90
|
+
warn "login looks like a URL, do you have the correct parameters?" if @login =~ /:\/\//
|
90
91
|
end
|
91
|
-
|
92
|
+
|
92
93
|
# Use Mutexes: only one lock per each thread
|
93
94
|
# Revert to original implementation attempt
|
94
95
|
@transmit_semaphore = Mutex.new
|
95
96
|
@read_semaphore = Mutex.new
|
96
97
|
@socket_semaphore = Mutex.new
|
97
|
-
|
98
|
+
|
98
99
|
@subscriptions = {}
|
99
100
|
@failure = nil
|
100
101
|
@connection_attempts = 0
|
101
|
-
|
102
|
+
|
102
103
|
socket
|
103
104
|
end
|
104
|
-
|
105
|
+
|
105
106
|
def hashed_initialize(params)
|
106
|
-
|
107
|
+
|
107
108
|
@parameters = refine_params(params)
|
108
109
|
@reliable = @parameters[:reliable]
|
109
110
|
@reconnect_delay = @parameters[:initial_reconnect_delay]
|
@@ -113,11 +114,8 @@ module Stomp
|
|
113
114
|
@logger = @parameters[:logger]
|
114
115
|
#sets the first host to connect
|
115
116
|
change_host
|
116
|
-
if @logger && @logger.respond_to?(:on_connecting)
|
117
|
-
@logger.on_connecting(log_params)
|
118
|
-
end
|
119
117
|
end
|
120
|
-
|
118
|
+
|
121
119
|
# Syntactic sugar for 'Connection.new' See 'initialize' for usage.
|
122
120
|
def Connection.open(login = '', passcode = '', host = 'localhost', port = 61613, reliable = false, reconnect_delay = 5, connect_headers = {})
|
123
121
|
Connection.new(login, passcode, host, port, reliable, reconnect_delay, connect_headers)
|
@@ -127,33 +125,33 @@ module Stomp
|
|
127
125
|
@socket_semaphore.synchronize do
|
128
126
|
used_socket = @socket
|
129
127
|
used_socket = nil if closed?
|
130
|
-
|
128
|
+
|
131
129
|
while used_socket.nil? || !@failure.nil?
|
132
130
|
@failure = nil
|
133
131
|
begin
|
134
132
|
used_socket = open_socket
|
135
133
|
# Open complete
|
136
|
-
|
134
|
+
|
137
135
|
connect(used_socket)
|
138
136
|
if @logger && @logger.respond_to?(:on_connected)
|
139
|
-
@logger.on_connected(log_params)
|
137
|
+
@logger.on_connected(log_params)
|
140
138
|
end
|
141
139
|
@connection_attempts = 0
|
142
140
|
rescue
|
143
141
|
@failure = $!
|
144
142
|
used_socket = nil
|
145
143
|
raise unless @reliable
|
146
|
-
if @logger && @logger.respond_to?(:on_connectfail)
|
147
|
-
@logger.on_connectfail(log_params)
|
144
|
+
if @logger && @logger.respond_to?(:on_connectfail)
|
145
|
+
@logger.on_connectfail(log_params)
|
148
146
|
else
|
149
147
|
$stderr.print "connect to #{@host} failed: #{$!} will retry(##{@connection_attempts}) in #{@reconnect_delay}\n"
|
150
148
|
end
|
151
149
|
raise Stomp::Error::MaxReconnectAttempts if max_reconnect_attempts?
|
152
150
|
|
153
151
|
sleep(@reconnect_delay)
|
154
|
-
|
152
|
+
|
155
153
|
@connection_attempts += 1
|
156
|
-
|
154
|
+
|
157
155
|
if @parameters
|
158
156
|
change_host
|
159
157
|
increase_reconnect_delay
|
@@ -163,10 +161,10 @@ module Stomp
|
|
163
161
|
@socket = used_socket
|
164
162
|
end
|
165
163
|
end
|
166
|
-
|
164
|
+
|
167
165
|
def refine_params(params)
|
168
166
|
params = params.uncamelize_and_symbolize_keys
|
169
|
-
|
167
|
+
|
170
168
|
default_params = {
|
171
169
|
:connect_headers => {},
|
172
170
|
:reliable => true,
|
@@ -182,35 +180,35 @@ module Stomp
|
|
182
180
|
# Parse Timeout
|
183
181
|
:parse_timeout => 5
|
184
182
|
}
|
185
|
-
|
183
|
+
|
186
184
|
default_params.merge(params)
|
187
|
-
|
185
|
+
|
188
186
|
end
|
189
|
-
|
187
|
+
|
190
188
|
def change_host
|
191
189
|
@parameters[:hosts] = @parameters[:hosts].sort_by { rand } if @parameters[:randomize]
|
192
|
-
|
190
|
+
|
193
191
|
# Set first as master and send it to the end of array
|
194
192
|
current_host = @parameters[:hosts].shift
|
195
193
|
@parameters[:hosts] << current_host
|
196
|
-
|
194
|
+
|
197
195
|
@ssl = current_host[:ssl]
|
198
196
|
@host = current_host[:host]
|
199
197
|
@port = current_host[:port] || Connection::default_port(@ssl)
|
200
198
|
@login = current_host[:login] || ""
|
201
199
|
@passcode = current_host[:passcode] || ""
|
202
|
-
|
200
|
+
|
203
201
|
end
|
204
|
-
|
202
|
+
|
205
203
|
def max_reconnect_attempts?
|
206
204
|
!(@parameters.nil? || @parameters[:max_reconnect_attempts].nil?) && @parameters[:max_reconnect_attempts] != 0 && @connection_attempts >= @parameters[:max_reconnect_attempts]
|
207
205
|
end
|
208
|
-
|
206
|
+
|
209
207
|
def increase_reconnect_delay
|
210
208
|
|
211
|
-
@reconnect_delay *= @parameters[:back_off_multiplier] if @parameters[:use_exponential_back_off]
|
209
|
+
@reconnect_delay *= @parameters[:back_off_multiplier] if @parameters[:use_exponential_back_off]
|
212
210
|
@reconnect_delay = @parameters[:max_reconnect_delay] if @reconnect_delay > @parameters[:max_reconnect_delay]
|
213
|
-
|
211
|
+
|
214
212
|
@reconnect_delay
|
215
213
|
end
|
216
214
|
|
@@ -289,7 +287,7 @@ module Stomp
|
|
289
287
|
headers[:id] = subId if headers[:id].nil?
|
290
288
|
end
|
291
289
|
_headerCheck(headers)
|
292
|
-
if @logger && @logger.respond_to?(:on_subscribe)
|
290
|
+
if @logger && @logger.respond_to?(:on_subscribe)
|
293
291
|
@logger.on_subscribe(log_params, headers)
|
294
292
|
end
|
295
293
|
|
@@ -328,21 +326,16 @@ module Stomp
|
|
328
326
|
headers = headers.symbolize_keys
|
329
327
|
headers[:destination] = destination
|
330
328
|
_headerCheck(headers)
|
331
|
-
if @logger && @logger.respond_to?(:on_publish)
|
329
|
+
if @logger && @logger.respond_to?(:on_publish)
|
332
330
|
@logger.on_publish(log_params, message, headers)
|
333
331
|
end
|
334
332
|
transmit(Stomp::CMD_SEND, headers, message)
|
335
333
|
end
|
336
|
-
|
334
|
+
|
337
335
|
def obj_send(*args)
|
338
336
|
__send__(*args)
|
339
337
|
end
|
340
|
-
|
341
|
-
def send(*args)
|
342
|
-
warn("This method is deprecated and will be removed on the next release. Use 'publish' instead")
|
343
|
-
publish(*args)
|
344
|
-
end
|
345
|
-
|
338
|
+
|
346
339
|
# Send a message back to the source or to the dead letter queue
|
347
340
|
#
|
348
341
|
# Accepts a dead letter queue option ( :dead_letter_queue => "/queue/DLQ" )
|
@@ -353,19 +346,19 @@ module Stomp
|
|
353
346
|
options = { :dead_letter_queue => "/queue/DLQ", :max_redeliveries => 6 }.merge options
|
354
347
|
# Lets make sure all keys are symbols
|
355
348
|
message.headers = message.headers.symbolize_keys
|
356
|
-
|
349
|
+
|
357
350
|
retry_count = message.headers[:retry_count].to_i || 0
|
358
351
|
message.headers[:retry_count] = retry_count + 1
|
359
352
|
transaction_id = "transaction-#{message.headers[:'message-id']}-#{retry_count}"
|
360
353
|
message_id = message.headers.delete(:'message-id')
|
361
|
-
|
354
|
+
|
362
355
|
begin
|
363
356
|
self.begin transaction_id
|
364
|
-
|
357
|
+
|
365
358
|
if client_ack?(message) || options[:force_client_ack]
|
366
359
|
self.ack(message_id, :transaction => transaction_id)
|
367
360
|
end
|
368
|
-
|
361
|
+
|
369
362
|
if retry_count <= options[:max_redeliveries]
|
370
363
|
self.publish(message.headers[:destination], message.body, message.headers.merge(:transaction => transaction_id))
|
371
364
|
else
|
@@ -378,7 +371,7 @@ module Stomp
|
|
378
371
|
raise exception
|
379
372
|
end
|
380
373
|
end
|
381
|
-
|
374
|
+
|
382
375
|
def client_ack?(message)
|
383
376
|
headers = @subscriptions[message.headers[:destination]]
|
384
377
|
!headers.nil? && headers[:ack] == "client"
|
@@ -445,7 +438,7 @@ module Stomp
|
|
445
438
|
super_result = __old_receive
|
446
439
|
end
|
447
440
|
#
|
448
|
-
if @logger && @logger.respond_to?(:on_receive)
|
441
|
+
if @logger && @logger.respond_to?(:on_receive)
|
449
442
|
@logger.on_receive(log_params, super_result)
|
450
443
|
end
|
451
444
|
return super_result
|
@@ -481,7 +474,7 @@ module Stomp
|
|
481
474
|
b[6] = (b[6] & 0x0F) | 0x40
|
482
475
|
b[8] = (b[8] & 0xbf) | 0x80
|
483
476
|
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
484
|
-
rs = sprintf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x",
|
477
|
+
rs = sprintf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x",
|
485
478
|
b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15])
|
486
479
|
rs
|
487
480
|
end
|
@@ -490,31 +483,17 @@ module Stomp
|
|
490
483
|
|
491
484
|
def _receive( read_socket )
|
492
485
|
@read_semaphore.synchronize do
|
493
|
-
|
494
|
-
|
495
|
-
# heartbeat.
|
496
|
-
begin
|
497
|
-
last_char = read_socket.getc
|
498
|
-
return nil if last_char.nil?
|
499
|
-
if @protocol >= Stomp::SPL_11
|
500
|
-
plc = parse_char(last_char)
|
501
|
-
if plc == "\n" # Server Heartbeat
|
502
|
-
@lr = Time.now.to_f if @hbr
|
503
|
-
end
|
504
|
-
end
|
505
|
-
end until parse_char(last_char) != "\n"
|
506
|
-
read_socket.ungetc(last_char)
|
507
|
-
|
486
|
+
line = read_socket.gets
|
487
|
+
return nil if line.nil?
|
508
488
|
# If the reading hangs for more than X seconds, abort the parsing process.
|
509
489
|
# X defaults to 5. Override allowed in connection hash parameters.
|
510
490
|
Timeout::timeout(@parse_timeout, Stomp::Error::PacketParsingTimeout) do
|
511
491
|
# Reads the beginning of the message until it runs into a empty line
|
512
492
|
message_header = ''
|
513
|
-
line = ''
|
514
493
|
begin
|
515
|
-
message_header
|
494
|
+
message_header += line
|
516
495
|
line = read_socket.gets
|
517
|
-
|
496
|
+
raise Stomp::Error::StompServerError if line.nil?
|
518
497
|
end until line =~ /^\s?\n$/
|
519
498
|
|
520
499
|
# Checks if it includes content_length header
|
@@ -528,13 +507,34 @@ module Stomp
|
|
528
507
|
raise Stomp::Error::InvalidMessageLength unless parse_char(read_socket.getc) == "\0"
|
529
508
|
# Else reads, the rest of the message until the first \0
|
530
509
|
else
|
531
|
-
message_body
|
510
|
+
message_body += char while (char = parse_char(read_socket.getc)) != "\0"
|
532
511
|
end
|
533
512
|
|
513
|
+
# If the buffer isn't empty, reads trailing new lines.
|
514
|
+
#
|
515
|
+
# Note: experiments with JRuby seem to show that .ready? never
|
516
|
+
# returns true. This means that this code to drain trailing new
|
517
|
+
# lines never runs using JRuby.
|
518
|
+
#
|
519
|
+
# Note 2: the draining of new lines mmust be done _after_ a message
|
520
|
+
# is read. Do _not_ leave them on the wire and attempt to drain them
|
521
|
+
# at the start of the next read. Attempting to do that breaks the
|
522
|
+
# asynchronous nature of the 'poll' method.
|
523
|
+
while read_socket.ready?
|
524
|
+
last_char = read_socket.getc
|
525
|
+
break unless last_char
|
526
|
+
if parse_char(last_char) != "\n"
|
527
|
+
read_socket.ungetc(last_char)
|
528
|
+
break
|
529
|
+
end
|
530
|
+
end
|
531
|
+
# And so, a JRuby hack. Remove any new lines at the start of the
|
532
|
+
# next buffer.
|
533
|
+
message_header.gsub!(/^\n?/, "")
|
534
|
+
|
534
535
|
if @protocol >= Stomp::SPL_11
|
535
536
|
@lr = Time.now.to_f if @hbr
|
536
537
|
end
|
537
|
-
|
538
538
|
# Adds the excluded \n and \0 and tries to create a new message with it
|
539
539
|
msg = Message.new(message_header + "\n" + message_body + "\0", @protocol >= Stomp::SPL_11)
|
540
540
|
#
|
@@ -583,16 +583,16 @@ module Stomp
|
|
583
583
|
# Ruby 1.8: String#length => # of bytes; Ruby 1.9: String#length => # of characters
|
584
584
|
# With Unicode strings, # of bytes != # of characters. So, use String#bytesize when available.
|
585
585
|
body_length_bytes = body.respond_to?(:bytesize) ? body.bytesize : body.length
|
586
|
-
|
587
|
-
# ActiveMQ interprets every message as a BinaryMessage
|
588
|
-
# if content_length header is included.
|
586
|
+
|
587
|
+
# ActiveMQ interprets every message as a BinaryMessage
|
588
|
+
# if content_length header is included.
|
589
589
|
# Using :suppress_content_length => true will suppress this behaviour
|
590
590
|
# and ActiveMQ will interpret the message as a TextMessage.
|
591
591
|
# For more information refer to http://juretta.com/log/2009/05/24/activemq-jms-stomp/
|
592
592
|
# Lets send this header in the message, so it can maintain state when using unreceive
|
593
593
|
headers['content-length'] = "#{body_length_bytes}" unless headers[:suppress_content_length]
|
594
594
|
headers['content-type'] = "text/plain; charset=UTF-8" unless headers['content-type']
|
595
|
-
used_socket.puts command
|
595
|
+
used_socket.puts command
|
596
596
|
headers.each do |k,v|
|
597
597
|
if v.is_a?(Array)
|
598
598
|
v.each do |e|
|
@@ -612,9 +612,14 @@ module Stomp
|
|
612
612
|
|
613
613
|
end
|
614
614
|
end
|
615
|
-
|
615
|
+
|
616
616
|
def open_tcp_socket
|
617
617
|
tcp_socket = nil
|
618
|
+
|
619
|
+
if @logger && @logger.respond_to?(:on_connecting)
|
620
|
+
@logger.on_connecting(log_params)
|
621
|
+
end
|
622
|
+
|
618
623
|
Timeout::timeout(@connect_timeout, Stomp::Error::SocketOpenTimeout) do
|
619
624
|
tcp_socket = TCPSocket.open @host, @port
|
620
625
|
end
|
@@ -625,20 +630,72 @@ module Stomp
|
|
625
630
|
def open_ssl_socket
|
626
631
|
require 'openssl' unless defined?(OpenSSL)
|
627
632
|
ctx = OpenSSL::SSL::SSLContext.new
|
633
|
+
ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE # Assume for now
|
634
|
+
#
|
635
|
+
# Note: if a client uses :ssl => true this results in the gem using
|
636
|
+
# the _default_ Ruby ciphers list. This is _known_ to fail in later
|
637
|
+
# Ruby releases. The gem provides a default cipher list that may
|
638
|
+
# function in these cases. To use this connect with:
|
639
|
+
# * :ssl => Stomp::SSLParams.new
|
640
|
+
# * :ssl => Stomp::SSLParams.new(..., :ciphers => Stomp::DEFAULT_CIPHERS)
|
641
|
+
#
|
642
|
+
# If connecting with an SSLParams instance, and the _default_ Ruby
|
643
|
+
# ciphers list is required, use:
|
644
|
+
# * :ssl => Stomp::SSLParams.new(..., :use_ruby_ciphers => true)
|
645
|
+
#
|
646
|
+
# If a custom ciphers list is required, connect with:
|
647
|
+
# * :ssl => Stomp::SSLParams.new(..., :ciphers => custom_ciphers_list)
|
648
|
+
#
|
649
|
+
if @ssl != true
|
650
|
+
#
|
651
|
+
# Here @ssl is:
|
652
|
+
# * an instance of Stomp::SSLParams
|
653
|
+
# Control would not be here if @ssl == false or @ssl.nil?.
|
654
|
+
#
|
628
655
|
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
656
|
+
# Back reference the SSLContext
|
657
|
+
@ssl.ctx = ctx
|
658
|
+
|
659
|
+
# Server authentication parameters if required
|
660
|
+
if @ssl.ts_files
|
661
|
+
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
662
|
+
truststores = OpenSSL::X509::Store.new
|
663
|
+
fl = @ssl.ts_files.split(",")
|
664
|
+
fl.each do |fn|
|
665
|
+
# Add next cert file listed
|
666
|
+
raise Stomp::Error::SSLNoTruststoreFileError if !File::exists?(fn)
|
667
|
+
truststores.add_file(fn)
|
668
|
+
end
|
669
|
+
ctx.cert_store = truststores
|
670
|
+
end
|
671
|
+
|
672
|
+
# Client authentication parameters
|
673
|
+
# Both cert file and key file must be present or not, it can not be a mix
|
674
|
+
raise Stomp::Error::SSLClientParamsError if @ssl.cert_file.nil? && !@ssl.key_file.nil?
|
675
|
+
raise Stomp::Error::SSLClientParamsError if !@ssl.cert_file.nil? && @ssl.key_file.nil?
|
676
|
+
if @ssl.cert_file # Any check will do here
|
677
|
+
raise Stomp::Error::SSLNoCertFileError if !File::exists?(@ssl.cert_file)
|
678
|
+
ctx.cert = OpenSSL::X509::Certificate.new(File.open(@ssl.cert_file))
|
679
|
+
raise Stomp::Error::SSLNoKeyFileError if !File::exists?(@ssl.key_file)
|
680
|
+
ctx.key = OpenSSL::PKey::RSA.new(File.open(@ssl.key_file))
|
681
|
+
end
|
682
|
+
|
683
|
+
# Cipher list
|
684
|
+
if !@ssl.use_ruby_ciphers # No Ruby ciphers (the default)
|
685
|
+
if @ssl.ciphers # User ciphers list?
|
686
|
+
ctx.ciphers = @ssl.ciphers # Accept user supplied ciphers
|
687
|
+
else
|
688
|
+
ctx.ciphers = Stomp::DEFAULT_CIPHERS # Just use Stomp defaults
|
689
|
+
end
|
690
|
+
end
|
691
|
+
end
|
633
692
|
|
634
|
-
#
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
693
|
+
#
|
694
|
+
ssl = nil
|
695
|
+
if @logger && @logger.respond_to?(:on_ssl_connecting)
|
696
|
+
@logger.on_ssl_connecting(log_params)
|
697
|
+
end
|
639
698
|
|
640
|
-
ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
641
|
-
ssl = nil
|
642
699
|
Timeout::timeout(@connect_timeout, Stomp::Error::SocketOpenTimeout) do
|
643
700
|
ssl = OpenSSL::SSL::SSLSocket.new(open_tcp_socket, ctx)
|
644
701
|
end
|
@@ -646,6 +703,18 @@ module Stomp
|
|
646
703
|
! @rbuffer.empty? || @io.ready?
|
647
704
|
end
|
648
705
|
ssl.connect
|
706
|
+
if @ssl != true
|
707
|
+
# Pass back results if possible
|
708
|
+
if RUBY_VERSION =~ /1\.8\.[56]/
|
709
|
+
@ssl.verify_result = "N/A for Ruby #{RUBY_VERSION}"
|
710
|
+
else
|
711
|
+
@ssl.verify_result = ssl.verify_result
|
712
|
+
end
|
713
|
+
@ssl.peer_cert = ssl.peer_cert
|
714
|
+
end
|
715
|
+
if @logger && @logger.respond_to?(:on_ssl_connected)
|
716
|
+
@logger.on_ssl_connected(log_params)
|
717
|
+
end
|
649
718
|
ssl
|
650
719
|
end
|
651
720
|
|
@@ -667,13 +736,13 @@ module Stomp
|
|
667
736
|
used_socket = @ssl ? open_ssl_socket : open_tcp_socket
|
668
737
|
# try to close the old connection if any
|
669
738
|
close_socket
|
670
|
-
|
739
|
+
|
671
740
|
@closed = false
|
672
741
|
# Use keepalive
|
673
742
|
used_socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true)
|
674
743
|
used_socket
|
675
744
|
end
|
676
|
-
|
745
|
+
|
677
746
|
def connect(used_socket)
|
678
747
|
@connect_headers = {} unless @connect_headers # Caller said nil/false
|
679
748
|
headers = @connect_headers.clone
|
@@ -817,7 +886,7 @@ module Stomp
|
|
817
886
|
@hb_sent = false # Set the warning flag
|
818
887
|
if @logger && @logger.respond_to?(:on_hbwrite_fail)
|
819
888
|
@logger.on_hbwrite_fail(log_params, {"ticker_interval" => @sti,
|
820
|
-
"exception" => sendex})
|
889
|
+
"exception" => sendex})
|
821
890
|
end
|
822
891
|
raise # Re-raise. What else could be done here?
|
823
892
|
end
|
@@ -858,7 +927,7 @@ module Stomp
|
|
858
927
|
# Shrug. Have not received one. Just set warning flag.
|
859
928
|
@hb_received = false
|
860
929
|
if @logger && @logger.respond_to?(:on_hbread_fail)
|
861
|
-
@logger.on_hbread_fail(log_params, {"ticker_interval" => @rti})
|
930
|
+
@logger.on_hbread_fail(log_params, {"ticker_interval" => @rti})
|
862
931
|
end
|
863
932
|
end
|
864
933
|
else
|
@@ -904,7 +973,7 @@ module Stomp
|
|
904
973
|
# * handles all occurrences of valid single byte characters i.e., the ASCII character set
|
905
974
|
# * provides state transition logic for start bytes of valid characters with 2-4 bytes
|
906
975
|
# * signals a validation failure for all other single bytes
|
907
|
-
#
|
976
|
+
#
|
908
977
|
when "start"
|
909
978
|
# puts "state: start" if DEBUG
|
910
979
|
case next_byte
|
@@ -1095,7 +1164,8 @@ module Stomp
|
|
1095
1164
|
raise Stomp::Error::UTF8ValidationError unless valid_utf8?(e)
|
1096
1165
|
end
|
1097
1166
|
else
|
1098
|
-
vs = v.to_s # Values are usually Strings, but could be TrueClass or Symbol
|
1167
|
+
vs = v.to_s + "" # Values are usually Strings, but could be TrueClass or Symbol
|
1168
|
+
# The + "" forces an 'unfreeze' if necessary
|
1099
1169
|
vs.force_encoding(Stomp::UTF8) if vs.respond_to?(:force_encoding)
|
1100
1170
|
raise Stomp::Error::UTF8ValidationError unless valid_utf8?(vs)
|
1101
1171
|
end
|
data/lib/stomp/constants.rb
CHANGED
@@ -75,4 +75,7 @@ module Stomp
|
|
75
75
|
"\\c", ":",
|
76
76
|
]
|
77
77
|
|
78
|
+
DEFAULT_CIPHERS = [["DHE-RSA-AES256-SHA", "TLSv1/SSLv3", 256, 256], ["DHE-DSS-AES256-SHA", "TLSv1/SSLv3", 256, 256], ["AES256-SHA", "TLSv1/SSLv3", 256, 256], ["EDH-RSA-DES-CBC3-SHA", "TLSv1/SSLv3", 168, 168], ["EDH-DSS-DES-CBC3-SHA", "TLSv1/SSLv3", 168, 168], ["DES-CBC3-SHA", "TLSv1/SSLv3", 168, 168], ["DHE-RSA-AES128-SHA", "TLSv1/SSLv3", 128, 128], ["DHE-DSS-AES128-SHA", "TLSv1/SSLv3", 128, 128], ["AES128-SHA", "TLSv1/SSLv3", 128, 128], ["RC4-SHA", "TLSv1/SSLv3", 128, 128], ["RC4-MD5", "TLSv1/SSLv3", 128, 128], ["EDH-RSA-DES-CBC-SHA", "TLSv1/SSLv3", 56, 56], ["EDH-DSS-DES-CBC-SHA", "TLSv1/SSLv3", 56, 56],
|
79
|
+
["DES-CBC-SHA", "TLSv1/SSLv3", 56, 56], ["EXP-EDH-RSA-DES-CBC-SHA", "TLSv1/SSLv3", 40, 56], ["EXP-EDH-DSS-DES-CBC-SHA", "TLSv1/SSLv3", 40, 56], ["EXP-DES-CBC-SHA", "TLSv1/SSLv3", 40, 56], ["EXP-RC2-CBC-MD5", "TLSv1/SSLv3", 40, 128], ["EXP-RC4-MD5", "TLSv1/SSLv3", 40, 128]]
|
80
|
+
|
78
81
|
end
|
data/lib/stomp/errors.rb
CHANGED
@@ -86,6 +86,36 @@ module Stomp
|
|
86
86
|
end
|
87
87
|
end
|
88
88
|
|
89
|
+
class SSLClientParamsError < RuntimeError
|
90
|
+
def message
|
91
|
+
"certificate and key files are both required"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
class StompServerError < RuntimeError
|
96
|
+
def message
|
97
|
+
"Connected, header read is nil, is this really a Stomp Server?"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class SSLNoKeyFileError < RuntimeError
|
102
|
+
def message
|
103
|
+
"client key file does not exist"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
class SSLNoCertFileError < RuntimeError
|
108
|
+
def message
|
109
|
+
"client cert file does not exist"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
class SSLNoTruststoreFileError < RuntimeError
|
114
|
+
def message
|
115
|
+
"a client truststore file does not exist"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
89
119
|
end # module Error
|
90
120
|
end # module Stomp
|
91
121
|
|
data/lib/stomp/message.rb
CHANGED
@@ -6,7 +6,7 @@ module Stomp
|
|
6
6
|
class Message
|
7
7
|
attr_accessor :command, :headers, :body, :original
|
8
8
|
|
9
|
-
@@allowed_commands = [
|
9
|
+
@@allowed_commands = [ Stomp::CMD_CONNECTED, Stomp::CMD_MESSAGE, Stomp::CMD_RECEIPT, Stomp::CMD_ERROR ]
|
10
10
|
|
11
11
|
def initialize(frame, protocol11p = false)
|
12
12
|
# p [ "00", frame, frame.encoding ]
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Stomp
|
4
|
+
#
|
5
|
+
# == Purpose
|
6
|
+
#
|
7
|
+
# Parameters for STOMP ssl connections.
|
8
|
+
#
|
9
|
+
class SSLParams
|
10
|
+
# The trust store files. Normally the certificate of the CA that signed
|
11
|
+
# the server's certificate. One file name, or a CSV list of file names.
|
12
|
+
attr_accessor :ts_files
|
13
|
+
# The client certificate file.
|
14
|
+
attr_accessor :cert_file
|
15
|
+
# The client private key file.
|
16
|
+
attr_accessor :key_file
|
17
|
+
# SSL Connect Verify Result. The result of the handshake.
|
18
|
+
attr_accessor :verify_result
|
19
|
+
# The certificate of the connection peer (the server), received during
|
20
|
+
# the handshake.
|
21
|
+
attr_accessor :peer_cert
|
22
|
+
# Optional list of SSL ciphers to be used. In the format documented for
|
23
|
+
# Ruby's OpenSSL.
|
24
|
+
attr_accessor :ciphers
|
25
|
+
# Abcolute command to use Ruby default ciphers
|
26
|
+
attr_reader :use_ruby_ciphers
|
27
|
+
# Back reference to the OpenSSL::SSL::SSLContext instance, gem sets before connect
|
28
|
+
attr_accessor :ctx # Set by the gem during connect, before the callbacks
|
29
|
+
#
|
30
|
+
def initialize(opts={})
|
31
|
+
|
32
|
+
# Server authentication parameters
|
33
|
+
@ts_files = opts[:ts_files] # A trust store file, normally a CA's cert
|
34
|
+
# or a CSV list of cert file names
|
35
|
+
|
36
|
+
# Client authentication parameters
|
37
|
+
@cert_file = opts[:cert_file] # Client cert
|
38
|
+
@key_file = opts[:key_file] # Client key
|
39
|
+
#
|
40
|
+
raise Stomp::Error::SSLClientParamsError if @cert_file.nil? && !@key_file.nil?
|
41
|
+
raise Stomp::Error::SSLClientParamsError if !@cert_file.nil? && @key_file.nil?
|
42
|
+
#
|
43
|
+
@ciphers = opts[:ciphers]
|
44
|
+
@use_ruby_ciphers = opts[:use_ruby_ciphers] ? opts[:use_ruby_ciphers] : false
|
45
|
+
#
|
46
|
+
end
|
47
|
+
end # of class SSLParams
|
48
|
+
|
49
|
+
end # of module Stomp
|
50
|
+
|
data/lib/stomp/version.rb
CHANGED
data/lib/stomp.rb
CHANGED
@@ -15,14 +15,15 @@
|
|
15
15
|
# See the License for the specific language governing permissions and
|
16
16
|
# limitations under the License.
|
17
17
|
|
18
|
+
require 'stomp/constants' # Constants first
|
18
19
|
require 'stomp/ext/hash'
|
19
20
|
require 'stomp/connection'
|
20
21
|
require 'stomp/client'
|
21
22
|
require 'stomp/message'
|
22
23
|
require 'stomp/version'
|
23
24
|
require 'stomp/errors'
|
24
|
-
require 'stomp/constants'
|
25
25
|
require 'stomp/codec'
|
26
|
+
require 'stomp/sslparams'
|
26
27
|
|
27
28
|
module Stomp
|
28
29
|
end
|