wamp 0.0.0 → 0.0.1
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/Gemfile +3 -1
- data/Gemfile.lock +7 -1
- data/VERSION +1 -1
- data/demo/client.html +8 -3
- data/demo/client.js +24 -24
- data/demo/client.rb +29 -0
- data/lib/wamp.rb +11 -0
- data/lib/wamp/bindable.rb +16 -0
- data/lib/wamp/client.rb +118 -0
- data/lib/wamp/engines/memory.rb +104 -0
- data/lib/wamp/protocols/version_1.rb +128 -0
- data/lib/wamp/server.rb +57 -80
- data/lib/wamp/socket.rb +3 -4
- data/lib/wamp/topic.rb +32 -3
- data/spec/lib/wamp/client_spec.rb +9 -0
- data/spec/lib/wamp/engines/memory_spec.rb +118 -0
- data/spec/lib/wamp/protocols/version_1_spec.rb +80 -0
- data/spec/lib/wamp/server_spec.rb +5 -6
- data/spec/lib/wamp/socket_spec.rb +6 -6
- data/spec/lib/wamp/topic_spec.rb +1 -1
- data/spec/support/dummy_socket.rb +11 -0
- data/wamp.gemspec +20 -5
- metadata +49 -8
data/Gemfile
CHANGED
@@ -10,10 +10,12 @@ gem 'faye-websocket'
|
|
10
10
|
group :development do
|
11
11
|
gem "rspec"
|
12
12
|
gem 'guard-rspec'
|
13
|
+
gem 'pry-nav'
|
13
14
|
gem 'rb-fsevent'
|
14
15
|
gem 'rb-inotify'
|
15
16
|
gem 'fuubar'
|
16
|
-
gem "
|
17
|
+
gem "yard"
|
18
|
+
gem 'redcarpet'
|
17
19
|
gem "bundler"
|
18
20
|
gem "jeweler", "~> 1.8.4"
|
19
21
|
end
|
data/Gemfile.lock
CHANGED
@@ -36,6 +36,8 @@ GEM
|
|
36
36
|
coderay (~> 1.0.5)
|
37
37
|
method_source (~> 0.8)
|
38
38
|
slop (~> 3.4)
|
39
|
+
pry-nav (0.2.3)
|
40
|
+
pry (~> 0.9.10)
|
39
41
|
rack (1.5.2)
|
40
42
|
rake (10.0.4)
|
41
43
|
rb-fsevent (0.9.3)
|
@@ -43,6 +45,7 @@ GEM
|
|
43
45
|
ffi (>= 0.5.0)
|
44
46
|
rdoc (3.12.2)
|
45
47
|
json (~> 1.4)
|
48
|
+
redcarpet (2.2.2)
|
46
49
|
rspec (2.13.0)
|
47
50
|
rspec-core (~> 2.13.0)
|
48
51
|
rspec-expectations (~> 2.13.0)
|
@@ -59,6 +62,7 @@ GEM
|
|
59
62
|
eventmachine (>= 0.12.6)
|
60
63
|
rack (>= 1.0.0)
|
61
64
|
thor (0.18.0)
|
65
|
+
yard (0.8.5.2)
|
62
66
|
|
63
67
|
PLATFORMS
|
64
68
|
ruby
|
@@ -69,8 +73,10 @@ DEPENDENCIES
|
|
69
73
|
fuubar
|
70
74
|
guard-rspec
|
71
75
|
jeweler (~> 1.8.4)
|
76
|
+
pry-nav
|
72
77
|
rb-fsevent
|
73
78
|
rb-inotify
|
74
|
-
|
79
|
+
redcarpet
|
75
80
|
rspec
|
76
81
|
thin
|
82
|
+
yard
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.1
|
data/demo/client.html
CHANGED
@@ -7,9 +7,14 @@
|
|
7
7
|
</head>
|
8
8
|
<body>
|
9
9
|
<div id="debug-data"></div>
|
10
|
-
<button onclick="connect();">Connect</button>
|
11
|
-
<
|
12
|
-
<
|
10
|
+
<button onclick="connect();">Connect</button></br>
|
11
|
+
<button onclick="registerPrefix('sample_topic', 'sample_topic');">Register Prefix ( sample_topic )</button></br>
|
12
|
+
<button onclick="subscribe('sample_topic:chat');">Subscribe Topic ( sample_topic:chat )</button></br>
|
13
|
+
<button onclick="unsubscribe();">Unsubscribe Topic ( sample_topic:chat )</button></br>
|
13
14
|
<input type="text" id="simple-msg"></input><button onclick="sendSimpleMsg()">Send</button>
|
15
|
+
|
16
|
+
<!-- <button onclick="connect();">Connect</button> -->
|
17
|
+
<!-- <input type="text" id="prefix-curie"></input><button onclick="registerPrefix()">Register Prefix</button> -->
|
18
|
+
<!-- <input type="text" id="topic-name"></input><button onclick="subscribe()">Subscribe</button><button onclick="unsubscribe()">Unsubscribe</button> -->
|
14
19
|
</abody>
|
15
20
|
</html>
|
data/demo/client.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
var wamp, topicName, topicPath, prefix;
|
2
|
-
var wsuri = "ws://
|
2
|
+
var wsuri = "ws://local.blove.me:9292";
|
3
3
|
|
4
4
|
debugData = function(msg){
|
5
5
|
$("#debug-data").append(msg + '</br>')
|
@@ -14,20 +14,20 @@ connect = function(){
|
|
14
14
|
},
|
15
15
|
|
16
16
|
// WAMP session is gone
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
17
|
+
function (code, reason) {
|
18
|
+
switch (code) {
|
19
|
+
case ab.CONNECTION_CLOSED:
|
20
|
+
debugData("Connection was closed properly - done.");
|
21
|
+
break;
|
22
|
+
case ab.CONNECTION_UNREACHABLE:
|
23
|
+
debugData("Connection could not be established.");
|
24
|
+
break;
|
25
|
+
case ab.CONNECTION_UNSUPPORTED:
|
26
|
+
debugData("Browser does not support WebSocket.");
|
27
|
+
break;
|
28
|
+
case ab.CONNECTION_LOST:
|
29
|
+
debugData("Connection lost - reconnecting ...");
|
30
|
+
break;
|
31
31
|
}
|
32
32
|
|
33
33
|
debugData("Session closed, code " + code + ", reason:" + reason)
|
@@ -35,7 +35,7 @@ connect = function(){
|
|
35
35
|
);
|
36
36
|
};
|
37
37
|
|
38
|
-
subscribe = function(){
|
38
|
+
subscribe = function(prefix){
|
39
39
|
wamp.subscribe(prefix, onEvent);
|
40
40
|
}
|
41
41
|
|
@@ -44,23 +44,23 @@ unsubscribe = function(){
|
|
44
44
|
topicPath = null;
|
45
45
|
}
|
46
46
|
|
47
|
-
registerPrefix = function(){
|
48
|
-
prefix =
|
49
|
-
topicName =
|
47
|
+
registerPrefix = function(prefix, topic){
|
48
|
+
prefix = prefix
|
49
|
+
topicName = topic
|
50
50
|
topicPath = wsuri + topicName;
|
51
51
|
|
52
52
|
wamp.prefix(prefix, topicPath);
|
53
53
|
}
|
54
54
|
|
55
55
|
function onEvent(topicUri, event) {
|
56
|
-
|
57
|
-
|
56
|
+
debugData(topicUri);
|
57
|
+
debugData(event);
|
58
58
|
}
|
59
59
|
|
60
60
|
function sendSimpleMsg()
|
61
61
|
{
|
62
|
-
|
63
|
-
|
62
|
+
msg = $("#simple-msg").val();
|
63
|
+
$("#simple-msg").val("");
|
64
64
|
|
65
|
-
|
65
|
+
wamp.publish("sample_topic:chat", msg);
|
66
66
|
}
|
data/demo/client.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require '../lib/wamp'
|
2
|
+
|
3
|
+
Client = WAMP::Client.new
|
4
|
+
|
5
|
+
Client.bind(:connect) do |client|
|
6
|
+
puts "Connected to server"
|
7
|
+
end
|
8
|
+
|
9
|
+
Client.bind(:welcome) do |client|
|
10
|
+
puts "Welcome message received"
|
11
|
+
# client.socket.send [5, "ws://localhost:9000/some_topic"].to_json
|
12
|
+
|
13
|
+
client.subscribe("ws://localhost:9000/some_topic")
|
14
|
+
client.publish("ws://localhost:9000/some_topic", { from: client.id, to: "You", what: "Whos there?" })
|
15
|
+
end
|
16
|
+
|
17
|
+
Client.bind(:event) do |client, topic, payload|
|
18
|
+
puts "New event on #{topic}: #{payload}"
|
19
|
+
|
20
|
+
if payload["what"] == "Whos there?"
|
21
|
+
client.publish("ws://localhost:9000/some_topic", { results: "I am!" }, exclude: true)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
Client.bind(:disconnect) do |client|
|
26
|
+
puts "Disconnected from server"
|
27
|
+
end
|
28
|
+
|
29
|
+
Client.start
|
data/lib/wamp.rb
CHANGED
@@ -5,11 +5,22 @@ module WAMP
|
|
5
5
|
|
6
6
|
ROOT = File.expand_path(File.dirname(__FILE__))
|
7
7
|
|
8
|
+
autoload :Bindable, File.join(ROOT, "wamp", "bindable")
|
9
|
+
autoload :Client, File.join(ROOT, "wamp", "client")
|
8
10
|
autoload :Server, File.join(ROOT, "wamp", "server")
|
9
11
|
autoload :Socket, File.join(ROOT, "wamp", "socket")
|
10
12
|
autoload :Topic, File.join(ROOT, "wamp", "topic")
|
11
13
|
autoload :MessageType, File.join(ROOT, "wamp", "message_type")
|
12
14
|
|
15
|
+
module Engines
|
16
|
+
autoload :Memory, File.join(ROOT, "wamp", "engines", "memory")
|
17
|
+
end
|
18
|
+
|
19
|
+
# autoload :Protocols, File.join(ROOT, "wamp", "protocols")
|
20
|
+
module Protocols
|
21
|
+
autoload :Version1, File.join(ROOT, "wamp", "protocols", "version_1")
|
22
|
+
end
|
23
|
+
|
13
24
|
class << self
|
14
25
|
def version
|
15
26
|
"#{MAJOR}.#{MINOR}.#{PATCH}"
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module WAMP
|
2
|
+
module Bindable
|
3
|
+
def available_bindings
|
4
|
+
raise NotImplementedError
|
5
|
+
end
|
6
|
+
|
7
|
+
def bind(name, &callback)
|
8
|
+
raise "Invalid binding: #{name}" unless available_bindings.include? name
|
9
|
+
callbacks[name] = callback
|
10
|
+
end
|
11
|
+
|
12
|
+
def trigger(name, *args)
|
13
|
+
callbacks[name].call *args if callbacks[name]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/wamp/client.rb
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'faye/websocket'
|
2
|
+
require 'json'
|
3
|
+
require 'eventmachine'
|
4
|
+
|
5
|
+
module WAMP
|
6
|
+
class Client
|
7
|
+
include WAMP::Bindable
|
8
|
+
|
9
|
+
attr_accessor :id, :socket, :wamp_protocol, :server_ident, :topics, :callbacks,
|
10
|
+
:prefixes, :ws_server
|
11
|
+
|
12
|
+
# WAMP Client
|
13
|
+
# Connects to WAMP server, after connection client should receve WELCOME message
|
14
|
+
# from server.
|
15
|
+
# Client can then register prefix, call, subscribe, unsubscribe, and publish
|
16
|
+
|
17
|
+
def initialize(options = {})
|
18
|
+
@ws_server = options[:host] || "ws://localhost:9000"
|
19
|
+
@id = nil
|
20
|
+
@socket = nil
|
21
|
+
@wamp_protocol = nil
|
22
|
+
@server_ident = nil
|
23
|
+
|
24
|
+
@prefixes = {}
|
25
|
+
@topics = []
|
26
|
+
@callbacks = {}
|
27
|
+
end
|
28
|
+
|
29
|
+
def available_bindings
|
30
|
+
[:connect, :welcome, :call_result, :call_error, :event, :disconnect]
|
31
|
+
end
|
32
|
+
|
33
|
+
def start
|
34
|
+
EM.run do
|
35
|
+
ws = Faye::WebSocket::Client.new(ws_server)
|
36
|
+
|
37
|
+
ws.onopen = lambda { |event| handle_open(ws, event) }
|
38
|
+
ws.onmessage = lambda { |event| handle_message(event) }
|
39
|
+
ws.onclose = lambda { |event| handle_close(event) }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def prefix(prefix, topic_uri)
|
44
|
+
socket.send [WAMP::MessageType[:PREFIX], prefix, topic_uri].to_json
|
45
|
+
|
46
|
+
prefixes[prefix] = topic_uri
|
47
|
+
end
|
48
|
+
|
49
|
+
def subscribe(topic_uri)
|
50
|
+
socket.send [WAMP::MessageType[:SUBSCRIBE], topic_uri].to_json
|
51
|
+
|
52
|
+
topics << topic_uri
|
53
|
+
end
|
54
|
+
|
55
|
+
def publish(topic_uri, payload, options = {})
|
56
|
+
exclude = options.fetch(:exclude, nil)
|
57
|
+
include = options.fetch(:include, nil)
|
58
|
+
|
59
|
+
socket.send [WAMP::MessageType[:PUBLISH], topic_uri, payload, exclude, include].to_json
|
60
|
+
end
|
61
|
+
|
62
|
+
def stop
|
63
|
+
EM.stop
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def handle_open(websocket, event)
|
69
|
+
@socket = websocket
|
70
|
+
|
71
|
+
trigger(:connect, self)
|
72
|
+
end
|
73
|
+
|
74
|
+
def handle_message(event)
|
75
|
+
parsed_msg = JSON.parse(event.data)
|
76
|
+
msg_type = parsed_msg[0]
|
77
|
+
|
78
|
+
case WAMP::MessageType[msg_type]
|
79
|
+
when :WELCOME
|
80
|
+
handle_welcome(parsed_msg)
|
81
|
+
when :EVENT
|
82
|
+
handle_event(parsed_msg)
|
83
|
+
else
|
84
|
+
handle_unknown(parsed_msg)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Handle welcome message from server
|
89
|
+
# WELCOME data structure [0, CLIENT_ID, WAMP_PROTOCOL, SERVER_IDENTITY]
|
90
|
+
def handle_welcome(data)
|
91
|
+
@id = data[1]
|
92
|
+
@wamp_protocol = data[2]
|
93
|
+
@server_ident = data[3]
|
94
|
+
|
95
|
+
trigger(:welcome, self)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Handle an event message from server
|
99
|
+
# EVENT data structure [8, TOPIC, PAYLOAD]
|
100
|
+
def handle_event(data)
|
101
|
+
topic = data[1]
|
102
|
+
payload = data[2]
|
103
|
+
|
104
|
+
trigger(:event, self, topic, payload)
|
105
|
+
end
|
106
|
+
|
107
|
+
def handle_unknown(data)
|
108
|
+
# Do nothing
|
109
|
+
end
|
110
|
+
|
111
|
+
def handle_close(event)
|
112
|
+
socket = nil
|
113
|
+
id = nil
|
114
|
+
|
115
|
+
trigger(:disconnect, self)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
3
|
+
module WAMP
|
4
|
+
module Engines
|
5
|
+
|
6
|
+
# Engine for managing clients, and topics in system memory. This engine is
|
7
|
+
# best used for single servers.
|
8
|
+
class Memory
|
9
|
+
attr_reader :clients, :topics, :options
|
10
|
+
|
11
|
+
# Creates a new instance of the memory engine as well as some empty hashes
|
12
|
+
# for holding clients and topics.
|
13
|
+
# @param options [Hash] Optional. Options hash for the memory engine.
|
14
|
+
def initialize(options = {})
|
15
|
+
@options = options
|
16
|
+
@clients = {}
|
17
|
+
@topics = {}
|
18
|
+
end
|
19
|
+
|
20
|
+
# Creates a new Socket object and adds it as a client.
|
21
|
+
# @param websocket [WebSocket] The websocket connection that belongs to the
|
22
|
+
# new client
|
23
|
+
# @return [WebSocket] Returns the newly created socket object
|
24
|
+
def create_client(websocket)
|
25
|
+
client = new_client(websocket)
|
26
|
+
@clients[client.id] = client
|
27
|
+
end
|
28
|
+
|
29
|
+
# Finds clients by the given parameters. Currently only supports one
|
30
|
+
# parameter. Todo: Support multiple parameters.
|
31
|
+
# @param args [Hash] A hash of arguments to match against the given clients
|
32
|
+
# @return [Array] Returns an array of all matching clients.
|
33
|
+
def find_clients(args = {})
|
34
|
+
matching_clients = clients.find_all do |id, socket|
|
35
|
+
socket.send(args.first[0]) == args.first[1]
|
36
|
+
end
|
37
|
+
|
38
|
+
matching_clients.flat_map { |x| x[1] }
|
39
|
+
end
|
40
|
+
|
41
|
+
# Deletes a client
|
42
|
+
# @param socket [WebSocket] The websocket to remove from clients
|
43
|
+
# @return [WAMP::Socket] The client that was removed
|
44
|
+
def delete_client(websocket)
|
45
|
+
client = find_clients(websocket: websocket).first
|
46
|
+
|
47
|
+
clients.delete client.id
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns an array of all connected clients
|
51
|
+
# @return [Array] Array of all connected clients.
|
52
|
+
def all_clients
|
53
|
+
clients.values
|
54
|
+
end
|
55
|
+
|
56
|
+
# Finds an existing topic, if non is found it will create one.
|
57
|
+
# @param topic_uri [String] The URI for the topic to find or create.
|
58
|
+
# @return [WAMP::Topic] Returns a WAMP Topic object.
|
59
|
+
def find_or_create_topic(topic_uri)
|
60
|
+
@topics[topic_uri] ||= new_topic(topic_uri)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Add a client to a topic and a topic to a client
|
64
|
+
# @param client [WAMP::Socket] The client socket to subscribe to the topic.
|
65
|
+
# @param topic_uri [String] URI or CURIE the client is to subscribe to.
|
66
|
+
# @return [WAMP::Topic] The topic that the client subscribed to.
|
67
|
+
def subscribe_client_to_topic(client, topic_uri)
|
68
|
+
topic = find_or_create_topic(topic_uri)
|
69
|
+
|
70
|
+
client.add_topic(topic)
|
71
|
+
topic.add_client(client)
|
72
|
+
|
73
|
+
topic
|
74
|
+
end
|
75
|
+
|
76
|
+
# Remove a client from a topic.
|
77
|
+
# @param client [WAMP::Socket] The client socket to unsubscribe from the topic.
|
78
|
+
# @param topic_uri [String] The URI of the topic to unsubscribe from.
|
79
|
+
# @return [WAMP::Topic] The topic that the client unsubscribed from.
|
80
|
+
def unsubscribe_client_from_topic(client, topic_uri)
|
81
|
+
topic = find_or_create_topic(topic_uri)
|
82
|
+
|
83
|
+
client.remove_topic(topic)
|
84
|
+
topic.remove_client(client)
|
85
|
+
|
86
|
+
topic
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def new_client(websocket)
|
92
|
+
WAMP::Socket.new(random_uuid, websocket)
|
93
|
+
end
|
94
|
+
|
95
|
+
def new_topic(uri)
|
96
|
+
WAMP::Topic.new(uri)
|
97
|
+
end
|
98
|
+
|
99
|
+
def random_uuid
|
100
|
+
SecureRandom.uuid
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|