xconn 0.1.0
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.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +29 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE +22 -0
- data/Makefile +9 -0
- data/README.md +2 -0
- data/Rakefile +14 -0
- data/bin/xconn +79 -0
- data/docs/index.md +7 -0
- data/docs/installation.md +11 -0
- data/example/sample/example.rb +23 -0
- data/example/sample/included_app.rb +12 -0
- data/lib/tasks/tasks.rake +24 -0
- data/lib/wamp/app.rb +39 -0
- data/lib/wamp/connection/session.rb +35 -0
- data/lib/wamp/connection/stream.rb +68 -0
- data/lib/wamp/connection/websocket_client.rb +137 -0
- data/lib/wamp/connection/websocket_connection.rb +52 -0
- data/lib/wamp/manager/base.rb +41 -0
- data/lib/wamp/manager/connection.rb +32 -0
- data/lib/wamp/manager/event/abort.rb +21 -0
- data/lib/wamp/manager/event/authenticate.rb +14 -0
- data/lib/wamp/manager/event/base.rb +41 -0
- data/lib/wamp/manager/event/call.rb +40 -0
- data/lib/wamp/manager/event/challenge.rb +26 -0
- data/lib/wamp/manager/event/error.rb +30 -0
- data/lib/wamp/manager/event/event.rb +20 -0
- data/lib/wamp/manager/event/goodbye.rb +18 -0
- data/lib/wamp/manager/event/hello.rb +38 -0
- data/lib/wamp/manager/event/invocation.rb +24 -0
- data/lib/wamp/manager/event/publish.rb +22 -0
- data/lib/wamp/manager/event/published.rb +13 -0
- data/lib/wamp/manager/event/register.rb +30 -0
- data/lib/wamp/manager/event/registered.rb +37 -0
- data/lib/wamp/manager/event/result.rb +13 -0
- data/lib/wamp/manager/event/subscribe.rb +39 -0
- data/lib/wamp/manager/event/subscribed.rb +26 -0
- data/lib/wamp/manager/event/unregister.rb +19 -0
- data/lib/wamp/manager/event/unregistered.rb +13 -0
- data/lib/wamp/manager/event/unsubscribe.rb +29 -0
- data/lib/wamp/manager/event/unsubscribed.rb +13 -0
- data/lib/wamp/manager/event/welcome.rb +21 -0
- data/lib/wamp/manager/event/yield.rb +13 -0
- data/lib/wamp/manager/event.rb +60 -0
- data/lib/wamp/manager/hello_event.rb +263 -0
- data/lib/wamp/manager/session.rb +91 -0
- data/lib/wamp/manager/subscription.rb +38 -0
- data/lib/wamp/manager.rb +12 -0
- data/lib/wamp/message_handler/api.rb +67 -0
- data/lib/wamp/message_handler/base.rb +65 -0
- data/lib/wamp/message_handler/call.rb +14 -0
- data/lib/wamp/message_handler/challenge.rb +12 -0
- data/lib/wamp/message_handler/error.rb +18 -0
- data/lib/wamp/message_handler/event.rb +18 -0
- data/lib/wamp/message_handler/goodbye.rb +19 -0
- data/lib/wamp/message_handler/hello.rb +18 -0
- data/lib/wamp/message_handler/invocation.rb +35 -0
- data/lib/wamp/message_handler/publish.rb +14 -0
- data/lib/wamp/message_handler/published.rb +18 -0
- data/lib/wamp/message_handler/register.rb +14 -0
- data/lib/wamp/message_handler/registered.rb +30 -0
- data/lib/wamp/message_handler/result.rb +17 -0
- data/lib/wamp/message_handler/subscribe.rb +14 -0
- data/lib/wamp/message_handler/subscribed.rb +30 -0
- data/lib/wamp/message_handler/unregister.rb +14 -0
- data/lib/wamp/message_handler/unregistered.rb +32 -0
- data/lib/wamp/message_handler/unsubscribe.rb +14 -0
- data/lib/wamp/message_handler/unsubscribed.rb +33 -0
- data/lib/wamp/message_handler/welcome.rb +12 -0
- data/lib/wamp/message_handler.rb +75 -0
- data/lib/wamp/router/base.rb +45 -0
- data/lib/wamp/router/client.rb +55 -0
- data/lib/wamp/router/connection.rb +150 -0
- data/lib/wamp/router/realm.rb +92 -0
- data/lib/wamp/router/server.rb +83 -0
- data/lib/wamp/router.rb +12 -0
- data/lib/wamp/serializer/cbor.rb +18 -0
- data/lib/wamp/serializer/json.rb +18 -0
- data/lib/wamp/serializer/message_pack.rb +18 -0
- data/lib/wamp/serializer.rb +5 -0
- data/lib/wamp/type/error.rb +24 -0
- data/lib/wamp/type/event.rb +16 -0
- data/lib/wamp/type/invocation.rb +16 -0
- data/lib/wamp/type/publication.rb +14 -0
- data/lib/wamp/type/registration.rb +14 -0
- data/lib/wamp/type/result.rb +16 -0
- data/lib/wamp/type/subscription.rb +14 -0
- data/lib/wamp/type/success.rb +8 -0
- data/lib/wamp/type.rb +16 -0
- data/lib/wamp/version.rb +5 -0
- data/lib/wamp.rb +15 -0
- data/mkdocs.yml +67 -0
- data/sig/wamp/serializer/json.rbs +10 -0
- data/sig/wamp.rbs +11 -0
- data/wamp.gemspec +40 -0
- metadata +223 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Wamp
|
|
4
|
+
module MessageHandler
|
|
5
|
+
# Published confirmation message
|
|
6
|
+
class Published < Base
|
|
7
|
+
def handle
|
|
8
|
+
validate_received_message
|
|
9
|
+
|
|
10
|
+
deliver_response(response)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def response
|
|
14
|
+
Type::Publication.new(publication_id: message.publication_id)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Wamp
|
|
4
|
+
module MessageHandler
|
|
5
|
+
# publish event to subscriber
|
|
6
|
+
class Register < Base
|
|
7
|
+
def send_message(handler, &callback)
|
|
8
|
+
store[store_key] = { handler: handler, callback: callback, procedure: message.procedure }
|
|
9
|
+
|
|
10
|
+
send_serialized message
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Wamp
|
|
4
|
+
module MessageHandler
|
|
5
|
+
# Registered callback
|
|
6
|
+
class Registered < Base
|
|
7
|
+
def handle
|
|
8
|
+
validate_received_message
|
|
9
|
+
|
|
10
|
+
store[alt_store_key] = { handler: stored_data.fetch(:handler), procedure: stored_data.fetch(:procedure) }
|
|
11
|
+
store_procedure
|
|
12
|
+
|
|
13
|
+
deliver_response(response)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def response
|
|
17
|
+
Type::Registration.new(registration_id: message.registration_id)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def alt_store_key
|
|
21
|
+
"registration_#{message.registration_id}"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def store_procedure
|
|
25
|
+
procedure = stored_data.fetch(:procedure)
|
|
26
|
+
store[procedure] = message.registration_id
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Wamp
|
|
4
|
+
module MessageHandler
|
|
5
|
+
# Result
|
|
6
|
+
class Result < Base
|
|
7
|
+
def handle
|
|
8
|
+
validate_received_message
|
|
9
|
+
stored_data.fetch(:handler).call(response)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def response
|
|
13
|
+
Type::Result.new(args: message.args, kwargs: message.kwargs, details: message.details)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Wamp
|
|
4
|
+
module MessageHandler
|
|
5
|
+
# Request subscription
|
|
6
|
+
class Subscribe < Base
|
|
7
|
+
def send_message(handler, &callback)
|
|
8
|
+
store[store_key] = { handler: handler, callback: callback, topic: message.topic }
|
|
9
|
+
|
|
10
|
+
send_serialized message
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Wamp
|
|
4
|
+
module MessageHandler
|
|
5
|
+
# Receive subscribed
|
|
6
|
+
class Subscribed < Base
|
|
7
|
+
def handle
|
|
8
|
+
validate_received_message
|
|
9
|
+
|
|
10
|
+
store[alt_store_key] = { handler: stored_data.fetch(:handler), topic: stored_data.fetch(:topic) }
|
|
11
|
+
store_topic
|
|
12
|
+
|
|
13
|
+
deliver_response(response)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def response
|
|
17
|
+
Type::Subscription.new(subscription_id: message.subscription_id)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def alt_store_key
|
|
21
|
+
"subscription_#{message.subscription_id}"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def store_topic
|
|
25
|
+
topic = stored_data.fetch(:topic)
|
|
26
|
+
store[topic] = message.subscription_id
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Wamp
|
|
4
|
+
module MessageHandler
|
|
5
|
+
# send unregister message
|
|
6
|
+
class Unregister < Base
|
|
7
|
+
def send_message(&callback)
|
|
8
|
+
store[store_key] = { callback: callback, registration_id: message.registration_id }
|
|
9
|
+
|
|
10
|
+
send_serialized message
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Wamp
|
|
4
|
+
module MessageHandler
|
|
5
|
+
# callback for unregister message
|
|
6
|
+
class Unregistered < Base
|
|
7
|
+
def handle
|
|
8
|
+
validate_received_message
|
|
9
|
+
|
|
10
|
+
delete_procedure store.delete(alt_store_key)
|
|
11
|
+
|
|
12
|
+
deliver_response(response)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def response
|
|
16
|
+
Type::Success.new
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def alt_store_key
|
|
20
|
+
"registration_#{registration_id}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def delete_procedure(data)
|
|
24
|
+
store.delete data.fetch(:procedure)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def registration_id
|
|
28
|
+
stored_data.fetch(:registration_id)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Wamp
|
|
4
|
+
module MessageHandler
|
|
5
|
+
# Request subscription
|
|
6
|
+
class Unsubscribe < Base
|
|
7
|
+
def send_message(&callback)
|
|
8
|
+
store[store_key] = { callback: callback, subscription_id: message.subscription_id }
|
|
9
|
+
|
|
10
|
+
send_serialized message
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Wamp
|
|
4
|
+
module MessageHandler
|
|
5
|
+
# Receive unsubscribed
|
|
6
|
+
class Unsubscribed < Base
|
|
7
|
+
def handle
|
|
8
|
+
validate_received_message
|
|
9
|
+
delete_topic store.delete(alt_store_key)
|
|
10
|
+
|
|
11
|
+
deliver_response(response)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def response
|
|
15
|
+
Type::Success.new
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def alt_store_key
|
|
21
|
+
"subscription_#{subscription_id}"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def delete_topic(data)
|
|
25
|
+
store.delete data.fetch(:topic)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def subscription_id
|
|
29
|
+
stored_data.fetch(:subscription_id)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "message_handler/base"
|
|
4
|
+
|
|
5
|
+
require_relative "message_handler/hello"
|
|
6
|
+
require_relative "message_handler/welcome"
|
|
7
|
+
require_relative "message_handler/challenge"
|
|
8
|
+
require_relative "message_handler/goodbye"
|
|
9
|
+
|
|
10
|
+
require_relative "message_handler/subscribe"
|
|
11
|
+
require_relative "message_handler/subscribed"
|
|
12
|
+
require_relative "message_handler/unsubscribe"
|
|
13
|
+
require_relative "message_handler/unsubscribed"
|
|
14
|
+
|
|
15
|
+
require_relative "message_handler/publish"
|
|
16
|
+
require_relative "message_handler/published"
|
|
17
|
+
require_relative "message_handler/event"
|
|
18
|
+
|
|
19
|
+
require_relative "message_handler/call"
|
|
20
|
+
require_relative "message_handler/result"
|
|
21
|
+
|
|
22
|
+
require_relative "message_handler/register"
|
|
23
|
+
require_relative "message_handler/registered"
|
|
24
|
+
require_relative "message_handler/unregister"
|
|
25
|
+
require_relative "message_handler/unregistered"
|
|
26
|
+
|
|
27
|
+
require_relative "message_handler/invocation"
|
|
28
|
+
|
|
29
|
+
require_relative "message_handler/error"
|
|
30
|
+
|
|
31
|
+
require_relative "message_handler/api"
|
|
32
|
+
|
|
33
|
+
module Wamp
|
|
34
|
+
# routes messages
|
|
35
|
+
module MessageHandler
|
|
36
|
+
# instantiate correct handler
|
|
37
|
+
module ClassMethods
|
|
38
|
+
def resolve(data, connection)
|
|
39
|
+
# return handle_when_not_joined(data, connection) unless connection.joiner.joined?
|
|
40
|
+
|
|
41
|
+
message = connection.joiner.serializer.deserialize(data)
|
|
42
|
+
klass_name = demodulize(message.class.name)
|
|
43
|
+
klass = constantize("Wamp::MessageHandler::#{klass_name}")
|
|
44
|
+
klass.new(message, connection)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def handle_when_not_joined(data, connection)
|
|
48
|
+
authenticate = connection.joiner.receive(data) # maybe welcome message then state should be joined
|
|
49
|
+
connection.transmit authenticate unless connection.joiner.joined?
|
|
50
|
+
connection.executor.call(connection.api) if connection.joiner.joined?
|
|
51
|
+
Struct.new(:handle).new
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def from(message, connection)
|
|
55
|
+
klass_name = demodulize(message.class.name)
|
|
56
|
+
klass = constantize("Wamp::MessageHandler::#{klass_name}")
|
|
57
|
+
klass.new(message, connection)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def demodulize(path)
|
|
61
|
+
path = path.to_s
|
|
62
|
+
if i = path.rindex("::") # rubocop:disable Lint/AssignmentInCondition
|
|
63
|
+
path[(i + 2), path.length]
|
|
64
|
+
else
|
|
65
|
+
path
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def constantize(camel_cased_word)
|
|
70
|
+
Object.const_get(camel_cased_word)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
extend ClassMethods
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "realm"
|
|
4
|
+
|
|
5
|
+
module Wamp
|
|
6
|
+
module Router
|
|
7
|
+
# Router
|
|
8
|
+
class Base
|
|
9
|
+
attr_reader :realms
|
|
10
|
+
|
|
11
|
+
def initialize
|
|
12
|
+
@realms = {}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def add_realm(name)
|
|
16
|
+
realms[name] = Realm.new(name)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def remove_realm(name)
|
|
20
|
+
realms.delete(name)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def attach_client(client)
|
|
24
|
+
error_message = "cannot attach client to non-existent realm #{client.realm}"
|
|
25
|
+
raise Wampproto::ValueError, error_message unless realms.include?(client.realm)
|
|
26
|
+
|
|
27
|
+
realms[client.realm].attach_client(client)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def detach_client(client)
|
|
31
|
+
error_message = "cannot attach client to non-existent realm #{client.realm}"
|
|
32
|
+
raise Wampproto::ValueError, error_message unless realms.include?(client.realm)
|
|
33
|
+
|
|
34
|
+
realms[client.realm].detach_client(client)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def receive_message(client, message)
|
|
38
|
+
error_message = "cannot attach client to non-existent realm #{client.realm}"
|
|
39
|
+
raise Wampproto::ValueError, error_message unless realms.include?(client.realm)
|
|
40
|
+
|
|
41
|
+
realms[client.realm].receive_message(client.session_id, message)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "realm"
|
|
4
|
+
|
|
5
|
+
module Wamp
|
|
6
|
+
module Router
|
|
7
|
+
# Auth
|
|
8
|
+
class Authenticator
|
|
9
|
+
def self.authenticate(request)
|
|
10
|
+
Wampproto::Acceptor::Response.new(request.authid, "role", "secret")
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Server Session
|
|
15
|
+
class Client
|
|
16
|
+
attr_accessor :router, :connection
|
|
17
|
+
attr_reader :acceptor, :serializer
|
|
18
|
+
|
|
19
|
+
def initialize(serializer = Wampproto::Serializer::JSON, authenticator = Authenticator)
|
|
20
|
+
@serializer = serializer
|
|
21
|
+
@acceptor = Wampproto::Acceptor.new(serializer, authenticator)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def realm
|
|
25
|
+
acceptor.session_details&.realm
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def send_message(message)
|
|
29
|
+
transmit(message)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def session_id
|
|
33
|
+
acceptor.session_details&.session_id
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def transmit(data)
|
|
37
|
+
case data
|
|
38
|
+
when Wampproto::Message::Base
|
|
39
|
+
connection.on_message serializer.serialize(data)
|
|
40
|
+
else
|
|
41
|
+
connection.on_message data
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def on_message(data)
|
|
46
|
+
unless acceptor.accepted?
|
|
47
|
+
msg, is_welcome = acceptor.receive(data)
|
|
48
|
+
transmit msg
|
|
49
|
+
router.attach_client(self) if is_welcome
|
|
50
|
+
end
|
|
51
|
+
router.receive_message(self, serializer.deserialize(data))
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "websocket/driver"
|
|
4
|
+
|
|
5
|
+
# Testing
|
|
6
|
+
class Authenticator
|
|
7
|
+
def self.authenticate(request)
|
|
8
|
+
Wampproto::Acceptor::Response.new(request.authid, "role")
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
module Wamp
|
|
13
|
+
module Router
|
|
14
|
+
# TOP Level Doc
|
|
15
|
+
class Connection < Client # rubocop:disable Metrics/ClassLength
|
|
16
|
+
include WebSocket::Driver::EventEmitter
|
|
17
|
+
CONNECTING = 0
|
|
18
|
+
OPEN = 1
|
|
19
|
+
CLOSING = 2
|
|
20
|
+
CLOSED = 3
|
|
21
|
+
|
|
22
|
+
attr_reader :socket, :session, :acceptor
|
|
23
|
+
|
|
24
|
+
def initialize(socket, &cleanup)
|
|
25
|
+
super()
|
|
26
|
+
@cleanup = cleanup
|
|
27
|
+
@socket = socket
|
|
28
|
+
@driver = WebSocket::Driver.server(self)
|
|
29
|
+
@driver.on(:open) { on_open(_1) }
|
|
30
|
+
@driver.on(:message) { on_message(_1.data) }
|
|
31
|
+
@driver.on(:close) { |evt| begin_close(evt.reason, evt.code) }
|
|
32
|
+
@driver.on(:connect) { on_connect }
|
|
33
|
+
@ready_state = CONNECTING
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def on_connect
|
|
37
|
+
@driver.start if WebSocket::Driver.websocket?(@driver.env)
|
|
38
|
+
choose_serializer_from @driver.env["HTTP_SEC_WEBSOCKET_PROTOCOL"]
|
|
39
|
+
@acceptor = Wampproto::Acceptor.new(serializer, Authenticator)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def connection
|
|
43
|
+
self
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def begin_close(reason, code)
|
|
47
|
+
return if @ready_state == CLOSED
|
|
48
|
+
|
|
49
|
+
@ready_state = CLOSING
|
|
50
|
+
@close_params = [reason, code]
|
|
51
|
+
|
|
52
|
+
@cleanup&.call(self)
|
|
53
|
+
finalize_close
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def finalize_close
|
|
57
|
+
return if @ready_state == CLOSED
|
|
58
|
+
|
|
59
|
+
@ready_state = CLOSED
|
|
60
|
+
@driver.close
|
|
61
|
+
socket.close
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def listen(&block) # rubocop:disable Metrics/MethodLength
|
|
65
|
+
return unless [CONNECTING, OPEN].include?(@ready_state)
|
|
66
|
+
|
|
67
|
+
begin
|
|
68
|
+
data = socket.read_nonblock(4096, exception: false)
|
|
69
|
+
case data
|
|
70
|
+
when :wait_readable
|
|
71
|
+
# do nothing
|
|
72
|
+
when nil
|
|
73
|
+
block&.call
|
|
74
|
+
@driver.close
|
|
75
|
+
else
|
|
76
|
+
receive_data(data)
|
|
77
|
+
end
|
|
78
|
+
rescue StandardError => e
|
|
79
|
+
puts e.message
|
|
80
|
+
puts e.backtrace
|
|
81
|
+
begin
|
|
82
|
+
block&.call
|
|
83
|
+
@driver.close
|
|
84
|
+
rescue StandardError
|
|
85
|
+
# Errno::ECONNRESET
|
|
86
|
+
puts "Failed to handle: Errno::ECONNRESET"
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# triggers on_message
|
|
92
|
+
def receive_data(data)
|
|
93
|
+
return unless [OPEN, CONNECTING].include?(@ready_state)
|
|
94
|
+
|
|
95
|
+
@driver.parse(data)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# called when @driver.text is invoked
|
|
99
|
+
def write(data)
|
|
100
|
+
socket.write(data)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def transmit(message)
|
|
104
|
+
# return false if @ready_state > OPEN
|
|
105
|
+
|
|
106
|
+
case message
|
|
107
|
+
when Wampproto::Message::Base then transmit(serializer.serialize(message))
|
|
108
|
+
when Numeric then @driver.text(message.to_s)
|
|
109
|
+
when String then @driver.text(message)
|
|
110
|
+
when Array then @driver.binary(message)
|
|
111
|
+
else false
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
private
|
|
116
|
+
|
|
117
|
+
def on_open(_evt)
|
|
118
|
+
return unless @ready_state == CONNECTING
|
|
119
|
+
|
|
120
|
+
@ready_state = OPEN
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def on_close(message)
|
|
124
|
+
return if @ready_state == CLOSED
|
|
125
|
+
|
|
126
|
+
@ready_state = CLOSED
|
|
127
|
+
socket.close
|
|
128
|
+
@driver.close(message.code, message.reason)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def close(_code, _reason)
|
|
132
|
+
@driver.close
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
attr_reader :serializer
|
|
136
|
+
|
|
137
|
+
def choose_serializer_from(protocols)
|
|
138
|
+
@serializer = if protocols.include?("wamp.2.msgpack")
|
|
139
|
+
Wampproto::Serializer::Msgpack
|
|
140
|
+
elsif protocols.include?("wamp.2.cbor")
|
|
141
|
+
Wampproto::Serializer::Cbor
|
|
142
|
+
elsif protocols.include?("wamp.2.json")
|
|
143
|
+
Wampproto::Serializer::JSON
|
|
144
|
+
else
|
|
145
|
+
close
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Wamp
|
|
4
|
+
module Router
|
|
5
|
+
# Realm
|
|
6
|
+
class Realm
|
|
7
|
+
attr_reader :broker, :dealer, :name, :clients
|
|
8
|
+
|
|
9
|
+
DEALER_MESSAGES = [
|
|
10
|
+
Wampproto::Message::Call,
|
|
11
|
+
Wampproto::Message::Yield,
|
|
12
|
+
Wampproto::Message::Register,
|
|
13
|
+
Wampproto::Message::Unregister
|
|
14
|
+
].freeze
|
|
15
|
+
|
|
16
|
+
BROKER_MESSAGES = [
|
|
17
|
+
Wampproto::Message::Publish,
|
|
18
|
+
Wampproto::Message::Subscribe,
|
|
19
|
+
Wampproto::Message::Unsubscribe
|
|
20
|
+
].freeze
|
|
21
|
+
|
|
22
|
+
GOODBYE_MESSAGE = Wampproto::Message::Goodbye
|
|
23
|
+
|
|
24
|
+
def initialize(name)
|
|
25
|
+
@name = name
|
|
26
|
+
@broker = Wampproto::Broker.new(id_gen)
|
|
27
|
+
@dealer = Wampproto::Dealer.new(id_gen)
|
|
28
|
+
@clients = {}
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def attach_client(client)
|
|
32
|
+
session_id = client.session_id
|
|
33
|
+
session_details = client.acceptor.session_details
|
|
34
|
+
|
|
35
|
+
clients[session_id] = client
|
|
36
|
+
broker.add_session(session_details)
|
|
37
|
+
dealer.add_session(session_details)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def detach_client(client)
|
|
41
|
+
remove_client(client.session_id)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def clear
|
|
45
|
+
clients.each { |client| remove_client(client.session_id) }
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def receive_message(session_id, message)
|
|
49
|
+
case message
|
|
50
|
+
when *DEALER_MESSAGES then handle_dealer(session_id, message)
|
|
51
|
+
when *BROKER_MESSAGES then handle_broker(session_id, message)
|
|
52
|
+
when GOODBYE_MESSAGE then handle_goodbye(session_id, message)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
def handle_dealer(session_id, message)
|
|
59
|
+
send_message dealer.receive_message(session_id, message)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def handle_broker(session_id, message)
|
|
63
|
+
send_message broker.receive_message(session_id, message)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def handle_goodbye(session_id, _message)
|
|
67
|
+
goodbye = Wampproto::Message::Goodbye.new({}, "wamp.close.goodbye_and_out")
|
|
68
|
+
send_message Wampproto::MessageWithRecipient.new(goodbye, session_id)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def send_message(message_with_receipient)
|
|
72
|
+
Array(message_with_receipient).each do |object|
|
|
73
|
+
client = clients[object.recipient]
|
|
74
|
+
|
|
75
|
+
next unless client
|
|
76
|
+
|
|
77
|
+
client.send_message object.message
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def id_gen
|
|
82
|
+
@id_gen ||= Wampproto::IdGenerator.new
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def remove_client(session_id)
|
|
86
|
+
broker.remove_session(session_id)
|
|
87
|
+
dealer.remove_session(session_id)
|
|
88
|
+
clients.delete(session_id)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|