stompserver 0.9.7 → 0.9.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +8 -6
- data/Manifest.txt +25 -7
- data/README.txt +136 -19
- data/Rakefile +8 -8
- data/STATUS +5 -0
- data/bin/stompserver +43 -19
- 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.conf +11 -0
- data/etc/passwd.example +3 -0
- data/lib/stomp_server.rb +132 -157
- data/lib/stomp_server/protocols/http.rb +128 -0
- data/lib/stomp_server/protocols/stomp.rb +186 -0
- data/lib/stomp_server/queue.rb +140 -0
- data/lib/stomp_server/queue/activerecord_queue.rb +104 -0
- data/lib/stomp_server/queue/ar_message.rb +5 -0
- data/lib/stomp_server/queue/dbm_queue.rb +68 -0
- data/lib/stomp_server/queue/file_queue.rb +47 -0
- data/lib/stomp_server/queue/memory_queue.rb +58 -0
- data/lib/stomp_server/queue_manager.rb +209 -0
- data/lib/stomp_server/stomp_auth.rb +22 -0
- data/lib/{stomp_frame.rb → stomp_server/stomp_frame.rb} +7 -7
- data/lib/stomp_server/stomp_id.rb +21 -0
- data/lib/stomp_server/stomp_user.rb +17 -0
- data/lib/stomp_server/test_server.rb +21 -0
- data/lib/{topic_manager.rb → stomp_server/topic_manager.rb} +14 -2
- data/test/tesly.rb +15 -0
- data/test/test_queue_manager.rb +39 -32
- data/test/test_stomp_frame.rb +3 -16
- data/test/test_topic_manager.rb +3 -4
- data/{test → test_todo}/test_stomp_server.rb +0 -27
- metadata +56 -23
- data/lib/frame_journal.rb +0 -135
- data/lib/queue_manager.rb +0 -81
- data/test/test_frame_journal.rb +0 -14
@@ -0,0 +1,22 @@
|
|
1
|
+
module StompServer
|
2
|
+
|
3
|
+
class StompAuth
|
4
|
+
attr_accessor :authorized
|
5
|
+
|
6
|
+
def initialize(passfile='.passwd')
|
7
|
+
@passfile = passfile
|
8
|
+
@authorized = Hash.new
|
9
|
+
if File.exists?(@passfile)
|
10
|
+
file = File.read(@passfile)
|
11
|
+
file.split(/\n/).each do |data|
|
12
|
+
next if data =~/^\s*#/
|
13
|
+
data.gsub(/\s/,'')
|
14
|
+
if data =~ /^\s*(\S+)\s*:\s*(.*?)\s*$/
|
15
|
+
@authorized[$1] = $2
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
puts "Authorized users #{@authorized.keys}" if $DEBUG
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
|
2
|
+
module StompServer
|
1
3
|
class StompFrame
|
2
4
|
attr_accessor :command, :headers, :body
|
3
5
|
def initialize(command=nil, headers=nil, body=nil)
|
@@ -5,7 +7,7 @@ class StompFrame
|
|
5
7
|
@headers = headers || {}
|
6
8
|
@body = body || ''
|
7
9
|
end
|
8
|
-
|
10
|
+
|
9
11
|
def to_s
|
10
12
|
result = @command + "\n"
|
11
13
|
@headers['content-length'] = @body.size.to_s if @body.include?(0)
|
@@ -23,13 +25,14 @@ class StompFrame
|
|
23
25
|
end
|
24
26
|
end
|
25
27
|
|
28
|
+
|
26
29
|
class StompFrameRecognizer
|
27
30
|
attr_accessor :frames
|
28
31
|
|
29
32
|
def initialize
|
30
33
|
@buffer = ''
|
31
34
|
@body_length = nil
|
32
|
-
@frame = StompFrame.new
|
35
|
+
@frame = StompServer::StompFrame.new
|
33
36
|
@frames = []
|
34
37
|
end
|
35
38
|
|
@@ -38,7 +41,7 @@ class StompFrameRecognizer
|
|
38
41
|
@frame.body = @buffer[0...len]
|
39
42
|
@buffer = @buffer[len+1..-1]
|
40
43
|
@frames << @frame
|
41
|
-
@frame = StompFrame.new
|
44
|
+
@frame = StompServer::StompFrame.new
|
42
45
|
end
|
43
46
|
|
44
47
|
def parse_binary_body
|
@@ -65,10 +68,6 @@ class StompFrameRecognizer
|
|
65
68
|
|
66
69
|
# body_length is nil, if there is no content-length, otherwise it is the length (as in integer)
|
67
70
|
@body_length = @frame.headers['content-length'] && @frame.headers['content-length'].to_i
|
68
|
-
else
|
69
|
-
# saftey valve to dump bad (DOSA?) headers/frames
|
70
|
-
# this should be a constant or read out of a configuration file
|
71
|
-
raise RuntimeError.new("Invalid stompframe (possible DOSA)") if @buffer.length > 4096
|
72
71
|
end
|
73
72
|
end
|
74
73
|
|
@@ -94,3 +93,4 @@ class StompFrameRecognizer
|
|
94
93
|
parse
|
95
94
|
end
|
96
95
|
end
|
96
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
# This class is instantiated in all the queue storage classes, plus the queue manager (for the statistic messages). It generates a unique
|
3
|
+
# id for each message. The caller passes an additional identifier that is appended message-id, which is usually the id of the frame and is
|
4
|
+
# different for each storage class.
|
5
|
+
|
6
|
+
require 'socket'
|
7
|
+
require 'resolv-replace'
|
8
|
+
|
9
|
+
module StompServer
|
10
|
+
class StompId
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@host = Socket.gethostname.to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
def [](id)
|
17
|
+
msgid = sprintf("%.6f",Time.now.to_f).to_s.sub('.','-')
|
18
|
+
msgid = @host + '-' + msgid + '-' + id.to_s
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
|
2
|
+
# Used when accessing queues/topics outside of EM
|
3
|
+
require 'stomp_id'
|
4
|
+
require 'stomp_frame'
|
5
|
+
$MULTIUSER = true
|
6
|
+
|
7
|
+
module StompServer
|
8
|
+
class StompUser
|
9
|
+
attr_accessor :data
|
10
|
+
def initialize
|
11
|
+
@data = []
|
12
|
+
end
|
13
|
+
def stomp_send_data(data)
|
14
|
+
@data << data.to_s
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'eventmachine'
|
3
|
+
|
4
|
+
module StompServer
|
5
|
+
module TestServer
|
6
|
+
|
7
|
+
|
8
|
+
def post_init
|
9
|
+
@transactions = {}
|
10
|
+
@connected = false
|
11
|
+
end
|
12
|
+
|
13
|
+
def receive_data(data)
|
14
|
+
end
|
15
|
+
|
16
|
+
def unbind
|
17
|
+
p "Unbind called" if $DEBUG
|
18
|
+
@connected = false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,10 +1,22 @@
|
|
1
1
|
# topic - non persistent, sent to all interested parties
|
2
2
|
|
3
|
+
module StompServer
|
3
4
|
class TopicManager
|
5
|
+
attr_accessor :frame_index
|
4
6
|
def initialize
|
7
|
+
@frame_index =0
|
5
8
|
@topics = Hash.new { Array.new }
|
9
|
+
puts "TopicManager initialized"
|
6
10
|
end
|
7
11
|
|
12
|
+
def index
|
13
|
+
@frame_index
|
14
|
+
end
|
15
|
+
|
16
|
+
def next_index
|
17
|
+
@frame_index += 1
|
18
|
+
end
|
19
|
+
|
8
20
|
def subscribe(topic, user)
|
9
21
|
@topics[topic] += [user]
|
10
22
|
end
|
@@ -22,9 +34,9 @@ class TopicManager
|
|
22
34
|
def sendmsg(msg)
|
23
35
|
msg.command = "MESSAGE"
|
24
36
|
topic = msg.headers['destination']
|
25
|
-
payload = msg.to_s
|
26
37
|
@topics[topic].each do |user|
|
27
|
-
user.
|
38
|
+
user.stomp_send_data(msg)
|
28
39
|
end
|
29
40
|
end
|
30
41
|
end
|
42
|
+
end
|
data/test/tesly.rb
ADDED
data/test/test_queue_manager.rb
CHANGED
@@ -1,33 +1,55 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
3
|
-
require '
|
4
|
-
require '
|
1
|
+
require 'stomp_server/stomp_id'
|
2
|
+
require 'stomp_server/stomp_frame'
|
3
|
+
require 'stomp_server/queue_manager'
|
4
|
+
require 'stomp_server/queue'
|
5
|
+
require 'stomp_server/queue/file_queue'
|
6
|
+
require 'stomp_server/queue/memory_queue'
|
7
|
+
require 'stomp_server/queue/dbm_queue'
|
8
|
+
require 'test/unit'
|
9
|
+
require 'fileutils'
|
5
10
|
|
6
11
|
class TestQueues < Test::Unit::TestCase
|
12
|
+
|
13
|
+
class MockQueueManager < StompServer::QueueManager
|
14
|
+
def initialize(qstore)
|
15
|
+
@qstore = qstore
|
16
|
+
@queue_stats = Hash.new
|
17
|
+
@queues = Hash.new { Array.new }
|
18
|
+
@pending = Hash.new { Array.new }
|
19
|
+
end
|
20
|
+
end
|
7
21
|
|
8
22
|
class UserMock
|
9
23
|
attr_accessor :data
|
10
24
|
def initialize ; @data = '' ; end
|
11
|
-
def
|
25
|
+
def stomp_send_data(data); @data += data.to_s ; end
|
26
|
+
def connected?;true;end
|
12
27
|
end
|
13
28
|
|
14
29
|
class MessageMock
|
15
|
-
attr_accessor :headers, :data, :command
|
16
|
-
def initialize(dest, msg, id=1)
|
17
|
-
@
|
18
|
-
@
|
30
|
+
attr_accessor :headers, :data, :command, :body
|
31
|
+
def initialize(dest, msg, id=1)
|
32
|
+
@body = msg
|
33
|
+
@headers = {
|
34
|
+
'message-id' => id,
|
35
|
+
'destination' => dest,
|
36
|
+
'content-length' => msg.size.to_s
|
37
|
+
}
|
38
|
+
|
39
|
+
@frame = StompServer::StompFrame.new('MESSAGE', headers, body)
|
40
|
+
@data = @frame.to_s
|
19
41
|
end
|
20
|
-
def
|
21
|
-
|
42
|
+
def to_s ; @data.to_s ; end
|
43
|
+
end
|
44
|
+
|
45
|
+
def teardown
|
46
|
+
FileUtils.rm_rf(".queue_test")
|
22
47
|
end
|
23
48
|
|
24
|
-
FileUtils.rm Dir.glob(".test_queue/*") rescue nil
|
25
|
-
@@journal = FrameJournal.new(".test_queue")
|
26
|
-
|
27
49
|
def setup
|
28
|
-
|
29
|
-
@@
|
30
|
-
@t =
|
50
|
+
FileUtils.rm_rf(".queue_test") if File.directory?('.queue_test')
|
51
|
+
@@qstore = StompServer::FileQueue.new(".queue_test")
|
52
|
+
@t = MockQueueManager.new(@@qstore)
|
31
53
|
end
|
32
54
|
|
33
55
|
def test_subscribe
|
@@ -98,19 +120,4 @@ class TestQueues < Test::Unit::TestCase
|
|
98
120
|
assert_equal('', u2.data)
|
99
121
|
end
|
100
122
|
|
101
|
-
def test_sendmsg_ack
|
102
|
-
u = UserMock.new
|
103
|
-
t = 'fooack'
|
104
|
-
@t.subscribe(t, u, true)
|
105
|
-
|
106
|
-
m1 = MessageMock.new(t, 'foomsg')
|
107
|
-
@t.sendmsg(m1)
|
108
|
-
assert_equal(m1.data, u.data)
|
109
|
-
assert_equal('MESSAGE', m1.command)
|
110
|
-
@t.disconnect(u)
|
111
|
-
|
112
|
-
u2 = UserMock.new
|
113
|
-
@t.subscribe(t, u2)
|
114
|
-
assert_equal(m1.data, u2.data)
|
115
|
-
end
|
116
123
|
end
|
data/test/test_stomp_frame.rb
CHANGED
@@ -1,10 +1,9 @@
|
|
1
|
-
require 'stomp_frame'
|
1
|
+
require 'stomp_server/stomp_frame'
|
2
2
|
require 'test/unit' unless defined? $ZENTEST and $ZENTEST
|
3
|
-
require 'tesly'
|
4
3
|
|
5
4
|
class TestStompFrame < Test::Unit::TestCase
|
6
5
|
def setup
|
7
|
-
@sfr = StompFrameRecognizer.new
|
6
|
+
@sfr = StompServer::StompFrameRecognizer.new
|
8
7
|
end
|
9
8
|
|
10
9
|
def test_simpleframe
|
@@ -57,20 +56,8 @@ FRAME
|
|
57
56
|
assert_equal("bar2", f.headers["foo2"])
|
58
57
|
assert_equal("message body 2\n", f.body)
|
59
58
|
end
|
60
|
-
|
61
|
-
def test_double2
|
62
|
-
data = "SEND\ndestination:/queue/f\ncontent-length: 33\ncontent-type: text/plain; charset=UTF-8\n\n1: Tue Oct 24 12:19:52 -0400 2006\000SEND\ndestination:/queue/f\ncontent-length: 33\ncontent-type: text/plain; charset=UTF-8\n\n2: Tue Oct 24 12:19:52 -0400 2006\000"
|
63
|
-
|
64
|
-
@sfr << data
|
65
|
-
assert_equal(2, @sfr.frames.size)
|
66
|
-
f = @sfr.frames.shift
|
67
|
-
assert_equal(1, @sfr.frames.size)
|
68
|
-
assert_equal("SEND", f.command)
|
69
|
-
assert_equal("/queue/f", f.headers["destination"])
|
70
|
-
assert_match(/1: Tue/, f.body)
|
71
|
-
end
|
72
59
|
|
73
|
-
|
60
|
+
def test_partialframe
|
74
61
|
@sfr << <<FRAME
|
75
62
|
COMMAND
|
76
63
|
name:value
|
data/test/test_topic_manager.rb
CHANGED
@@ -1,13 +1,12 @@
|
|
1
|
-
require 'topic_manager'
|
1
|
+
require 'stomp_server/topic_manager'
|
2
2
|
require 'test/unit' unless defined? $ZENTEST and $ZENTEST
|
3
|
-
require 'tesly'
|
4
3
|
|
5
4
|
class TestTopics < Test::Unit::TestCase
|
6
5
|
|
7
6
|
class UserMock
|
8
7
|
attr_accessor :data
|
9
8
|
def initialize ; @data = '' ; end
|
10
|
-
def
|
9
|
+
def stomp_send_data(data); @data += data.to_s ; end
|
11
10
|
end
|
12
11
|
|
13
12
|
class MessageMock
|
@@ -20,7 +19,7 @@ class TestTopics < Test::Unit::TestCase
|
|
20
19
|
end
|
21
20
|
|
22
21
|
def setup
|
23
|
-
@t = TopicManager.new
|
22
|
+
@t = StompServer::TopicManager.new
|
24
23
|
end
|
25
24
|
|
26
25
|
def test_subscribe
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'stomp_server'
|
2
|
-
require 'frame_journal'
|
3
2
|
require 'fileutils'
|
4
3
|
require 'test/unit' unless defined? $ZENTEST and $ZENTEST
|
5
4
|
require 'tesly'
|
@@ -55,13 +54,8 @@ class TestStompServer < Test::Unit::TestCase
|
|
55
54
|
assert(!ss.connected)
|
56
55
|
end
|
57
56
|
|
58
|
-
FileUtils.rm Dir.glob(".test_journal/*") rescue nil
|
59
|
-
@@journal = FrameJournal.new(".test_journal")
|
60
|
-
StompServer.setup(@@journal)
|
61
57
|
|
62
58
|
def setup
|
63
|
-
# be sure and delete anything in our journal directory
|
64
|
-
@@journal.clear
|
65
59
|
@ss = MockStompServer.make_client
|
66
60
|
end
|
67
61
|
|
@@ -238,25 +232,4 @@ class TestStompServer < Test::Unit::TestCase
|
|
238
232
|
ss2.stomp("SUBSCRIBE", {"destination" => '/queue/foo'})
|
239
233
|
assert_match(/Hi Pat/, ss2.sent)
|
240
234
|
end
|
241
|
-
|
242
|
-
def test_ack_queue_message
|
243
|
-
ss1 = MockStompServer.make_client
|
244
|
-
ss1.stomp("SEND", {'destination' => '/queue/taqm'},
|
245
|
-
'Hi Pat')
|
246
|
-
ss1.stomp("DISCONNECT")
|
247
|
-
|
248
|
-
ss2 = MockStompServer.make_client
|
249
|
-
ss2.stomp("SUBSCRIBE", {"destination" => '/queue/taqm', 'ack' => 'client'})
|
250
|
-
assert_match(/Hi Pat/, ss2.sent)
|
251
|
-
ss2.unbind
|
252
|
-
|
253
|
-
ss3 = MockStompServer.make_client
|
254
|
-
ss3.stomp("SUBSCRIBE", {"destination" => '/queue/taqm'})
|
255
|
-
assert_match(/Hi Pat/, ss3.sent)
|
256
|
-
|
257
|
-
assert_nothing_raised do
|
258
|
-
ss3.stomp("SUBSCRIBE", {"destination" => '/queue/taqm',
|
259
|
-
"message-id" => "msg-cmastomp-1"})
|
260
|
-
end
|
261
|
-
end
|
262
235
|
end
|
metadata
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.9.
|
2
|
+
rubygems_version: 0.9.4
|
3
3
|
specification_version: 1
|
4
4
|
name: stompserver
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.9.
|
7
|
-
date:
|
6
|
+
version: 0.9.8
|
7
|
+
date: 2007-08-16 00:00:00 +02:00
|
8
8
|
summary: A very light messaging server
|
9
9
|
require_paths:
|
10
10
|
- lib
|
11
|
-
|
12
|
-
|
13
|
-
homepage: " by Patrick Hurley"
|
11
|
+
email:
|
12
|
+
- lionel-dev@bouton.name
|
13
|
+
homepage: " by Patrick Hurley, Lionel Bouton"
|
14
14
|
rubyforge_project: stompserver
|
15
|
-
description: "
|
15
|
+
description: "Stomp messaging server with file/dbm/memory/activerecord based FIFO queues, queue monitoring, and basic authentication. == SYNOPSYS: Handles basic message queue processing"
|
16
16
|
autorequire:
|
17
17
|
default_executable:
|
18
18
|
bindir: bin
|
@@ -28,30 +28,54 @@ signing_key:
|
|
28
28
|
cert_chain:
|
29
29
|
post_install_message:
|
30
30
|
authors:
|
31
|
-
-
|
31
|
+
- Lionel Bouton
|
32
32
|
files:
|
33
33
|
- History.txt
|
34
34
|
- Manifest.txt
|
35
35
|
- README.txt
|
36
36
|
- Rakefile
|
37
|
-
-
|
37
|
+
- STATUS
|
38
38
|
- bin/stompserver
|
39
|
-
-
|
40
|
-
-
|
41
|
-
-
|
39
|
+
- client/README.txt
|
40
|
+
- client/both.rb
|
41
|
+
- client/consume.rb
|
42
|
+
- client/send.rb
|
43
|
+
- config/stompserver.conf
|
44
|
+
- etc/passwd.example
|
42
45
|
- lib/stomp_server.rb
|
43
|
-
- lib/
|
44
|
-
-
|
46
|
+
- lib/stomp_server/protocols/http.rb
|
47
|
+
- lib/stomp_server/protocols/stomp.rb
|
48
|
+
- lib/stomp_server/queue.rb
|
49
|
+
- lib/stomp_server/queue/activerecord_queue.rb
|
50
|
+
- lib/stomp_server/queue/ar_message.rb
|
51
|
+
- lib/stomp_server/queue/dbm_queue.rb
|
52
|
+
- lib/stomp_server/queue/file_queue.rb
|
53
|
+
- lib/stomp_server/queue/memory_queue.rb
|
54
|
+
- lib/stomp_server/queue_manager.rb
|
55
|
+
- lib/stomp_server/stomp_auth.rb
|
56
|
+
- lib/stomp_server/stomp_frame.rb
|
57
|
+
- lib/stomp_server/stomp_id.rb
|
58
|
+
- lib/stomp_server/stomp_user.rb
|
59
|
+
- lib/stomp_server/test_server.rb
|
60
|
+
- lib/stomp_server/topic_manager.rb
|
61
|
+
- setup.rb
|
62
|
+
- test/tesly.rb
|
45
63
|
- test/test_queue_manager.rb
|
46
64
|
- test/test_stomp_frame.rb
|
47
|
-
- test/test_stomp_server.rb
|
48
65
|
- test/test_topic_manager.rb
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
66
|
+
- test_todo/test_stomp_server.rb
|
67
|
+
test_files:
|
68
|
+
- test/test_queue_manager.rb
|
69
|
+
- test/test_stomp_frame.rb
|
70
|
+
- test/test_topic_manager.rb
|
71
|
+
rdoc_options:
|
72
|
+
- --main
|
73
|
+
- README.txt
|
74
|
+
extra_rdoc_files:
|
75
|
+
- History.txt
|
76
|
+
- Manifest.txt
|
77
|
+
- README.txt
|
78
|
+
- client/README.txt
|
55
79
|
executables:
|
56
80
|
- stompserver
|
57
81
|
extensions: []
|
@@ -60,13 +84,13 @@ requirements: []
|
|
60
84
|
|
61
85
|
dependencies:
|
62
86
|
- !ruby/object:Gem::Dependency
|
63
|
-
name:
|
87
|
+
name: daemons
|
64
88
|
version_requirement:
|
65
89
|
version_requirements: !ruby/object:Gem::Version::Requirement
|
66
90
|
requirements:
|
67
91
|
- - ">="
|
68
92
|
- !ruby/object:Gem::Version
|
69
|
-
version: 0.
|
93
|
+
version: 1.0.2
|
70
94
|
version:
|
71
95
|
- !ruby/object:Gem::Dependency
|
72
96
|
name: hoe
|
@@ -77,3 +101,12 @@ dependencies:
|
|
77
101
|
- !ruby/object:Gem::Version
|
78
102
|
version: 1.1.1
|
79
103
|
version:
|
104
|
+
- !ruby/object:Gem::Dependency
|
105
|
+
name: hoe
|
106
|
+
version_requirement:
|
107
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: 1.2.2
|
112
|
+
version:
|