stompserver_ng 1.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +159 -0
- data/Manifest.txt +71 -0
- data/README.txt +172 -0
- data/Rakefile +38 -0
- data/STATUS +5 -0
- data/bin/stompserver_ng +63 -0
- data/client/README.txt +1 -0
- data/client/both.rb +25 -0
- data/client/consume.rb +14 -0
- data/client/send.rb +17 -0
- data/config/stompserver_ng.conf +11 -0
- data/etc/19xcompat/notes.txt +223 -0
- data/etc/arutils/README-activerecord.txt +78 -0
- data/etc/arutils/cre_mysql.rb +34 -0
- data/etc/arutils/cre_postgres.rb +33 -0
- data/etc/arutils/cre_sqlite3.rb +28 -0
- data/etc/arutils/mysql_boot.sql +12 -0
- data/etc/arutils/postgres_boot.sql +14 -0
- data/etc/database.mysql.yml +9 -0
- data/etc/database.postgres.yml +9 -0
- data/etc/passwd.example +3 -0
- data/etc/ppqinfo.rb +15 -0
- data/etc/runserver.sh +17 -0
- data/etc/stompserver_ng +50 -0
- data/etc/stompserver_ng.conf +13 -0
- data/lib/stomp_server_ng.rb +471 -0
- data/lib/stomp_server_ng/protocols/http.rb +128 -0
- data/lib/stomp_server_ng/protocols/stomp.rb +407 -0
- data/lib/stomp_server_ng/qmonitor.rb +58 -0
- data/lib/stomp_server_ng/queue.rb +248 -0
- data/lib/stomp_server_ng/queue/activerecord_queue.rb +118 -0
- data/lib/stomp_server_ng/queue/ar_message.rb +21 -0
- data/lib/stomp_server_ng/queue/ar_reconnect.rb +18 -0
- data/lib/stomp_server_ng/queue/dbm_queue.rb +72 -0
- data/lib/stomp_server_ng/queue/file_queue.rb +56 -0
- data/lib/stomp_server_ng/queue/memory_queue.rb +64 -0
- data/lib/stomp_server_ng/queue_manager.rb +302 -0
- data/lib/stomp_server_ng/stomp_auth.rb +26 -0
- data/lib/stomp_server_ng/stomp_frame.rb +32 -0
- data/lib/stomp_server_ng/stomp_frame_recognizer.rb +77 -0
- data/lib/stomp_server_ng/stomp_id.rb +32 -0
- data/lib/stomp_server_ng/stomp_user.rb +17 -0
- data/lib/stomp_server_ng/test_server.rb +21 -0
- data/lib/stomp_server_ng/topic_manager.rb +46 -0
- data/setup.rb +1585 -0
- data/stompserver_ng.gemspec +136 -0
- data/test/devserver/props.yaml +5 -0
- data/test/devserver/runserver.sh +16 -0
- data/test/devserver/stompserver_ng.dbm.conf +12 -0
- data/test/devserver/stompserver_ng.file.conf +12 -0
- data/test/devserver/stompserver_ng.memory.conf +12 -0
- data/test/noserver/mocklogger.rb +12 -0
- data/test/noserver/test_queue_manager.rb +134 -0
- data/test/noserver/test_stomp_frame.rb +138 -0
- data/test/noserver/test_topic_manager.rb +79 -0
- data/test/noserver/ts_all_no_server.rb +12 -0
- data/test/props.yaml +5 -0
- data/test/runalltests.sh +14 -0
- data/test/runtest.sh +4 -0
- data/test/test_0000_base.rb +107 -0
- data/test/test_0001_conn.rb +47 -0
- data/test/test_0002_conn_sr.rb +94 -0
- data/test/test_0006_client.rb +41 -0
- data/test/test_0011_send_recv.rb +74 -0
- data/test/test_0015_ack_conn.rb +78 -0
- data/test/test_0017_ack_client.rb +78 -0
- data/test/test_0019_ack_no_ack.rb +145 -0
- data/test/test_0022_ack_noack_conn.rb +123 -0
- data/test/test_0030_subscr_id.rb +44 -0
- data/test/test_0040_receipt_conn.rb +87 -0
- data/test/ts_all_server.rb +10 -0
- metadata +196 -0
@@ -0,0 +1,128 @@
|
|
1
|
+
|
2
|
+
class Mongrel::HttpRequest
|
3
|
+
attr_reader :body, :params
|
4
|
+
|
5
|
+
def initialize(params, initial_body)
|
6
|
+
@params = params
|
7
|
+
@body = StringIO.new
|
8
|
+
@body.write params.http_body
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module StompServer
|
13
|
+
module StompServer::Protocols
|
14
|
+
|
15
|
+
class Http < EventMachine::Connection
|
16
|
+
|
17
|
+
def initialize *args
|
18
|
+
super
|
19
|
+
@buf = ''
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
def post_init
|
24
|
+
@parser = Mongrel::HttpParser.new
|
25
|
+
@params = Mongrel::HttpParams.new
|
26
|
+
@nparsed = 0
|
27
|
+
@request = nil
|
28
|
+
@request_method = nil
|
29
|
+
@request_length = 0
|
30
|
+
@state = :headers
|
31
|
+
@headers_out = {'Content-Length' => 0, 'Content-Type' => 'text/plain; charset=UTF-8'}
|
32
|
+
end
|
33
|
+
|
34
|
+
def receive_data data
|
35
|
+
parse_request(data)
|
36
|
+
end
|
37
|
+
|
38
|
+
def parse_request data
|
39
|
+
@buf << data
|
40
|
+
case @state
|
41
|
+
when :headers
|
42
|
+
@nparsed = @parser.execute(@params, @buf, @nparsed)
|
43
|
+
if @parser.finished?
|
44
|
+
@request = Mongrel::HttpRequest.new(@params,@buf)
|
45
|
+
@request_method = @request.params[Mongrel::Const::REQUEST_METHOD]
|
46
|
+
content_length = @request.params[Mongrel::Const::CONTENT_LENGTH].to_i
|
47
|
+
@request_length = @nparsed + content_length
|
48
|
+
@remain = content_length - @request.params.http_body.length
|
49
|
+
if @remain <= 0
|
50
|
+
@buf = @buf[@request_length+1..-1] || ''
|
51
|
+
process_request
|
52
|
+
post_init
|
53
|
+
return
|
54
|
+
end
|
55
|
+
@request.body.write @request.params.http_body
|
56
|
+
@state = :body
|
57
|
+
end
|
58
|
+
when :body
|
59
|
+
@remain -= @request.body.write data[0...@remain]
|
60
|
+
if @remain <= 0
|
61
|
+
@buf = @buf[@request_length+1..-1] || ''
|
62
|
+
process_request
|
63
|
+
post_init
|
64
|
+
return
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def process_request
|
70
|
+
begin
|
71
|
+
@request.body.rewind
|
72
|
+
dest = @request.params[Mongrel::Const::REQUEST_PATH]
|
73
|
+
case @request_method
|
74
|
+
when 'PUT'
|
75
|
+
@frame = StompServer::StompFrame.new
|
76
|
+
@frame.command = 'SEND'
|
77
|
+
@frame.body = @request.body.read
|
78
|
+
@frame.headers['destination'] = dest
|
79
|
+
if @@queue_manager.enqueue(@frame)
|
80
|
+
create_response('200','Message Enqueued')
|
81
|
+
else
|
82
|
+
create_response('500','Error enqueueing message')
|
83
|
+
end
|
84
|
+
when 'GET'
|
85
|
+
if frame = @@queue_manager.dequeue(dest)
|
86
|
+
@headers_out['message-id'] = frame.headers['message-id']
|
87
|
+
create_response('200',frame.body)
|
88
|
+
else
|
89
|
+
create_response('404','No messages in queue')
|
90
|
+
end
|
91
|
+
else
|
92
|
+
create_response('500','Invalid Command')
|
93
|
+
end
|
94
|
+
rescue Exception => e
|
95
|
+
puts "err: #{e} #{e.backtrace.join("\n")}"
|
96
|
+
create_response('500',e)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def unbind
|
101
|
+
puts "Closing connection"
|
102
|
+
close_connection_after_writing
|
103
|
+
end
|
104
|
+
|
105
|
+
def create_response(code,response_text)
|
106
|
+
response = ''
|
107
|
+
@headers_out['Content-Length'] = response_text.size
|
108
|
+
|
109
|
+
case code
|
110
|
+
when '200'
|
111
|
+
response << "HTTP/1.1 200 OK\r\n"
|
112
|
+
when '500'
|
113
|
+
response << "HTTP/1.1 500 Server Error\r\n"
|
114
|
+
when '404'
|
115
|
+
response << "HTTP/1.1 404 Message Not Found\r\n"
|
116
|
+
end
|
117
|
+
@headers_out.each_pair do |key, value|
|
118
|
+
response << "#{key}:#{value}\r\n"
|
119
|
+
end
|
120
|
+
response << "\r\n"
|
121
|
+
response << response_text
|
122
|
+
send_data(response)
|
123
|
+
unbind if @request.params['HTTP_CONNECTION'] == 'close'
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,407 @@
|
|
1
|
+
#
|
2
|
+
module StompServer
|
3
|
+
module StompServer::Protocols
|
4
|
+
#
|
5
|
+
VALID_COMMANDS = [
|
6
|
+
:abort, # Explicit method supplied
|
7
|
+
:ack, # Explicit method supplied
|
8
|
+
:begin, # Explicit method supplied
|
9
|
+
:commit, # Explicit method supplied
|
10
|
+
:connect, # Explicit method supplied
|
11
|
+
:disconnect, # Explicit method supplied
|
12
|
+
:send, # Explicit method supplied
|
13
|
+
:subscribe, # Explicit method supplied
|
14
|
+
:unsubscribe # Explicit method supplied
|
15
|
+
]
|
16
|
+
#
|
17
|
+
# = Stomp Protocol Handler.
|
18
|
+
#
|
19
|
+
class Stomp < EventMachine::Connection
|
20
|
+
|
21
|
+
attr_reader :session_id
|
22
|
+
|
23
|
+
# Protocol handler initialization
|
24
|
+
def initialize(*args)
|
25
|
+
super(*args)
|
26
|
+
#
|
27
|
+
@@log = Logger.new(STDOUT)
|
28
|
+
@@log.level = StompServer::LogHelper.get_loglevel()
|
29
|
+
#
|
30
|
+
@@options = (Hash === args.last) ? args.pop : {}
|
31
|
+
# Arguments are passed from EventMachine::start_server
|
32
|
+
@@auth_required = args[0]
|
33
|
+
@@queue_manager = args[1]
|
34
|
+
@@topic_manager = args[2]
|
35
|
+
@@stompauth = args[3]
|
36
|
+
#
|
37
|
+
# N.B.: The session ID is an instance variable!
|
38
|
+
#
|
39
|
+
if @@options[:session_cache] == 0
|
40
|
+
lt = Time.now
|
41
|
+
@session_id = "ssng_#{lt.to_f}"
|
42
|
+
else
|
43
|
+
@session_id = StompServer::SessionIDManager.get_cache_id(@@options[:session_cache])
|
44
|
+
end
|
45
|
+
@@log.debug("#{@session_id} #{self} Session ID assigned")
|
46
|
+
#
|
47
|
+
@@log.warn("#{@session_id} #{self} Protocol initialization complete")
|
48
|
+
end
|
49
|
+
|
50
|
+
# :stopdoc:
|
51
|
+
#
|
52
|
+
# <tt>EM::Connection.close_connection()</tt>
|
53
|
+
#
|
54
|
+
# <tt>EM::Connection.close_connection_after_writing()</tt>
|
55
|
+
#
|
56
|
+
# <tt>EM::Connection.comm_inactivity_timeout()</tt>
|
57
|
+
#
|
58
|
+
# <tt>EM::Connection.comm_inactivity_timeout=(value)</tt>
|
59
|
+
#
|
60
|
+
# <tt>EM::Connection.connection_completed()</tt>
|
61
|
+
#
|
62
|
+
# <tt>EM::Connection.detach()</tt>
|
63
|
+
#
|
64
|
+
# <tt>EM::Connection.error?()</tt>
|
65
|
+
#
|
66
|
+
# <tt>EM::Connection.get_peer_cert()</tt>
|
67
|
+
#
|
68
|
+
# <tt>EM::Connection.get_peername()</tt>
|
69
|
+
#
|
70
|
+
# <tt>EM::Connection.get_pid()</tt>
|
71
|
+
#
|
72
|
+
# <tt>EM::Connection.get_sock_opt(level,option)</tt>
|
73
|
+
#
|
74
|
+
# <tt>EM::Connection.get_sockname()</tt>
|
75
|
+
#
|
76
|
+
# <tt>EM::Connection.get_status()</tt>
|
77
|
+
#
|
78
|
+
# <tt>EM::Connection.notify_readable=(mode)</tt>
|
79
|
+
#
|
80
|
+
# <tt>EM::Connection.notify_readable?()</tt>
|
81
|
+
#
|
82
|
+
# <tt>EM::Connection.notify_writable=(mode)</tt>
|
83
|
+
#
|
84
|
+
# <tt>EM::Connection.notify_writable?()</tt>
|
85
|
+
#
|
86
|
+
# <tt>EM::Connection.pause()</tt>
|
87
|
+
#
|
88
|
+
# <tt>EM::Connection.paused?()</tt>
|
89
|
+
#
|
90
|
+
# <tt>EM::Connection.pending_connect_timeout()</tt>
|
91
|
+
#
|
92
|
+
# <tt>EM::Connection.pending_connect_timeout=(value)</tt>
|
93
|
+
#
|
94
|
+
|
95
|
+
# :startdoc:
|
96
|
+
|
97
|
+
# <tt>EM::Connection.post_init()</tt>
|
98
|
+
#
|
99
|
+
# Protocol handler post initialization.
|
100
|
+
def post_init
|
101
|
+
@sfr = StompServer::StompFrameRecognizer.new
|
102
|
+
@transactions = {}
|
103
|
+
@connected = false
|
104
|
+
@@log.debug("#{@session_id} protocol post_init complete")
|
105
|
+
end
|
106
|
+
|
107
|
+
# :stopdoc:
|
108
|
+
|
109
|
+
#
|
110
|
+
# <tt>EM::Connection.proxy_incoming_to(conn,bufsize=0)</tt>
|
111
|
+
#
|
112
|
+
# <tt>EM::Connection.proxy_target_unbound()</tt>
|
113
|
+
#
|
114
|
+
|
115
|
+
# :startdoc:
|
116
|
+
|
117
|
+
# <tt>EM::Connection.receive_data(data)</tt>
|
118
|
+
#
|
119
|
+
# Delegate to stomp_receive_data helper.
|
120
|
+
#
|
121
|
+
def receive_data(data)
|
122
|
+
stomp_receive_data(data)
|
123
|
+
end
|
124
|
+
|
125
|
+
# :stopdoc:
|
126
|
+
|
127
|
+
# <tt>EM::Connection.reconnect(server,port)</tt>
|
128
|
+
#
|
129
|
+
# <tt>EM::Connection.resume()</tt>
|
130
|
+
#
|
131
|
+
|
132
|
+
# :startdoc:
|
133
|
+
|
134
|
+
# <tt>EM::Connection.send_data(data)</tt>
|
135
|
+
#
|
136
|
+
# Just calls super.
|
137
|
+
#
|
138
|
+
def send_data(data)
|
139
|
+
super(data)
|
140
|
+
end
|
141
|
+
|
142
|
+
# :stopdoc:
|
143
|
+
|
144
|
+
# <tt>EM::Connection.send_datagram(data,recipient_address,recipient_port)</tt>
|
145
|
+
#
|
146
|
+
# <tt>EM::Connection.send_file_data(filename)</tt>
|
147
|
+
#
|
148
|
+
# <tt>EM::Connection.set_comm_inactivity_timeout(value)</tt>
|
149
|
+
#
|
150
|
+
# <tt>EM::Connection.set_pending_connect_timeout(value)</tt>
|
151
|
+
#
|
152
|
+
# <tt>EM::Connection.ssl_handshake_completed()</tt>
|
153
|
+
#
|
154
|
+
# <tt>EM::Connection.ssl_verify_peer(cert)</tt>
|
155
|
+
#
|
156
|
+
# <tt>EM::Connection.start_tls(args={})</tt>
|
157
|
+
#
|
158
|
+
# <tt>EM::Connection.stop_proxying()</tt>
|
159
|
+
#
|
160
|
+
# <tt>EM::Connection.stream_file_data(filename, args={})</tt>
|
161
|
+
#
|
162
|
+
|
163
|
+
# :startdoc:
|
164
|
+
|
165
|
+
# <tt>EM::Connection.unbind()</tt>
|
166
|
+
#
|
167
|
+
# Unbind the connection.
|
168
|
+
#
|
169
|
+
def unbind()
|
170
|
+
@@log.warn "#{@session_id} Unbind called"
|
171
|
+
@connected = false
|
172
|
+
@@queue_manager.disconnect(self)
|
173
|
+
@@topic_manager.disconnect(self)
|
174
|
+
end
|
175
|
+
|
176
|
+
# :stopdoc:
|
177
|
+
|
178
|
+
# Stomp Protocol Verbs
|
179
|
+
|
180
|
+
# :startdoc:
|
181
|
+
#
|
182
|
+
# Stomp Protocol - ABORT
|
183
|
+
#
|
184
|
+
def abort(frame, trans=nil)
|
185
|
+
raise "#{@session_id} Missing transaction" unless trans
|
186
|
+
raise "#{@session_id} transaction does not exist" unless @transactions.has_key?(trans)
|
187
|
+
@transactions.delete(trans)
|
188
|
+
end
|
189
|
+
#
|
190
|
+
# Stomp Protocol - ACK
|
191
|
+
#
|
192
|
+
# Delegated to the queue manager.
|
193
|
+
#
|
194
|
+
def ack(frame)
|
195
|
+
@@queue_manager.ack(self, frame)
|
196
|
+
end
|
197
|
+
#
|
198
|
+
# Stomp Protocol - BEGIN
|
199
|
+
#
|
200
|
+
def begin(frame, trans=nil)
|
201
|
+
raise "#{@session_id} Missing transaction" unless trans
|
202
|
+
raise "#{@session_id} transaction exists" if @transactions.has_key?(trans)
|
203
|
+
@transactions[trans] = []
|
204
|
+
end
|
205
|
+
#
|
206
|
+
# Stomp Protocol - COMMIT
|
207
|
+
#
|
208
|
+
def commit(frame, trans=nil)
|
209
|
+
raise "#{@session_id} Missing transaction" unless trans
|
210
|
+
raise "#{@session_id} transaction does not exist" unless @transactions.has_key?(trans)
|
211
|
+
#
|
212
|
+
(@transactions[trans]).each do |frame|
|
213
|
+
frame.headers.delete('transaction')
|
214
|
+
process_frame(frame)
|
215
|
+
end
|
216
|
+
@transactions.delete(trans)
|
217
|
+
end
|
218
|
+
#
|
219
|
+
# Stomp Protocol - CONNECT
|
220
|
+
#
|
221
|
+
def connect(frame)
|
222
|
+
if @@auth_required
|
223
|
+
unless frame.headers['login'] and frame.headers['passcode'] and @@stompauth.authorized[frame.headers['login']] == frame.headers['passcode']
|
224
|
+
raise "#{@session_id} {self} Invalid Login"
|
225
|
+
end
|
226
|
+
end
|
227
|
+
@@log.warn "#{@session_id} Connecting"
|
228
|
+
response = StompServer::StompFrame.new("CONNECTED", {'session' => @session_id})
|
229
|
+
#
|
230
|
+
stomp_send_data(response)
|
231
|
+
@connected = true
|
232
|
+
end
|
233
|
+
#
|
234
|
+
# Stomp Protocol - DISCONNECT
|
235
|
+
#
|
236
|
+
def disconnect(frame)
|
237
|
+
@@log.warn "#{@session_id} Polite disconnect"
|
238
|
+
close_connection_after_writing
|
239
|
+
end
|
240
|
+
#
|
241
|
+
# Stomp Protocol - SEND
|
242
|
+
#
|
243
|
+
# The stomp SEND verb is by routing through:
|
244
|
+
#
|
245
|
+
# * receive_data(data)
|
246
|
+
# * stomp_receive_data
|
247
|
+
# * process_frames
|
248
|
+
# * process_frame
|
249
|
+
# * use Object#__send__ to call this method
|
250
|
+
#
|
251
|
+
def send(frame)
|
252
|
+
# set message id
|
253
|
+
if frame.dest.match(%r|^/queue|)
|
254
|
+
@@queue_manager.sendmsg(frame)
|
255
|
+
else
|
256
|
+
frame.headers['message-id'] = "msg-#stompcma-#{@@topic_manager.next_index}"
|
257
|
+
@@topic_manager.sendmsg(frame)
|
258
|
+
end
|
259
|
+
end
|
260
|
+
#
|
261
|
+
#
|
262
|
+
# Stomp Protocol - SUBSCRIBE
|
263
|
+
#
|
264
|
+
# Delegated to the queue or topic manager.
|
265
|
+
#
|
266
|
+
def subscribe(frame)
|
267
|
+
use_ack = false
|
268
|
+
use_ack = true if frame.headers['ack'] == 'client'
|
269
|
+
#
|
270
|
+
if frame.headers['id']
|
271
|
+
subid = frame.headers['id']
|
272
|
+
elsif frame.headers[:id]
|
273
|
+
subid = frame.headers[:id]
|
274
|
+
else
|
275
|
+
subid = nil
|
276
|
+
end
|
277
|
+
#
|
278
|
+
if frame.dest =~ %r|^/queue|
|
279
|
+
@@queue_manager.subscribe(frame.dest, self, use_ack, subid)
|
280
|
+
else
|
281
|
+
@@topic_manager.subscribe(frame.dest, self)
|
282
|
+
end
|
283
|
+
end
|
284
|
+
#
|
285
|
+
# Stomp Protocol - UNSUBSCRIBE
|
286
|
+
#
|
287
|
+
# Delegated to the queue or topic manager.
|
288
|
+
#
|
289
|
+
def unsubscribe(frame)
|
290
|
+
if frame.dest =~ %r|^/queue|
|
291
|
+
@@queue_manager.unsubscribe(frame.dest,self)
|
292
|
+
else
|
293
|
+
@@topic_manager.unsubscribe(frame.dest,self)
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
# :stopdoc:
|
298
|
+
|
299
|
+
# Helper methods
|
300
|
+
|
301
|
+
# :startdoc:
|
302
|
+
#
|
303
|
+
# stomp_receive_data
|
304
|
+
#
|
305
|
+
# Called from <tt>EM::Connection.receive_data(data)</tt>. This is where
|
306
|
+
# we begin processing a set of data fresh off the wire.
|
307
|
+
#
|
308
|
+
def stomp_receive_data(data)
|
309
|
+
begin
|
310
|
+
# Limit log message length.
|
311
|
+
logdata = data
|
312
|
+
logdata = data[0..256] + "...truncated..." if data.length > 256
|
313
|
+
@@log.debug "#{@session_id} receive_data: #{logdata.inspect}"
|
314
|
+
# Append all data to the recognizer buffer.
|
315
|
+
@sfr << data
|
316
|
+
# Process any stomp frames in this set of data.
|
317
|
+
process_frames
|
318
|
+
rescue Exception => e
|
319
|
+
@@log.error "#{@session_id} err: #{e} #{e.backtrace.join("\n")}"
|
320
|
+
send_error(e.to_s)
|
321
|
+
close_connection_after_writing
|
322
|
+
end
|
323
|
+
end
|
324
|
+
#
|
325
|
+
# process_frames
|
326
|
+
#
|
327
|
+
# Handle all stomp frames currently in the recognizer's accumulated
|
328
|
+
# array of frames.
|
329
|
+
#
|
330
|
+
def process_frames
|
331
|
+
frame = nil
|
332
|
+
process_frame(frame) while frame = @sfr.frames.shift
|
333
|
+
end
|
334
|
+
#
|
335
|
+
# process_frame
|
336
|
+
#
|
337
|
+
# Process and individual stomp frame.
|
338
|
+
#
|
339
|
+
def process_frame(frame)
|
340
|
+
cmd = frame.command.downcase.to_sym
|
341
|
+
raise "#{@session_id} #{self} Unhandled frame: #{cmd}" unless VALID_COMMANDS.include?(cmd)
|
342
|
+
raise "#{@session_id} #{self} Not connected" if !@connected && cmd != :connect
|
343
|
+
@@log.debug("#{@session_id} process_frame: #{frame.command}")
|
344
|
+
# Add session ID to the frame headers
|
345
|
+
frame.headers['session'] = @session_id
|
346
|
+
# Send receipt first if required
|
347
|
+
send_receipt(frame.headers['receipt']) if frame.headers['receipt']
|
348
|
+
#
|
349
|
+
if trans = frame.headers['transaction']
|
350
|
+
# Handle transactional frame if required.
|
351
|
+
handle_transaction(frame, trans, cmd)
|
352
|
+
else
|
353
|
+
# Otherwise, just route the non-transactional frame.
|
354
|
+
__send__(cmd, frame) # Object#send alias call
|
355
|
+
end
|
356
|
+
end
|
357
|
+
#
|
358
|
+
# handle_transaction
|
359
|
+
#
|
360
|
+
def handle_transaction(frame, trans, cmd)
|
361
|
+
if [:begin, :commit, :abort].include?(cmd)
|
362
|
+
__send__(cmd, frame, trans) # Object#send alias call
|
363
|
+
else
|
364
|
+
raise "#{@session_id} transaction does not exist" unless @transactions.has_key?(trans)
|
365
|
+
@transactions[trans] << frame
|
366
|
+
end
|
367
|
+
end
|
368
|
+
#
|
369
|
+
# send_error
|
370
|
+
#
|
371
|
+
# Send a single error frame.
|
372
|
+
#
|
373
|
+
def send_error(msg)
|
374
|
+
send_frame("ERROR",{'message' => 'See below'},msg)
|
375
|
+
end
|
376
|
+
#
|
377
|
+
# send_frame
|
378
|
+
#
|
379
|
+
# Send an individual stomp frame.
|
380
|
+
#
|
381
|
+
def send_frame(command, headers={}, body='')
|
382
|
+
headers['content-length'] = body.size.to_s
|
383
|
+
response = StompServer::StompFrame.new(command, headers, body)
|
384
|
+
stomp_send_data(response)
|
385
|
+
end
|
386
|
+
#
|
387
|
+
# send_receipt
|
388
|
+
#
|
389
|
+
# Send a single receipt frame.
|
390
|
+
#
|
391
|
+
def send_receipt(id)
|
392
|
+
send_frame("RECEIPT", { 'receipt-id' => id})
|
393
|
+
end
|
394
|
+
#
|
395
|
+
# stomp_send_data
|
396
|
+
#
|
397
|
+
def stomp_send_data(frame)
|
398
|
+
@@log.debug "#{@session_id} Sending frame #{frame.to_s}"
|
399
|
+
send_data(frame.to_s)
|
400
|
+
end
|
401
|
+
|
402
|
+
#
|
403
|
+
end # class Stomp < EventMachine::Connection
|
404
|
+
#
|
405
|
+
end # module StompServer::Protocols
|
406
|
+
end # module StompServer
|
407
|
+
|