StompMq 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
File without changes
data/lib/stompmq.rb ADDED
@@ -0,0 +1,2 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
2
+ require 'stompmq/connection'
@@ -0,0 +1,131 @@
1
+ require 'socket'
2
+ require 'stompmq/frame'
3
+ require 'stompmq/message'
4
+
5
+ module StompMq
6
+ class InvalidFrameType < StandardError; end
7
+ class CorruptFrame < StandardError; end
8
+ class CorruptHeader < StandardError; end
9
+ class ProtocolSequenceViolation < StandardError; end
10
+ class StompErrorReceived < StandardError; end
11
+
12
+ # Represents a connection to a STOMP message broker.
13
+ class Connection
14
+ # Connect to a STOMP broker and log in.
15
+ def initialize(opts = { :broker => 'localhost', :port => 61613, :username => nil, :passcode => nil })
16
+ @buffer = ""
17
+ @broker = opts[:broker]
18
+ @port = opts[:port]
19
+ @username = opts[:username]
20
+ @passcode = opts[:passcode]
21
+ @sock = TCPSocket.new @broker, @port
22
+ send_frame :connect, {:login => @username, :passcode => @passcode}
23
+ frame = receive_frame(15)
24
+ raise ProtocolSequenceViolation unless frame.cmd == 'CONNECTED'
25
+ self
26
+ end
27
+
28
+ # Subscribe to a STOMP queue.
29
+ def subscribe(opts = { :queue => nil })
30
+ queue = opts[:queue]
31
+ send_frame :subscribe, {:destination => queue}
32
+ end
33
+
34
+ # Send a STOMP message to a queue.
35
+ def send_message(opts = { :queue => nil, :header => {}, :content => {} })
36
+ queue = args[:queue]
37
+ content = args[:content]
38
+ header = args[:header]
39
+
40
+ header = {:destination => queue}.merge(header)
41
+ send_frame :send, header, content
42
+ end
43
+
44
+ # Receive a STOMP message.
45
+ def receive_message(timeout = 0)
46
+ frame = receive_frame(timeout)
47
+ return nil if !frame
48
+ raise StompErrorReceived.new(frame.content) if frame.cmd == 'ERROR'
49
+ raise ProtocolSequenceViolation unless frame.cmd == 'MESSAGE'
50
+ StompMq::Message.new(frame.header, frame.content)
51
+ end
52
+
53
+ private
54
+
55
+ # Transmit a standard STOMP frame.
56
+ def send_frame(function, header = {}, content = {})
57
+ frame = "#{function.to_s.upcase}\n"
58
+ header['content-length'] = content.to_s.length
59
+ header.each do |key, val|
60
+ frame += "#{key.to_s}:#{val.to_s}\n"
61
+ end
62
+ frame += "\n"
63
+ frame += "#{content.to_s}\000"
64
+ @sock.puts(frame)
65
+ end
66
+
67
+ # Receive a standard STOMP frame.
68
+ def receive_frame(timeout = 0)
69
+ receive_data(timeout)
70
+ parse_frame
71
+ end
72
+
73
+ # Receive data waiting on a socket. If timeout is passed, block for this many seconds,
74
+ # otherwise don't block, return nil if no frame is waiting.
75
+ def receive_data(timeout = 0)
76
+ sock_ready = select([@sock], nil, nil, timeout)
77
+ return nil if !sock_ready
78
+ @buffer += @sock.recv(1024)
79
+ end
80
+
81
+ # Parse the instance buffer and pick out one frame. If one entire frame is not available
82
+ # in the buffer, returns nil.
83
+ def parse_frame
84
+ return nil if !@buffer["\000"]
85
+
86
+ cmd = header_text = nil
87
+ @buffer.lstrip!
88
+ raise CorruptFrame.new("No end to header found.") unless @buffer.include?("\n\n")
89
+ begin
90
+ cmd = @buffer.slice!(0..@buffer.index("\n")).chomp
91
+ header_text = @buffer.slice!(0..@buffer.index("\n\n")+1).chomp
92
+ rescue ArgumentError
93
+ raise CorruptFrame.new
94
+ end
95
+ raise CorruptHeader.new("Found null in header.") if header_text.include?("\000")
96
+
97
+ # split the header text up into a proper hash
98
+ header = {}
99
+ header_text.split("\n").each do |keyval|
100
+ key,val = keyval.split(':')
101
+ header[key] = val
102
+ end
103
+
104
+ # content runs until the first null, or per the content-length header if present.
105
+ content_length = @buffer.index("\000")
106
+ content_length = header['content-length'].to_i if header['content-length']
107
+ content = ''
108
+ if(@buffer.length) < content_length then
109
+ # turns out we don't have a full frame after all! push the cmd/header back in.
110
+ @buffer = "#{cmd}\n#{header_text}\n\n#{buffer}"
111
+ return nil
112
+ puts "NIL!"
113
+ end
114
+ if(content_length > 0) then
115
+ content = @buffer[0..content_length-1]
116
+ @buffer[0..content_length] = ''
117
+ else
118
+ content = nil
119
+ @buffer[0] = ''
120
+ end
121
+
122
+ raise InvalidFrameType.new unless ['CONNECTED', 'RECEIPT', 'MESSAGE', 'ERROR'].include?(cmd)
123
+
124
+ return StompMq::Frame.new(cmd, header, content)
125
+ end
126
+
127
+ def buffer=(buffer)
128
+ @buffer = buffer
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,12 @@
1
+ module StompMq
2
+ # Holds a STOMP frame of any type.
3
+ class Frame
4
+ attr_reader :cmd, :header, :content
5
+
6
+ def initialize(cmd, header, content)
7
+ @cmd = cmd
8
+ @header = header
9
+ @content = content
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ module StompMq
2
+ # Holds a STOMP message.
3
+ class Message
4
+ attr_reader :header, :content
5
+
6
+ def initialize(header, content)
7
+ @header = header
8
+ @content = content
9
+ end
10
+ end
11
+ end
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: StompMq
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.1"
5
+ platform: ruby
6
+ authors:
7
+ - Sarah Nordstrom
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-09-01 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: sarahemm@sarahemm.net
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ files:
25
+ - lib/stompmq
26
+ - lib/stompmq/connection.rb
27
+ - lib/stompmq/frame.rb
28
+ - lib/stompmq/message.rb
29
+ - lib/stompmq.rb
30
+ - README
31
+ has_rdoc: true
32
+ homepage: http://www.rubyforge.org/stompmq/
33
+ post_install_message:
34
+ rdoc_options: []
35
+
36
+ require_paths:
37
+ - lib
38
+ required_ruby_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: "0"
43
+ version:
44
+ required_rubygems_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: "0"
49
+ version:
50
+ requirements: []
51
+
52
+ rubyforge_project: stompmq
53
+ rubygems_version: 1.0.1
54
+ signing_key:
55
+ specification_version: 2
56
+ summary: Support for the STOMP messaging protocol in Ruby.
57
+ test_files: []
58
+