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 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