wamp 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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 "rdoc", "~> 3.12"
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
- rdoc (~> 3.12)
79
+ redcarpet
75
80
  rspec
76
81
  thin
82
+ yard
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.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
- <input type="text" id="prefix-curie"></input><button onclick="registerPrefix()">Register Prefix</button>
12
- <input type="text" id="topic-name"></input><button onclick="subscribe()">Subscribe</button><button onclick="unsubscribe()">Unsubscribe</button>
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://localhost:9292";
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
- 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;
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 = $("#prefix-curie").val()
49
- topicName = $("#topic-name").val();
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
- debugData(topicUri);
57
- debugData(event);
56
+ debugData(topicUri);
57
+ debugData(event);
58
58
  }
59
59
 
60
60
  function sendSimpleMsg()
61
61
  {
62
- msg = $("#simple-msg").val();
63
- $("#simple-msg").val("");
62
+ msg = $("#simple-msg").val();
63
+ $("#simple-msg").val("");
64
64
 
65
- wamp.publish(prefix, msg);
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
@@ -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