GithubHelp home page GithubHelp logo

stompgem / stomp Goto Github PK

View Code? Open in Web Editor NEW

This project forked from zmalltalker/stomp

152.0 10.0 80.0 984 KB

A ruby gem for sending and receiving messages from a Stomp protocol compliant message queue. Includes: failover logic, ssl support.

Home Page: http://stomp.github.com

License: Apache License 2.0

Ruby 99.03% Shell 0.97%

stomp's Introduction

README

Overview

An implementation of the Stomp protocol for Ruby. See:

Hash Login Example Usage (this is the recommended login technique):

hash = {
  hosts: [
    # First connect is to remotehost1
    { login: 'login1', passcode: 'passcode1', host: 'remotehost1', port: 61_612, ssl: true },
    # First failover connect is to remotehost2
    { login: 'login2', passcode: 'passcode2', host: 'remotehost2', port: 61_613, ssl: false }
  ],
  # These are the default parameters and do not need to be set
  reliable: true,                  # reliable (use failover)
  initial_reconnect_delay: 0.01,   # initial delay before reconnect (secs)
  max_reconnect_delay: 30.0,       # max delay before reconnect
  use_exponential_back_off: true,  # increase delay between reconnect attpempts
  back_off_multiplier: 2,          # next delay multiplier
  max_reconnect_attempts: 0,       # retry forever, use # for maximum attempts
  randomize: false,                # do not radomize hosts hash before reconnect
  connect_timeout: 0,              # Timeout for TCP/TLS connects, use # for max seconds
  connect_headers: {},             # user supplied CONNECT headers (req'd for Stomp 1.1+)
  parse_timeout: 5,                # IO::select wait time on socket reads
  logger: nil,                     # user suplied callback logger instance
  dmh: false,                      # do not support multihomed IPV4 / IPV6 hosts during failover
  closed_check: true,              # check first if closed in each protocol method
  hbser: false,                    # raise on heartbeat send exception
  stompconn: false,                # Use STOMP instead of CONNECT
  usecrlf: false,                  # Use CRLF command and header line ends (1.2+)
  max_hbread_fails: 0,             # Max HB read fails before retry.  0 => never retry
  max_hbrlck_fails: 0,             # Max HB read lock obtain fails before retry.  0 => never retry
  fast_hbs_adjust: 0.0,            # Fast heartbeat senders sleep adjustment, seconds, needed ...
  # For fast heartbeat senders.  'fast' == YMMV.  If not
  # correct for your environment, expect unnecessary fail overs
  connread_timeout: 0,             # Timeout during CONNECT for read of CONNECTED/ERROR, secs
  tcp_nodelay: true,               # Turns on the TCP_NODELAY socket option; disables Nagle's algorithm
  start_timeout: 0,                # Timeout around Stomp::Client initialization
  sslctx_newparm: nil,             # Param for SSLContext.new
  ssl_post_conn_check: true,       # Further verify broker identity
  nto_cmd_read: true,              # No timeout on COMMAND read
}

# for a client
client = Stomp::Client.new(hash)

# for a connection
connection = Stomp::Connection.new(hash)

Positional Parameter Usage:

client = Stomp::Client.new("user", "pass", "localhost", 61613)
client.publish("/queue/mine", "hello world!")
client.subscribe("/queue/mine") do |msg|
    p msg
end

Stomp URL Usage:

A Stomp URL must begin with stomp:// and can be in one of the following forms:

stomp://host:port
stomp://host.domain.tld:port
stomp://login:passcode@host:port
stomp://login:[email protected]:port

# e.g. c = Stomp::Client.new(urlstring)

Failover + SSL Example URL Usage:

options = 'initialReconnectDelay=5000&randomize=false&useExponentialBackOff=false'
# remotehost1 uses SSL, remotehost2 doesn't
client = Stomp::Client.new("failover:(stomp+ssl://login1:passcode1@remotehost1:61612,stomp://login2:passcode2@remotehost2:61613)?#{options}")
client.publish('/queue/mine', 'hello world!')
client.subscribe('/queue/mine') do |msg|
  p msg
end

New:

See CHANGELOG.rdoc for details.

  • Gem version 1.4.9. Fix two issues, enhance debugging and examples.
  • Gem version 1.4.8. Fix missed merge in 1.4.7 release.
  • Gem version 1.4.7. Add support for text SSL certs. Do not use, use 1.4.8 instead.
  • Gem version 1.4.6. Fix version 1.4.5 which breaks JRuby support.
  • Gem version 1.4.5. JRuby broken here. Use is not recommended.
  • Gem version 1.4.4. Miscellaneous fixes, see CHANGELOG.md for details.
  • Gem version 1.4.3. Fix broken install. Do not try to install 1.4.2.
  • Gem version 1.4.2. Fix memory leak, and others !: see CHANGELOG.md for details.
  • Gem version 1.4.1. Important SSL changes !: see CHANGELOG.md for details.
  • Gem version 1.4.0. Note: Change sementics of :parse_timeout, see CHANGELOG.md for details.
  • Gem version 1.3.5. Miscellaneous fixes, see CHANGELOG.md for details.

For changes in older versions see CHANGELOG.rdoc for details.

Historical Information:

Up until March 2009 the project was maintained and primarily developed by Brian McCallister.

Source Code and Project URLs:

Source Code and Project

Stomp Protocol Information:

Protocol Information

Contributors

See CONTRIBUTORS.md.

stomp's People

Contributors

2potatocakes avatar chirino avatar chrisn avatar glennr avatar gmallard avatar grempe avatar ismith avatar jphastings avatar js avatar kiall avatar krsibbald avatar merichar avatar michaelklishin avatar morellon avatar neilw avatar oraziocw avatar psharpnumerex avatar raducu-deaconu-visma avatar reidmv avatar richardc avatar ripienaar avatar rrosenblum avatar shortcut-kinder avatar smitp avatar thbishop avatar thiagoxvo avatar tommay avatar tonyg avatar traylenator avatar waynerobinson avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

stomp's Issues

Automatic reconnection works only once (except for Apache Apollo)

  1. I was testing out the automatic reconnection feature which should kick in if the client cannot connect to the broker.
  2. With a simple consumer like this:
require 'bundler/setup'
require 'stomp'
require 'json'
require 'pp'

hash = { :hosts => 
  [
   { :login => "admin",
     :passcode => "password",
     :host => 'localhost', 
     :port => 61613 
   }
  ],
}

client = Stomp::Client.new(hash)

# subscribe
client.subscribe("/queue/foo") do |message|
  if message.headers["content-type"] =~ /json/
    pp JSON.parse(message.body)
  else
    pp message.body
  end
end
Kernel.trap(:INT) {
  client.close
  puts "Recieved term, stopping..."
  exit 0
}
loop do
  sleep(1)
  puts "."
end

I ran the test by shutting down the broker while the consumer was running and then subsequently bringing it back up.

  1. For RabbitMQ (2.8.6.1) and ActiveMQ (5.7.0) on Mac OS X 10.8.2 and CentOS 6.3, automatic reconnection works only once. That is, the consumer reconnects the first time I bounce the broker but not on subsequent restarts.
  2. Surprisingly, automatic reconnection seems to work flawlessly with Apache Apollo (1.4) on Mac OS X 10.8.2.

Need friendly wrong-service message

If (like me) you're new to ActiveMQ and Stomp, and don't actually have Stomp configured, and try to connect to an ActiveMQ port, the error message is totally unrelated to the actual issue.

irb(main):009:0> client = Stomp::Client.new "stomp://localhost:8161"
TypeError: can't convert nil into String

Instead, the error returned should probably be something like "This is not a Stomp server".

How to test if connection is currently failing?

Hello,

I'm needing to implement some logic to occur when our stomp client is unable to connect to our message server.

I was trying to use client.open?. This returned true just fine, but when I killed my message server to test the failure condition, it continued to report true, even though 'on_connectfail' log messages were being logged.

After checking out the socket method in connection.rb, It looks like I might be able to check @connection_attempts > 0 but was wondering if there is a better way, or if maybe I'm going about this all wrong...

Thanks!

reconnect delays not always honoured

If I make a deliberate mistake here - not specifying :"accept-version" header - the reconnect delays and backoffs arent honoured:

class Logger
  def on_connectfail(params=nil)
      puts "%s: failed to connect: %s" % [Time.now.to_i,  params[:cur_host]]
  end
end

connection = {:hosts => [ {:login => "rip", :passcode => "secret", :host => "stomp", :port => 6163} ],
              :initial_reconnect_delay => 0.1,
              :max_reconnect_delay => 30,
              :use_exponential_back_off => true,
              :back_off_multiplier => 2,
              :max_reconnect_attempts => 10,
              :logger => Logger.new,
              :connect_headers => {:host => "test"}}

@connection = Stomp::Connection.open(connection)

p @connection.connection_frame
% ruby test.rb
1368198528: failed to connect: stomp
1368198528: failed to connect: stomp
1368198528: failed to connect: stomp
1368198528: failed to connect: stomp
1368198528: failed to connect: stomp
1368198528: failed to connect: stomp
1368198528: failed to connect: stomp
1368198528: failed to connect: stomp
1368198529: failed to connect: stomp
1368198529: failed to connect: stomp
1368198529: failed to connect: stomp
/home/rip/.gem/gems/stomp-1.2.9/lib/connection/utils.rb:138:in `socket': Maximum number of reconnection attempts reached (Stomp::Error::MaxReconnectAttempts)

you can see there is no backoff of anything here

so the settings are for reconnections, but I think this should also apply in the initial connetion setup?

EL5 *** buffer overflow detected ***: /usr/bin/ruby terminated

On Red Hat Enterprise Linux 5.7 the installation of stomp-1.2.0 terminates. Older versions do work (1.1.10).

The error:

[root@host~]# gem install stomp-1.2.0.gem
*** buffer overflow detected ***: /usr/bin/ruby terminated
======= Backtrace: =========
/lib64/libc.so.6(__chk_fail+0x2f)[0x33edae807f]
/usr/lib64/ruby/1.8/x86_64-linux/syck.so(rb_syck_mktime+0x48e)[0x2b33a61f2c7e]
/usr/lib64/ruby/1.8/x86_64-linux/syck.so(yaml_org_handler+0x860)[0x2b33a61f3590]
/usr/lib64/ruby/1.8/x86_64-linux/syck.so(syck_defaultresolver_node_import+0x39)[0x2b33a61f3799]
/usr/lib64/libruby.so.1.8[0x3183a3492e]
/usr/lib64/libruby.so.1.8[0x3183a34e48]
/usr/lib64/libruby.so.1.8[0x3183a353f2]
/usr/lib64/libruby.so.1.8(rb_funcall+0x85)[0x3183a356c5]
/usr/lib64/ruby/1.8/x86_64-linux/syck.so(rb_syck_load_handler+0x47)[0x2b33a61f2727]
/usr/lib64/ruby/1.8/x86_64-linux/syck.so(syck_hdlr_add_node+0x39)[0x2b33a61ee4f9]
/usr/lib64/ruby/1.8/x86_64-linux/syck.so(syckparse+0xb45)[0x2b33a61e81f5]
/usr/lib64/ruby/1.8/x86_64-linux/syck.so(syck_parse+0x19)[0x2b33a61ecc19]
/usr/lib64/ruby/1.8/x86_64-linux/syck.so(syck_parser_load+0xed)[0x2b33a61f259d]
/usr/lib64/libruby.so.1.8[0x3183a3492e]
/usr/lib64/libruby.so.1.8[0x3183a34e48]
/usr/lib64/libruby.so.1.8[0x3183a3bbc6]
/usr/lib64/libruby.so.1.8[0x3183a3afb5]
/usr/lib64/libruby.so.1.8[0x3183a3494a]
/usr/lib64/libruby.so.1.8[0x3183a34e48]
/usr/lib64/libruby.so.1.8[0x3183a3bbc6]
/usr/lib64/libruby.so.1.8[0x3183a3afb5]
/usr/lib64/libruby.so.1.8[0x3183a3494a]
/usr/lib64/libruby.so.1.8[0x3183a34e48]
/usr/lib64/libruby.so.1.8[0x3183a3bbc6]
/usr/lib64/libruby.so.1.8[0x3183a3d694]
/usr/lib64/libruby.so.1.8[0x3183a3494a]
/usr/lib64/libruby.so.1.8[0x3183a34e48]
/usr/lib64/libruby.so.1.8[0x3183a3bcf9]
/usr/lib64/libruby.so.1.8[0x3183a3ae99]
/usr/lib64/libruby.so.1.8[0x3183a3db45]
/usr/lib64/libruby.so.1.8[0x3183a3fb4f]
/usr/lib64/libruby.so.1.8[0x3183a3c197]
/usr/lib64/libruby.so.1.8[0x3183a3fb4f]
/usr/lib64/libruby.so.1.8[0x3183a41059]
/usr/lib64/libruby.so.1.8[0x3183a3492e]
/usr/lib64/libruby.so.1.8[0x3183a34e48]
/usr/lib64/libruby.so.1.8[0x3183a3bcf9]
/usr/lib64/libruby.so.1.8[0x3183a3df9d]
/usr/lib64/libruby.so.1.8[0x3183a3494a]
/usr/lib64/libruby.so.1.8[0x3183a34e48]
/usr/lib64/libruby.so.1.8[0x3183a3bbc6]
/usr/lib64/libruby.so.1.8[0x3183a3df9d]
/usr/lib64/libruby.so.1.8[0x3183a3494a]
/usr/lib64/libruby.so.1.8[0x3183a34e48]
/usr/lib64/libruby.so.1.8(rb_obj_call_init+0x54)[0x3183a35104]
/usr/lib64/libruby.so.1.8(rb_class_new_instance+0x32)[0x3183a5f612]
/usr/lib64/libruby.so.1.8[0x3183a3492e]
/usr/lib64/libruby.so.1.8[0x3183a34e48]
/usr/lib64/libruby.so.1.8(rb_call_super+0x8d)[0x3183a35ead]
/usr/lib64/libruby.so.1.8[0x3183a341b9]
/usr/lib64/libruby.so.1.8[0x3183a34e48]
/usr/lib64/libruby.so.1.8[0x3183a3bcf9]
/usr/lib64/libruby.so.1.8[0x3183a3afb5]
/usr/lib64/libruby.so.1.8[0x3183a3db45]
/usr/lib64/libruby.so.1.8[0x3183a3494a]
/usr/lib64/libruby.so.1.8[0x3183a34e48]
/usr/lib64/libruby.so.1.8[0x3183a3bbc6]
/usr/lib64/libruby.so.1.8[0x3183a3e7ff]
/usr/lib64/libruby.so.1.8[0x3183a3bf75]
/usr/lib64/libruby.so.1.8[0x3183a3494a]
/usr/lib64/libruby.so.1.8[0x3183a34e48]
/usr/lib64/libruby.so.1.8[0x3183a3bbc6]
/usr/lib64/libruby.so.1.8[0x3183a3df9d]
======= Memory map: ========
00400000-00401000 r-xp 00000000 fd:04 426424 /usr/bin/ruby
00600000-00602000 rw-p 00000000 fd:04 426424 /usr/bin/ruby
0cdc4000-0d2f9000 rw-p 0cdc4000 00:00 0 [heap]
3183a00000-3183ad8000 r-xp 00000000 fd:04 364444 /usr/lib64/libruby.so.1.8.5
3183ad8000-3183cd8000 ---p 000d8000 fd:04 364444 /usr/lib64/libruby.so.1.8.5
3183cd8000-3183cdd000 rw-p 000d8000 fd:04 364444 /usr/lib64/libruby.so.1.8.5
3183cdd000-3183cfb000 rw-p 3183cdd000 00:00 0
33ed600000-33ed61c000 r-xp 00000000 fd:00 327938 /lib64/ld-2.5.so
33ed81c000-33ed81d000 r--p 0001c000 fd:00 327938 /lib64/ld-2.5.so
33ed81d000-33ed81e000 rw-p 0001d000 fd:00 327938 /lib64/ld-2.5.so
33eda00000-33edb4e000 r-xp 00000000 fd:00 327939 /lib64/libc-2.5.so
33edb4e000-33edd4e000 ---p 0014e000 fd:00 327939 /lib64/libc-2.5.so
33edd4e000-33edd52000 r--p 0014e000 fd:00 327939 /lib64/libc-2.5.so
33edd52000-33edd53000 rw-p 00152000 fd:00 327939 /lib64/libc-2.5.so
33edd53000-33edd58000 rw-p 33edd53000 00:00 0
33ede00000-33ede02000 r-xp 00000000 fd:00 327940 /lib64/libdl-2.5.so
33ede02000-33ee002000 ---p 00002000 fd:00 327940 /lib64/libdl-2.5.so
33ee002000-33ee003000 r--p 00002000 fd:00 327940 /lib64/libdl-2.5.so
33ee003000-33ee004000 rw-p 00003000 fd:00 327940 /lib64/libdl-2.5.so
33ee200000-33ee23b000 r-xp 00000000 fd:00 327944 /lib64/libsepol.so.1
33ee23b000-33ee43b000 ---p 0003b000 fd:00 327944 /lib64/libsepol.so.1
33ee43b000-33ee43c000 rw-p 0003b000 fd:00 327944 /lib64/libsepol.so.1
33ee43c000-33ee446000 rw-p 33ee43c000 00:00 0
33ee600000-33ee615000 r-xp 00000000 fd:00 327945 /lib64/libselinux.so.1
33ee615000-33ee815000 ---p 00015000 fd:00 327945 /lib64/libselinux.so.1
33ee815000-33ee817000 rw-p 00015000 fd:00 327945 /lib64/libselinux.so.1
33ee817000-33ee818000 rw-p 33ee817000 00:00 0
33eea00000-33eea16000 r-xp 00000000 fd:00 327946 /lib64/libpthread-2.5.so
33eea16000-33eec15000 ---p 00016000 fd:00 327946 /lib64/libpthread-2.5.so
33eec15000-33eec16000 r--p 00015000 fd:00 327946 /lib64/libpthread-2.5.so
33eec16000-33eec17000 rw-p 00016000 fd:00 327946 /lib64/libpthread-2.5.so
33eec17000-33eec1b000 rw-p 33eec17000 00:00 0
33eee00000-33eee82000 r-xp 00000000 fd:00 327951 /lib64/libm-2.5.so
33eee82000-33ef081000 ---p 00082000 fd:00 327951 /lib64/libm-2.5.so
33ef081000-33ef082000 r--p 00081000 fd:00 327951 /lib64/libm-2.5.so
33ef082000-33ef083000 rw-p 00082000 fd:00 327951 /lib64/libm-2.5.so
33ef600000-33ef609000 r-xp 00000000 fd:00 327950 /lib64/libcrypt-2.5.so
33ef609000-33ef808000 ---p 00009000 fd:00 327950 /lib64/libcrypt-2.5.so
33ef808000-33ef809000 r--p 00008000 fd:00 327950 /lib64/libcrypt-2.5.so
33ef809000-33ef80a000 rw-p 00009000 fd:00 327950 /lib64/libcrypt-2.5.so
33ef80a000-33ef838000 rw-p 33ef80a000 00:00 0
33efa00000-33efa14000 r-xp 00000000 fd:00 327953 /lib64/libz.so.1.2.3
33efa14000-33efc13000 ---p 00014000 fd:00 327953 /lib64/libz.so.1.2.3
33efc13000-33efc14000 rw-p 00013000 fd:00 327953 /lib64/libz.so.1.2.3
33efe00000-33efe02000 r-xp 00000000 fd:00 327960 /lib64/libcom_err.so.2.1
33efe02000-33f0001000 ---p 00002000 fd:00 327960 /lib64/libcom_err.so.2.1
33f0001000-33f0002000 rw-p 00001000 fd:00 327960 /lib64/libcom_err.so.2.1
33f0200000-33f0211000 r-xp 00000000 fd:00 327964 /lib64/libresolv-2.5.so
33f0211000-33f0411000 ---p 00011000 fd:00 327964 /lib64/libresolv-2.5.so
33f0411000-33f0412000 r--p 00011000 fd:00 327964 /lib64/libresolv-2.5.so
33f0412000-33f0413000 rw-p 00012000 fd:00 327964 /lib64/libresolv-2.5.so
33f0413000-33f0415000 rw-p 33f0413000 00:00 0
33f0a00000-33f0b2d000 r-xp 00000000 fd:00 327954 /lib64/libcrypto.so.0.9.8e
33f0b2d000-33f0d2c000 ---p 0012d000 fd:00 327954 /lib64/libcrypto.so.0.9.8e
33f0d2c000-33f0d4d000 rw-p 0012c000 fd:00 327954 /lib64/libcrypto.so.0.9.8e
33f0d4d000-33f0d51000 rw-p 33f0d4d000 00:00 0
33f0e00000-33f0e02000 r-xp 00000000 fd:00 327965 /lib64/libkeyutils-1.2.so
33f0e02000-33f1001000 ---p 00002000 fd:00 327965 /lib64/libkeyutils-1.2.so
33f1001000-33f1002000 rw-p 00001000 fd:00 327965 /lib64/libkeyutils-1.2.so
33f1200000-33f122c000 r-xp 00000000 fd:04 363348 /usr/lib64/libgssapi_krb5.so.2.2
33f122c000-33f142c000 ---p 0002c000 fd:04 363348 /usr/lib64/libgssapi_krb5.so.2.2
33f142c000-33f142e000 rw-p 0002c000 fd:04 363348 /usr/lib64/libgssapi_krb5.so.2.2
33f1600000-33f1692000 r-xp 00000000 fd:04 363347 /usr/lib64/libkrb5.so.3.3
33f1692000-33f1891000 ---p 00092000 fd:04 363347 /usr/lib64/libkrb5.so.3.3
33f1891000-33f1895000 rw-p 00091000 fd:04 363347 /usr/lib64/libkrb5.so.3.3
33f1a00000-33f1a08000 r-xp 00000000 fd:04 363345 /usr/lib64/libkrb5support.so.0.1
33f1a08000-33f1c07000 ---p 00008000 fd:04 363345 /usr/lib64/libkrb5support.so.0.1
33f1c07000-33f1c08000 rw-p 00007000 fd:04 363345 /usr/lib64/libkrb5support.so.0.1
33f1e00000-33f1e24000 r-xp 00000000 fd:04 363346 /usr/lib64/libk5crypto.so.3.1
33f1e24000-33f2023000 ---p 00024000 fd:04 363346 /usr/lib64/libk5crypto.so.3.1
33f2023000-33f2025000 rw-p 00023000 fd:04 363346 /usr/lib64/libk5crypto.so.3.1
33f2200000-33f2246000 r-xp 00000000 fd:00 327733 /lib64/libssl.so.0.9.8e
33f2246000-33f2446000 ---p 00046000 fd:00 327733 /lib64/libssl.so.0.9.8e
33f2446000-33f244c000 rw-p 00046000 fd:00 327733 /lib64/libssl.so.0.9.8e
2b33a5ebe000-2b33a5ec0000 rw-p 2b33a5ebe000 00:00 0
2b33a5ec6000-2b33a5f2b000 rw-p 2b33a5ec6000 00:00 0
2b33a5f2c000-2b33a5fdc000 rw-p 2b33a5f2c000 00:00 0
2b33a5fdc000-2b33a5fe0000 r-xp 00000000 fd:04 363401 /usr/lib64/ruby/1.8/x86_64-linux/stringio.so
2b33a5fe0000-2b33a61e0000 ---p 00004000 fd:04 363401 /usr/lib64/ruby/1.8/x86_64-linux/stringio.so
2b33a61e0000-2b33a61e1000 rw-p 00004000 fd:04 363401 /usr/lib64/ruby/1.8/x86_64-linux/stringio.so
2b33a61e1000-2b33a61fd000 r-xp 00000000 fd:04 363403 /usr/lib64/ruby/1.8/x86_64-linux/syck.so
2b33a61fd000-2b33a63fc000 ---p 0001c000 fd:04 363403 /usr/lib64/ruby/1.8/x86_64-linux/syck.so
2b33a63fc000-2b33a63fe000 rw-p 0001b000 fd:04 363403 /usr/lib64/ruby/1.8/x86_64-linux/syck.so
2b33a63ff000-2b33a653c000 rw-p 2b33a63ff000 00:00 0
2b33a653c000-2b33a653e000 r-xp 00000000 fd:04 363388 /usr/lib64/ruby/1.8/x86_64-linux/etc.so
2b33a653e000-2b33a673e000 ---p 00002000 fd:04 363388 /usr/lib64/ruby/1.8/x86_64-linux/etc.so
2b33a673e000-2b33a673f000 rw-p 00002000 fd:04 363388 /usr/lib64/ruby/1.8/x86_64-linux/etc.so
2b33a673f000-2b33a6779000 r-xp 00000000 fd:04 363394 /usr/lib64/ruby/1.8/x86_64-linux/openssl.so
2b33a6779000-2b33a6978000 ---p 0003a000 fd:04 363394 /usr/lib64/ruby/1.8/x86_64-linux/openssl.so
2b33a6978000-2b33a697b000 rw-p 00039000 fd:04 363394 /usr/lib64/ruby/1.8/x86_64-linux/openssl.so
2b33a697c000-2b33a6bb6000 rw-p 2b33a697c000 00:00 0
2b33a6bb6000-2b33a6bb7000 r-xp 00000000 fd:04 363389 /usr/lib64/ruby/1.8/x86_64-linux/fcntl.so
2b33a6bb7000-2b33a6db6000 ---p 00001000 fd:04 363389 /usr/lib64/ruby/1.8/x86_64-linux/fcntl.so
2b33a6db6000-2b33a6db7000 rw-p 00000000 fd:04 363389 /usr/lib64/ruby/1.8/x86_64-linux/fcntl.so
2b33a6db7000-2b33a6dc0000 r-xp 00000000 fd:04 363405 /usr/lib64/ruby/1.8/x86_64-linux/zlib.so
2b33a6dc0000-2b33a6fbf000 ---p 00009000 fd:04 363405 /usr/lib64/ruby/1.8/x86_64-linux/zlib.so
2b33a6fbf000-2b33a6fc0000 rw-p 00008000 fd:04 363405 /usr/lib64/ruby/1.8/x86_64-linux/zlib.so
2b33a6fc0000-2b33a6fc2000 r-xp 00000000 fd:04 363382 /usr/lib64/ruby/1.8/x86_64-linux/digest/md5.so
2b33a6fc2000-2b33a71c1000 ---p 00002000 fd:04 363382 /usr/lib64/ruby/1.8/x86_64-linux/digest/md5.so
2b33a71c1000-2b33a71c2000 rw-p 00001000 fd:04 363382 /usr/lib64/ruby/1.8/x86_64-linux/digest/md5.so
2b33a71c2000-2b33a71c4000 r-xp 00000000 fd:04 363381 /usr/lib64/ruby/1.8/x86_64-linux/digest.so
2b33a71c4000-2b33a73c3000 ---p 00002000 fd:04 363381 /usr/lib64/ruby/1.8/x86_64-linux/digest.so
2b33a73c3000-2b33a73c4000 rw-p 00001000 fd:04 363381 /usr/lib64/ruby/1.8/x86_64-linux/digest.so
2b33a73c4000-2b33a73cf000 r-xp 00000000 fd:04 363400 /usr/lib64/ruby/1.8/x86_64-linux/socket.so
2b33a73cf000-2b33a75ce000 ---p 0000b000 fd:04 363400 /usr/lib64/ruby/1.8/x86_64-linux/socket.so
2b33a75ce000-2b33a75cf000 rw-p 0000a000 fd:04 363400 /usr/lib64/ruby/1.8/x86_64-linux/socket.so
2b33a75cf000-2b33a75d0000 rw-p 2b33a75cf000 00:00 0
2b33a75d5000-2b33a75df000 r-xp 00000000 fd:00 327707 /lib64/libnss_files-2.5.so
2b33a75df000-2b33a77de000 ---p 0000a000 fd:00 327707 /lib64/libnss_files-2.5.so
2b33a77de000-2b33a77df000 r--p 00009000 fd:00 327707 /lib64/libnss_files-2.5.so
2b33a77df000-2b33a77e0000 rw-p 0000a000 fd:00 327707 /lib64/libnss_files-2.5.so
2b33a77e6000-2b33a77f3000 r-xp 00000000 fd:00 327952 /lib64/libgcc_s-4.1.2-20080825.so.1
2b33a77f3000-2b33a79f3000 ---p 0000d000 fd:00 327952 /lib64/libgcc_s-4.1.2-20080825.so.1
2b33a79f3000-2b33a79f4000 rw-p 0000d000 fd:00 327952 /lib64/libgcc_s-4.1.2-20080825.so.1
7fffb3be9000-7fffb3c19000 rw-p 7ffffffce000 00:00 0 [stack]
7fffb3d87000-7fffb3d8a000 r-xp 7fffb3d87000 00:00 0 [vdso]
ffffffffff600000-ffffffffffe00000 ---p 00000000 00:00 0 [vsyscall]
Aborted

1.0 server CONNECTED frame erroneously raises UnsupportedProtocolError

Current Scenario:

  • Client connects with a header of exactly "accept-version" => "1.0" (and a proper "host" header)
  • The server is a 1.0 only server (e.g. AMQ)
  • The server ignores unknown CONNECT headers and returns a CONNECTED frame
  • The server does not return any STOMP 1.1 headers (expected server behavior for 1.0), specifically a "version" header
  • A Stomp::Error::UnsupportedProtocolError is raised

This is erroneous behavior. The STOMP client should:

  • Accept this connection as a "1.0" connection
  • Set the 'protocol' variable appropriately
  • Continue with normal operation

Note: if the client connects with a more complex header like: "accept-version" => "1.1, 3.14159, 1.0" , where "1.0" is a listed option, the connection should proceed without error as described above.

Note: if "1.0" is not listed in the "accept-version" header, the Stomp::Error::UnsupportedProtocolError should continue to be raised.

stomp 1.1 multithreading

hello,

Given the code

require 'rubygems'
require 'stomp'
require 'pp'

class StompLogger
  def on_miscerr(params, errstr)
    puts "Unexpected error on connection to stomp://%s@%s:%d %s" % [params[:cur_login], params[:cur_host], params[:cur_port], errstr]
    pp caller
  end
end

options = { :stompuser => "dev", :stomppass => "secret", :stompserver => "1.2.3.4", :stompport => 6163 }

connection = {:hosts => [
                          {:login => options[:stompuser], :passcode => options[:stomppass], :host => options[:stompserver], :port => options[:stompport]},
                        ], :logger => StompLogger.new, :connect_headers => {:"heart-beat" => "10000,10000", :host => "stomp", :"accept-version" => "1.1,1.0"}}

conn = Stomp::Connection.open(connection)

p conn.connection_frame.headers

Thread.new(conn) do |conn|
  while true
    p conn.receive
  end
end

puts "Sleeping....."

sleep 10000

So there's a background thread that just loops and receives and prints what it gets while the rest of the program continues. I am not sure if this is the intended use pattern for achiving this but it does work in 1.0 mode quite well and I've used this style of code all over.

When 1.1 protocol heartbeats are enabled this happens after some time:

{"heart-beat"=>"10000,10000", "version"=>"1.1", "session"=>"ID:stomp-34412-1340368192346-3:100", "server"=>"ActiveMQ/5.6.0"}
Sleeping.....
Unexpected error on connection to stomp://[email protected]:6163 receive failed: execution expired
["/home/rip/.gem/gems/stomp-1.2.3/lib/stomp/connection.rb:428:in `__old_receive'",
 "/home/rip/.gem/gems/stomp-1.2.3/lib/stomp/connection.rb:438:in `receive'",
 "test.rb:24",

on_ssl_connectfail logging

hello,

Busy testing the new on_ssl_connectfail logging and it looks good, certainly provides all the information you'd need to give useful feedback.

I am wondering if it would be a good idea to give this logger some way to abort, disconnect and raise an exception that bubbles up back to the ruby code that uses the gem?

Imagine the CA file does not exist or is wrong so you get an verification error. You may argue that retrying forever is fine since the user might eventually put the right CA file down. But you might also want to give the user the ability to say when this happens, stop retrying and just fail?

Connection timeout

hello,

I see the hash style connection takes a timeout parameter which I assumed was for the connection timeout in the case of the broker being down but seems its not the case.

Following code from Connection#initialize that calls #socket to #open_socket to #open_tcp_socket nothing has a timeout block on the initial TCPSocket.open.

So if the JMS server is down it will take a very long time - TCP connect timeout - before failover happened, would be nice if we can wrap that in a timeout

ACKs/NACKs sent with wrong 'id' header when SUBSCRIBE has 'ack' header set to 'client' mode

ActiveMQ 5.8.0 with 1.2.10 of the gem:

In the STOMP log output below, the ACK message has its id header incorrectly populated with the value of the MESSAGE's message-id header. It should, however, populate the id header using the value of the MESSAGE's ack header, given that the ack mode on the subscription is set to client.

As a result ActiveMQ rejects the ACK with the ERROR frame shown.

According to the STOMP spec the same behavior is expected when the ack mode is set to client-individual (not verified).

2013/07/23 22:45:41.869 | TRACE | StompIO                        | Received: 
SUBSCRIBE
content-type:text/plain; charset=UTF-8
activemq.subscriptionName:vicki_event_ods
ack:client
destination:/topic/Vicki.Event
id:vicki_event_processor
content-length:0

2013/07/23 22:46:07.136 | TRACE | StompIO                        | Sending: 
MESSAGE
ack:ID:darkhorse.onyx.ove.com-41603-1374633870794-4:1
message-id:ID:darkhorse.onyx.ove.com-41603-1374633870794-6:1:1:1:1
type:
destination:/topic/Vicki.Event
timestamp:1374633967127
expires:0
subscription:vicki_event_processor
priority:0
correlation-id:

<?xml version="1.0" encoding="utf-8"?>
<univ...universalid>
2013/07/23 22:46:07.354 | TRACE | StompIO                        | Received: 
ACK
content-type:text/plain; charset=UTF-8
id:ID:darkhorse.onyx.ove.com-41603-1374633870794-6:1:1:1:1
content-length:0


2013/07/23 22:46:07.357 | TRACE | StompIO                        | Sending: 
ERROR
content-type:text/plain
message:Unexpected ACK received for message-id [null]

org.apache.activemq.transport.stomp.ProtocolE...d.java:662)

NoCurrentConnection

hello,

In some circumstances @closed gets set to false and remains false, I think this happens when an exception gets raised during open_socket after setting it to false.

Once its set to false and even if reliable is true etc - stomp gem will never try to reconnect since methods like receive, poll, disconnect, unreceive, publish, unsubscribe and more or less all others will raise the NoCurrentConnection error before doing anything with #socket that would take care of reconnection attempts.

The end result is that forever the stomp gem just raises NoCurrentConnection instead of trying to reconnect.

I can work around this by catching NoCurrentConnection outside of the gem but it feels to me that at least with reliable set true the gem should retry connections rather than raising this exception.

affects version 1.2.4

Packet parsing timeout

My Ruby 1.8.7 based project includes a queue subscriber and it works perfectly on my workstation with ActiveMQ running on the same host. However, as I deploy to the production environment, one message gets popped from the queue and then I get the timeout exception:

Packet parsing timeout (Stomp::Error::PacketParsingTimeout)

Stomp::Connection#poll issues Hard Receive

In the current gem, Connection#poll will hang in a hard receive, waiting on messages when none can possibly be present.

It should be asynchronous, and return 'nil' if there is nothing to be received.

TCP Keepalive or Stomp level ping

We often find our stomp connections stuck and not responding, this tends to happen on idle networks with session aware inspection.

Stomp connections tend to be 100% idle and firewalls see this as dead sessions. It would be great if we could optionally enable SO_KEEPALIVE on the socket or perhaps send some kind of data that keeps the connection alive.

I belive the Stomp 1.0 protocol doesnt let you send ping messages as part of the protocol so hopefully Socket keep alive might help a bit

ERROR msg with stomp 1.1

This is more a question than a bug report.
When I send a message to a wrong queue, the server answer's back an ERROR frame. However, this is never returned to the caller as the publish method just does a transmit and does not read back the server answers. Is this the expected behavior ? If so, how can one access the information that the message was not delivered ?

SSL Example Use Case 4 Fails with JRuby 1.6.5

I'm using Stomp 1.2.2 with JRuby 1.6.5 (using Ruby 1.9 compatibility) and the SSL example use case 4 doesn't work.

In connection.rb, line 688 which reads the "cert_file", it uses File.open. Also line 691 (which reads the key_file) uses File.open. This works with Ruby but not with JRuby (at least 1.6.5).

In JRuby "File.read" needs to be used, such as:

ctx.cert = OpenSSL::X509::Certificate.new(File.read(@ssl.cert_file))
ctx.key  = OpenSSL::PKey::RSA.new(File.read(@ssl.key_file))

If File.open is used JRuby throws an error "can't convert File into String" from their X509Cert class.

Ultimately JRuby probably needs to be fixed so that it can handle a File object (the result of File.open) as well as a String (File.read).

However, since File.read works in Ruby and JRuby I thought perhaps Stomp could be updated to use it so SSL will work with JRuby today.

Error Frame received errors

Hi guys,

I ran into some probs today on a VM I've got running. I have a backend service manager which I wrote in ruby. Since updating 1 of my VM's from version 1.1.10 to the latest 1.2.2 gem I've been receiving loads of Error messages like these:

27-04-2012 17:21:03 #2860 INFO --: Processing request for service font, worker 1
27-04-2012 17:21:06 #2860 INFO --: Finished processing request for service font, worker 1
27-04-2012 17:21:07 #2860 ERROR --: ERROR frame received: {"message"=>"content-length bytes were read and there was no trailing null byte"}
27-04-2012 17:21:07 #2860 ERROR --: ERROR frame received: {"message"=>"Unable to parser header line [Arial\r]"}
27-04-2012 17:21:07 #2860 ERROR --: ERROR frame received: {"message"=>"Unable to parser header line [BatangChe\r]"}
27-04-2012 17:21:07 #2860 ERROR --: ERROR frame received: {"message"=>"Unable to parser header line [GungsuhChe\r]"}
27-04-2012 17:21:07 #2860 ERROR --: ERROR frame received: {"message"=>"Unable to parser header line [DaunPenh\r]"}
27-04-2012 17:21:07 #2860 ERROR --: ERROR frame received: {"message"=>"Unable to parser header line [Estrangelo Edessa\r]"}
27-04-2012 17:21:07 #2860 ERROR --: ERROR frame received: {"message"=>"Unable to parser header line [Gautami\r]"}
27-04-2012 17:21:07 #2860 ERROR --: ERROR frame received: {"message"=>"Unable to parser header line [Gulim\r]"}
27-04-2012 17:21:07 #2860 ERROR --: ERROR frame received: {"message"=>"Unable to parser header line [Dotum\r]"}
27-04-2012 17:21:08 #2860 INFO --: Processing request for service font, worker 1
27-04-2012 17:21:10 #2860 INFO --: Finished processing request for service font, worker 1
27-04-2012 17:21:10 #2860 ERROR --: ERROR frame received: {"message"=>"Unexpected ACK received for message-id [ID:uk-towton-01-59246-1335543450997-2:31:-1:1:1]"}

This error occurs when trying to send a response back to ActiveMQ.

If I revert to the older 1.1.10 gem the problem goes away. I've stepped through it on my service manager's end and I can't see anywhere that is "ACK"ing back inappropriately, also I've tried modifying my service manager to ensure the 'content-length' header has been set properly on my end and it is from what I can tell.

As far as I can tell it looks like something's been introduced into one of the latest gem versions? I don't mind taking a look at the stomp gem, I just thought I'd check with you guys first if you've seen this before or if it's already been dealt with recently?

Lucas

disconnect method fails when using a Hash to connect

Hi guys,

It could be I'm doing something wrong.. just thought I'd run this by you guys though in case I'm not.

I seem to get different behavior when trying to disconnect a stomp connection from ActiveMQ 5.4

When I use Stomp::Connection.new('', '', 'localhost', 61613, false) it seems to work fine, when I use a Hash instead of parameters though, I seem to have trouble disconnecting cleanly and get "Transport failed" errors from ActiveMQ and an error that comes out in my console "receive failed: stream closed"

I put a gist up for you to look at, please let me know if I'm just being stupid and leaving something out of the hash.
https://gist.github.com/1205377

Windows/port bug?

I'm trying out Stomp on a Windows machine, where out of the box ActiveMQ starts on port 8161. Stomp will refuse to connect:

irb(main):009:0> client = Stomp::Client.new "stomp://localhost:8161"
TypeError: can't convert nil into String

If I try an incorrect port number instead, like 8162, I get this

irb(main):008:0> client = Stomp::Client.new "stomp://localhost:8162"
Errno::ECONNREFUSED: No connection could be made because the target machine actively refused it. - connect(2)

I also see no connection attempt appear in the ActiveMQ log on the try with the correct port. So what's happening in trying to connect to the correct host/port that it responds with a nil error?

failover URL should allow for NIO option

The failover URL parsing logic in client/utils.rb line 41 should be:

/^failover:(\/\/)?\(stomp(\+(ssl|nio))?:\/\/#{url_regex}(,stomp(\+(ssl|nio))?:\/\/#{url_regex}\))+(\?(.*))?$/

Note the capture group numberings change as a result.

Connection#publish modifies the supplied headers variable

The publish method accepts headers and then modifies the original supplied variable:

headers = {}
connection.publish("/queue/foo", "test", headers)
pp headers

This will produce something like:

{:destination=>"/queue/foo", "content-length"=>"4"}

The method should probably clone the headers and modify the clone instead

Commit d7d3ad0 causes gem build failures

For the record, I will manually revert this commit.

This is only a problem for folks who build the gem, not those who use it.

The stomp gem should be able to build and run seamlessly in a number of environments, e.g.:

rake build

should just work.

In particular it MUST build with Ruby 1.8.7 and gem version 1.4.1 (or earlier).

Also for the record, my personal (current) Ruby environments are:

185_231 (2008-06-20 patchlevel 231)
186_383 (2009-08-04 patchlevel 383)
187_000 1.8.7 (2008-04-15 patchlevel 0)
187_299 (2010-06-23 patchlevel 299)
191_378 1.9.1p378 (2010-01-10)
192_188 1.9.2p188 (2011-03-28 revision 31204)
193_134 1.9.3p134 (2012-02-19 revision 34690)
ruby 1.9.2p290 (2011-07-04 revision 32477)
ruby 1.9.3p358 (2012-12-22 revision 38541)
ruby 2.0.0p0 (2013-02-24 revision 39473)
ruby 2.1.0dev (2013-03-23 trunk 39878)

Errors sent from ActiveMQ are not exposed in any way to the client

When performing some load testing, we configured really low memory/disk usage for ActiveMQ, e.g.:

          <systemUsage>                                                             
            <systemUsage sendFailIfNoSpace="true">                                  
                <memoryUsage>                                                       
                    <memoryUsage limit="1 mb"/>                                    
                </memoryUsage>                                                      
                <storeUsage>                                                        
                    <storeUsage limit="1 mb"/>                                    
                </storeUsage>                                                       
                <tempUsage>                                                         
                    <tempUsage limit="1 mb"/>                                      
                </tempUsage>                                                        
            </systemUsage>                                                          
        </systemUsage>       

Note the sendFailIfNoSpace.

What ends up happening if the broker cannot receive messages is that the Stomp::Client#publish call continues to "succeed" (not block at least) and eventually the following is printed to $stderr:

hreceive failed: invalid command: "\nERROR\ncontent-type:text/plain\nmessage:Temp Store is Full (0% of 5242880). Stopping producer (ID:activemq-test1-57156-1378923899188-8:1:-1:1) to prevent flooding queue://consumer.testcase.virtual.stahp. See http://activemq.apache.org/producer-flow-control.html for more info\n\njavax.jms.ResourceAllocationException: Temp Store is Full (0% of 5242880). Stopping producer (ID:activemq-test1-57156-1378923899188-8:1:-1:1) to prevent flooding queue://consumer.testcase.virtual.stahp. See http://activemq.apache.org/producer-flow-control.html for more info\n\tat org.apache.activemq.broker.region.BaseDestination.waitForSpace(BaseDestination.java:616)\n\tat org.apache.activemq.broker.region.BaseDestination.waitForSpace(BaseDestination.java:610)\n\tat org.apache.activemq.broker.region.Queue.checkUsage(Queue.java:825)\n\tat org.apache.activemq.broker.region.Queue.doMessageSend(Queue.java:742)\n\tat org.apache.activemq.broker.region.Queue.send(Queue.java:721)\n\tat org.apache.activemq.broker.region.DestinationFilter.send(DestinationFilter.java:142)\n\tat org.apache.activemq.broker.region.virtual.VirtualTopicInterceptor.send(VirtualTopicInterceptor.java:50)\n\tat org.apache.activemq.broker.region.AbstractRegion.send(AbstractRegion.java:406)\n\tat org.apache.activemq.broker.region.RegionBroker.send(RegionBroker.java:392)\n\tat org.apache.activemq.broker.jmx.ManagedRegionBroker.send(ManagedRegionBroker.java:282)\n\tat org.apache.activemq.broker.BrokerFilter.send(BrokerFilter.java:129)\n\tat org.apache.activemq.broker.CompositeDestinationBroker.send(CompositeDestinationBroker.java:96)\n\tat org.apache.activemq.broker.TransactionBroker.send(TransactionBroker.java:317)\n\tat org.apache.activemq.broker.BrokerFilter.send(BrokerFilter.java:129)\n\tat org.apache.activemq.broker.BrokerFilter.send(BrokerFilter.java:129)\n\tat org.apache.activemq.security.AuthorizationBroker.send(AuthorizationBroker.java:202)\n\tat org.apache.activemq.broker.MutableBrokerFilter.send(MutableBrokerFilter.java:135)\n\tat org.apache.activemq.broker.TransportConnection.processMessage(TransportConnection.java:499)\n\tat org.apache.activemq.command.ActiveMQMessage.visit(ActiveMQMessage.java:749)\n\tat org.apache.activemq.broker.TransportConnection.service(TransportConnection.java:329)\n\tat org.apache.activemq.broker.TransportConnection$1.onCommand(TransportConnection.java:184)\n\tat org.apache.activemq.transport.MutexTransport.onCommand(MutexTransport.java:45)\n\tat org.apache.activemq.transport.AbstractInactivityMonitor.onCommand(AbstractInactivityMonitor.java:288)\n\tat org.apache.activemq.transport.stomp.StompTransportFilter.sendToActiveMQ(StompTransportFilter.java:84)\n\tat org.apache.activemq.transport.stomp.ProtocolConverter.sendToActiveMQ(ProtocolConverter.java:195)\n\tat org.apache.activemq.transport.stomp.ProtocolConverter.onStompSend(ProtocolConverter.java:321)\n\tat org.apache.activemq.transport.stomp.ProtocolConverter.onStompCommand(ProtocolConverter.java:233)\n\tat org.apache.activemq.transport.stomp.StompTransportFilter.onCommand(StompTransportFilter.java:73)\n\tat org.apache.activemq.transport.TransportSupport.doConsume(TransportSupport.java:83)\n\tat org.apache.activemq.transport.tcp.TcpTransport.doRun(TcpTransport.java:214)\n\tat org.apache.activemq.transport.tcp.TcpTransport.run(TcpTransport.java:196)\n\tat java.lang.Thread.run(Thread.java:722)\n\u0

I think the Stomp::Client should have some means of expressing an error from the server, but I'm not sure how it should be expressed

Packet parsing timeout when running a consumer under JRuby

You'll notice none of the application code being invoked at this point, all I'm doing is a simple:

client.subscribe('/queue/myqueue') do |msg|
   puts msg
end

And the following traceback is thrown under JRuby, but the code works just fine under MRI 1.9.3

Packet parsing timeout
org/jruby/RubyIO.java:2189:in `gets'
/home/tyler/.rvm/gems/jruby-1.7.2@smb/gems/stomp-1.2.10/lib/connection/netio.rb:39:in `_receive'
org/jruby/ext/timeout/Timeout.java:169:in `timeout'
/home/tyler/.rvm/gems/jruby-1.7.2@smb/gems/stomp-1.2.10/lib/connection/netio.rb:34:in `_receive'
org/jruby/ext/thread/Mutex.java:149:in `synchronize'
/home/tyler/.rvm/gems/jruby-1.7.2@smb/gems/stomp-1.2.10/lib/connection/netio.rb:16:in `_receive'
/home/tyler/.rvm/gems/jruby-1.7.2@smb/gems/stomp-1.2.10/lib/connection/utils.rb:231:in `__old_receive'
/home/tyler/.rvm/gems/jruby-1.7.2@smb/gems/stomp-1.2.10/lib/stomp/connection.rb:397:in `receive'
/home/tyler/.rvm/gems/jruby-1.7.2@smb/gems/stomp-1.2.10/lib/client/utils.rb:159:in `start_listeners'

receive failed: SSL_read:: no start line

This is a issue I've noticed since very early releases, the reason I have not logged this before is that I do not know how to reproduce it reliably.

When connecting to ActiveMQ with SSL enabled I sometimes get the error logged (using the new callback loggers here)

`on_miscerr' Unexpected error on connection stomp://[email protected]:6164: receive failed:  SSL_read:: no start line

This is from the __old_receive method on connection.rb, if I tweak the code to also log the exception class I get:

`on_miscerr' Unexpected error on connection stomp://[email protected]:6164: receive failed: OpenSSL::SSL::SSLError: SSL_read:: no start line

I think I am finally getting near to being able to reproduce this but only in a very complex piece of code, I've not been able to create a simple bit of code that demonstrates this.

do you guys have any idea what might be the cause of this that might assist me in creating a reliable test case for this behavior?

License missing from gemspec

RubyGems.org doesn't report a license for your gem. This is because it is not specified in the gemspec of your last release.

via e.g.

spec.license = 'MIT'
# or
spec.licenses = ['MIT', 'GPL-2']

Including a license in your gemspec is an easy way for rubygems.org and other tools to check how your gem is licensed. As you can imagine, scanning your repository for a LICENSE file or parsing the README, and then attempting to identify the license or licenses is much more difficult and more error prone. So, even for projects that already specify a license, including a license in your gemspec is a good practice. See, for example, how rubygems.org uses the gemspec to display the rails gem license.

There is even a License Finder gem to help companies/individuals ensure all gems they use meet their licensing needs. This tool depends on license information being available in the gemspec. This is an important enough issue that even Bundler now generates gems with a default 'MIT' license.

I hope you'll consider specifying a license in your gemspec. If not, please just close the issue with a nice message. In either case, I'll follow up. Thanks for your time!

Appendix:

If you need help choosing a license (sorry, I haven't checked your readme or looked for a license file), GitHub has created a license picker tool. Code without a license specified defaults to 'All rights reserved'-- denying others all rights to use of the code.
Here's a list of the license names I've found and their frequencies

p.s. In case you're wondering how I found you and why I made this issue, it's because I'm collecting stats on gems (I was originally looking for download data) and decided to collect license metadata,too, and make issues for gemspecs not specifying a license as a public service :). See the previous link or my blog post about this project for more information.

Hardcoded values

Not sure if this is a known issue or not:

I have recently been pulling my hair out trying to get echowaves (http://echowaves.com) [which utilises ruby-stomp] to run on webfaction. As webfaction is shared hosting, ports tend to be somewhat random..usually requiring manual configuration to get things to work.

It came to my attention that upon changing the configured stomp port (default: 61613), within the rails/echowaves environment (and also orbited itself) led to connection refused errors. This appears to be a result of some hardcoded(?) values with the ruby stomp gem which I rather dirtily hacked around by running 'perl -pi -e 's/61613/$NEWPORT/g' on all of the files within the stomp gem directory..which has fixed the issue.

So perhaps there are hardcoded values within the stomp rubygem or environmental values aren't being read correctly?

Call backs on connection events

At present its hard to give user feedback in logs for network issues - the stomp gem handles the connection and reconnects etc, I love how this is really easy but unfortunately it only prints to STDERR.

Would it be possible for people to register callbacks on major connectivitiy events? disconnects, connects, reconnects etc so we can implement logging/stats in our apps?

ipv4 and ipv6 dual homing

hey,

When using the stomp gem in a mixed ipv6 and ipv4 setup it does the right thing for the initial connection - tries the ipv6 address first. But if the connection to the ipv6 host fails it doesn't attempt to connect to the ipv4 address as a failback, it keeps trying the ipv6 one.

This behavior makes sense but ruby TCPSocket.new doesnt do this, it might be something to detect open_tcp_socket and handle? The same might be said for hosts with many ipv4 addresses, we should try them all before moving to the next host.

% telnet stomp 6164
Trying 2001:41d0:2:xx::2...
telnet: connect to address 2001:41d0:2:xx::2: Connection timed out
Trying 178.xx.48.196...
Connected to stomp.

Source Code Refactor

The connection.rb and to a lesser extent client.rb source modules are beginning to reach an insane LOC number.

These modules need to be split into multiple source modules based on public / private method specifications and on what functionality is implemented.

Additionally at some point the entire source tree should be "beautified".

This seems to be a quiet time for the gem, and this effort can be started.

@reliable connections will infinite loop when max_reconnect_attempts are reached

This was originally reported on codehaus Jira. The problem still exists in the current gem. See:

http://jira.codehaus.org/browse/STOMP-20

The fix suggested at the codehaus site is:

def transmit(command, headers = {}, body = '')
  # The transmit may fail so we may need to retry.
  while TRUE
      begin
          used_socket = socket
         _transmit(used_socket, command, headers, body)
         return
      rescue Stomp::Error::MaxReconnectAttempts => e
          raise
      rescue
          @failure = $!
          raise unless @reliable
          $stderr.print "transmit to #{@host} failed: #{$!}\n"
          end
      end
  end

UTF-8 issue with OpenMQ

Hey there,

We are using OpenMQ and want to access it with stomp over stomp-bridge.
I noticed that there were problems with the string UTF-8 used in stomp so I quickly tried to find out where exactly. It's this line:

https://github.com/solars/stomp-test/blob/master/lib/stomp/connection.rb#L436
If I comment it out, then it works, otherwise openmq complains about the dash iirc.

The stomp version in this repository should be the latest, openmq is v 4.4

Now I'm not sure if this is an openmq problem or stomp problem, could you please comment on that?

Thanks in advance,
Christoph

URL regex matching should allow for non-word characters in passwords and usernames

In client/utils.rb the method:

def url_regex
  '(([\w\.\-]*):(\w*)@)?([\w\.\-]+):(\d+)'
end

should be changed to:

def url_regex
  '(([\w~!@#$%^&*()\-+=.?:<>,.]*\w):([\w~!@#$%^&*()\-+=.?:<>,.]*)@)?([\w\.\-]+):(\d+)'
end

This will match the following URLs:

host1.com:61613
@host1.com:61613
f@#$$%^&*()_+=o.o:@host1.com:61613
f@#$$%^&*()_+=o.o::b~!@#$%^&*()+-_=?:<>,.@@host1.com:61613

with the restriction that the username must end on a word character \w, which is a minor concession.

The extracted username and password are:

f@#$$%^&*()_+=o.o

and:

:b~!@#$%^&*()+-_=?:<>,.@

respectively.

Subscription id handling on NACK/ACKs for STOMP 1.1 clients.

The Client class has broken implementations for these methods under STOMP 1.1. Correct implementation is provided below (with the addition of the helper method).

The gem will create and manage a subscription id header
for you on subscribing when using STOMP 1.1, if you do not explicitly provide one. The id header is mandatory under STOMP 1.1.

However, Client#acknowledge() lacks handling for STOMP 1.1. It only caters for 1.0 and 1.2. Given that under STOMP 1.1 the 'msg' being ACK'ed must have an id header already, use it for the ACK! This negates
the need for the caller to supply the id via the headers hash argument.

You can leave the method name acknowledge in place if you wish but the name choice is totally dumb and asymmetric with nack. Therefore introduce the ack method and deprecate acknowledge which can delegate to ack.

The signature of nack should change. It should take a message not a message_id. Please, no BS arguments about 'breaking existing' users; they can cope with such a minor change and that's not what 'breaking' an API even means.

    def ack(message, headers = {})
      txn_id = headers[:transaction]

      if txn_id
        replay_list = @replay_messages_by_txn[txn_id]

        if replay_list.nil?
          replay_list = []
          @replay_messages_by_txn[txn_id] = replay_list
        end

        replay_list << message
      end

      if block_given?
        headers['receipt'] = register_receipt_listener(lambda { |r| yield r })
      end

      context = ack_context_for message, headers
      @connection.ack context[:message_id], context[:headers]
    end

    def nack(message, headers = {})
      context = ack_context_for message, headers
      @connection.nack context[:message_id], context[:headers]
    end

    def ack_context_for(message, headers)
      id = case protocol
             when Stomp::SPL_12
               'ack'
             when Stomp::SPL_11
               headers.merge!(:subscription => message.headers['subscription'])
               'message-id'
             else
               'message-id'
           end

      {:message_id => message.headers[id], :headers => headers}
    end

Uncaught exception thrown when AMQ closes connection

Using ActiveMQ 5.8.0 with 1.2.11 of the gem.

There appears to be a bug in utils.rb, line 165. What if message.nil? is true and reliable is true as well? You'll get "undefined method 'command' for nil:NilClass".

In my case the broker decided to close the connection owing to an inactivity timeout kicking in (2000ms) (log output can be provided if interested).

Thanks,
Paul

should not by default allow duplicate subscribes

Hello,

I think the behavior with duplicate subscribes is confusing and / or broken.

client.subscribe("/topic/foo")
client.subscribe("/topic/foo")

client.publish("/topic/foo", "hello")
p client.receive.body
p client.receive.body

This gives you two copies of the same message. Now at the most basic I think you should not be able to subscribe twice to the same source without specifically enabling some flag to force this.

Additionally you store subscriptions in @subscriptions and on a later connection attempt you replay the subscriptions this is fine but in the case of dupe subscriptions you will loose the duplicated subscription.

So if you ran the code above followed by:

client.disconnect
client.publish("/topic/foo", "hello")
p client.receive.body
p client.receive.body

You'd now only receive 1 copy of the message as the dupe subscription isnt replayed.

ActiveMQ does not manage STOMP write heart beats correctly: AMQ-4710

I thought I would bring to the attention of the gem maintainers an issue in ActiveMQ 5.8.0 regarding a bug in its STOMP write heart beat management.

The maintainers should be aware of this bug as it will materially affect testing of the Gem.

A Jira issue was opened against ActiveMQ 5.8.0 #AMQ-4710 for which I have submitted a test and a patch. It has yet to be accepted.

The incorrect behavior ActiveMQ exhibits is that its write checker can sleep for twice (worst case) the configured sleep interval between write heart beats. This can/will confuse connected clients, potentially resulting in a false failover attempt.

Whenever the write checker wakes it checks to see if any data was sent whilst it was asleep. If so, it does nothing and goes back to sleep. This is wrong.

Example (assume the following has happened):

  • a write checker is running, configured with an interval of 5000ms
  • a data frame was sent by the broker during the write checker's last sleep interval
  • the sending of the data frame took place 4000ms before the write checker woke
  • the write checker wakes, realizes data was sent, does nothing and goes back to sleep
  • no data is sent by the broker during the next write checker sleep interval

Current behavior:

  • when the write checker wakes again it will correctly send a KEEPALIVE to the client. However, a total of 9000ms has elapsed since the client last received any data from the broker causing the client to believe the broker has gone away possibly resulting in a false failover attempt by the client.

Correct behavior:

  • Every time the broker sends the client a data frame the current write checker timer task should be cancelled and replaced with a new one. The new timer task starts counting down immediately. Essentially the timer is 'reset.'

Connection#poll doesnt work

hello,

I might be missunderstanding the purpose of #poll but for me it always returns nil unless I add some inconvenient sleeps:

Given a queue that has messages already on the queue

connection = Stomp::Connection("me", "secret", "stomp", 6163, true)
connection.subscribe("/queue/foo")
p connection.poll

I just get a nil,

If I simply insert a sleep 1 before the call to poll then its fine and I get my message.

It this expected behavior?

Losing Connection

Hey,

after switching to the latest stomp version, and ruby 1.9.2, I'm getting a lot of disconnects from my queue (openmq with stomp bridge).

The daemon is still running though (I'm using stomp with daemon-kit).
What I wanted to ask for is, does anyone have a suggestion how I could debug this? if it's stomps fault, if I can reconnect somehow, and how to enable debug logging for this?

Might also be the fault of openmq, although I have another daemon, running on ruby 1.8.7

In the logs I only have the following: https://gist.github.com/c746181c75a454deaa5a

Thanks in advance for any pointers,
Christoph

Private key password can't be set

The current SSL support doesn't allow for a password to be set for the private key. Right now it lets you configure the 'key_file' which ultimately gets read in and passed to the OpenSSL::PKey::RSA constructor. The RSA constructor also allows for a second argument, the password.

The SSLParams should allow a "key_password" to be defined which gets passed along to the OpenSSL::PKey::RSA constructor if defined.

Automatic reconnect not working Apache ActiveMQ 5.6.0

To isolate I wrote a little test subscriber:

client = Stomp::Client.open("stomp://localhost:61613")
client.subscribe('/queue/testme') do |msg|
  puts msg.body
end
client.join

When run it will correctly consume each method until ActiveMQ is restarted. When that happens the client will enter a state where it is still running but no longer has an active subscription (confirmed in the AMQ admin console), nor will it consume any further messages.

In verion 1.2.5 of the gem, the AMQ restart would trigger a nil exception which would crash the program. Although a crash is generally bad, in this case it is preferable as at least the consumer hasn't entered a zombie-like state where it will never do anything useful again.

failover URL regex should allow a single broker to be specified.

AFAIK the failover protocol does not mandate a minimum of two brokers to be specified. Therefore the following is perfectly legal and should be allowed:

failover://(stomp://host1.com:61613)

This is still meaningful as this should cause the client to enter into its connection reestablishment logic should the connection to the single broker be lost.

To permit a single broker failover URL modify the failover regex found in client/utils.rb at line 41 to:

/^failover:(\/\/)?\(stomp(\+(ssl|nio))?:\/\/#{url_regex}(,stomp(\+(ssl|nio))?:\/\/#{url_regex})*\)(\?(.*))?$/

(This also includes the NIO requested fix mentioned in issue #64 )

This also has the consequence when combined with the fix in issue #65 that failover URLs no longer require a :@ prefix before the hostname as seen in a few examples where broker access is not anonymous.

The following URLs will match:

failover://(stomp://host1.com:61613)
failover://(stomp://host1.com:61613,stomp://host2.com:61613)

rather than:

failover://(stomp://:@host1.com:61613)

However, a : is still required if a username but no password is required:

failover://(stomp://someuser:@host1.com:61613)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.