xconn 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f4a4f50da44bd4849d8e503de34fcdee9edf558c06244ec43746b81401c09e3a
|
4
|
+
data.tar.gz: 5624eedc589212e83ba1684ab67e06d27bbb14c35dc8cf91245aed67b92475ce
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2867240ea024fafcd2fbc93da161473a546989fe349bc9be61a3e12c209d2358187957f291b0ee9d58874e524139cbfbd567838a4305bde178bb5c7e2519f253
|
7
|
+
data.tar.gz: 477e4d9640d8da4e555ace59c5b29f76c7b2b799399c4ad76e17ef9402ca2284519299c4b1e931b18d8e788ba60af7c72300f87819969743e51819fcd9bfb403
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.6
|
3
|
+
NewCops: enable
|
4
|
+
|
5
|
+
Style/StringLiterals:
|
6
|
+
Enabled: true
|
7
|
+
EnforcedStyle: double_quotes
|
8
|
+
|
9
|
+
Style/StringLiteralsInInterpolation:
|
10
|
+
Enabled: true
|
11
|
+
EnforcedStyle: double_quotes
|
12
|
+
|
13
|
+
Layout/LineLength:
|
14
|
+
Max: 120
|
15
|
+
|
16
|
+
Metrics/BlockLength:
|
17
|
+
Enabled: false
|
18
|
+
|
19
|
+
Layout/BeginEndAlignment:
|
20
|
+
EnforcedStyleAlignWith: start_of_line
|
21
|
+
|
22
|
+
Layout/EndAlignment:
|
23
|
+
EnforcedStyleAlignWith: start_of_line
|
24
|
+
|
25
|
+
Layout/MultilineMethodCallIndentation:
|
26
|
+
EnforcedStyle: indented
|
27
|
+
|
28
|
+
Layout/CaseIndentation:
|
29
|
+
EnforcedStyle: end
|
data/CHANGELOG.md
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2024 Simple Things Inc.
|
4
|
+
Copyright (c) 2024 XConnIO Ltd.
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
8
|
+
in the Software without restriction, including without limitation the rights
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
11
|
+
furnished to do so, subject to the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
14
|
+
copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
22
|
+
SOFTWARE.
|
data/Makefile
ADDED
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
require "rspec/core/rake_task"
|
5
|
+
|
6
|
+
RSpec::Core::RakeTask.new(:spec)
|
7
|
+
|
8
|
+
require "rubocop/rake_task"
|
9
|
+
|
10
|
+
RuboCop::RakeTask.new
|
11
|
+
|
12
|
+
task default: %i[spec rubocop]
|
13
|
+
|
14
|
+
Dir.glob("lib/tasks/**/*.rake").each { |r| load r }
|
data/bin/xconn
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require "wamp"
|
6
|
+
|
7
|
+
require "optparse"
|
8
|
+
|
9
|
+
options = { host: "127.0.0.1", port: 8080, realm: "realm1", directory: ".", app: "App" }
|
10
|
+
OptionParser.new do |opts|
|
11
|
+
opts.banner = "Usage: xconn [options]"
|
12
|
+
|
13
|
+
opts.on("-hHOST", "--host HOST", "WebSocket host (default: ws://127.0.0.1:8080/ws)") do |host|
|
14
|
+
options[:host] = host
|
15
|
+
end
|
16
|
+
|
17
|
+
opts.on("-rREALM", "--realm REALM", "Realm (default: reaml1)") do |realm|
|
18
|
+
options[:realm] = realm
|
19
|
+
end
|
20
|
+
|
21
|
+
opts.on("-pPORT", "--port PORT", "Port (default: 8080)") do |port|
|
22
|
+
options[:port] = port
|
23
|
+
end
|
24
|
+
|
25
|
+
opts.on("-dDIRECTORY", "--directory DIRECTORY", 'Directory (default: ".")') do |directory|
|
26
|
+
options[:directory] = directory
|
27
|
+
end
|
28
|
+
|
29
|
+
opts.on("-aAPP", "--app APP", 'App (default: "App")') do |app|
|
30
|
+
options[:app] = app
|
31
|
+
end
|
32
|
+
|
33
|
+
opts.on("-v", "--version", "Gem Version") do |version|
|
34
|
+
options[:version] = version
|
35
|
+
end
|
36
|
+
end.parse!
|
37
|
+
|
38
|
+
if options.include?(:version)
|
39
|
+
puts "Xconn v#{Wamp::VERSION}"
|
40
|
+
exit 0
|
41
|
+
end
|
42
|
+
|
43
|
+
def create_client_session(router)
|
44
|
+
session = Wamp::Connection::Session.new
|
45
|
+
|
46
|
+
server_session = Wamp::Router::Client.new
|
47
|
+
server_session.router = router
|
48
|
+
server_session.connection = session
|
49
|
+
|
50
|
+
session.stream = server_session
|
51
|
+
session
|
52
|
+
end
|
53
|
+
|
54
|
+
router = Wamp::Router::Base.new
|
55
|
+
router.add_realm(options.fetch(:realm))
|
56
|
+
|
57
|
+
client = create_client_session(router).tap(&:on_open)
|
58
|
+
|
59
|
+
begin
|
60
|
+
Pathname.new(options[:directory]).glob("**/*.rb").each { |file| require file.to_s }
|
61
|
+
rescue LoadError => e
|
62
|
+
puts e.message
|
63
|
+
exit 1
|
64
|
+
end
|
65
|
+
|
66
|
+
begin
|
67
|
+
app = Object.const_get(options[:app])
|
68
|
+
app.new.procedures.each do |procedure, func|
|
69
|
+
client.api.register(procedure, func) do
|
70
|
+
puts "Registered procedure: #{procedure}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
rescue StandardError => e
|
74
|
+
puts e.message
|
75
|
+
exit 1
|
76
|
+
end
|
77
|
+
|
78
|
+
server = Wamp::Router::Server.new(router, options)
|
79
|
+
server.run
|
data/docs/index.md
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "wamp"
|
4
|
+
require "date"
|
5
|
+
require_relative "included_app"
|
6
|
+
|
7
|
+
# SystemApp
|
8
|
+
class Example < Wamp::App
|
9
|
+
register echo: "io.xconn.echo", current_date: "io.xconn.date.get"
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
super
|
13
|
+
include_app(IncludedApp.new, "test.")
|
14
|
+
end
|
15
|
+
|
16
|
+
def echo(invocation)
|
17
|
+
Wamp::Type::Result.new(args: invocation.args, kwargs: invocation.kwargs, details: invocation.details)
|
18
|
+
end
|
19
|
+
|
20
|
+
def current_date(_invocation)
|
21
|
+
Wamp::Type::Result.new(args: Date.today.iso8601)
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "wamp"
|
4
|
+
|
5
|
+
# Class that can be included
|
6
|
+
class IncludedApp < Wamp::App
|
7
|
+
register echo: "foo.bar.echo"
|
8
|
+
|
9
|
+
def echo(invocation)
|
10
|
+
Wamp::Type::Result.new(args: invocation.args, kwargs: invocation.kwargs, details: invocation.details)
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
namespace :xconn do
|
4
|
+
desc "Start SAMPLE app"
|
5
|
+
task :run, [:host, :port, :realm, :directory, :app] do |_t, args|
|
6
|
+
host = args[:host] || "127.0.0.1"
|
7
|
+
port = args[:port] || 8080
|
8
|
+
realm = args[:realm] || "realm1"
|
9
|
+
app = args[:app] || "Example"
|
10
|
+
directory = args[:directory] || "./example/sample"
|
11
|
+
|
12
|
+
command = "bin/xconn -h #{host} -p #{port} -r #{realm} -d #{directory} -a #{app}"
|
13
|
+
|
14
|
+
puts "Running: #{command}"
|
15
|
+
|
16
|
+
trap("SIGINT") do
|
17
|
+
puts "\nReceived SIGINT. Gracefully exiting..."
|
18
|
+
|
19
|
+
exit 0
|
20
|
+
end
|
21
|
+
|
22
|
+
`#{command}`
|
23
|
+
end
|
24
|
+
end
|
data/lib/wamp/app.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wamp
|
4
|
+
# WAMPApp
|
5
|
+
class App
|
6
|
+
def initialize
|
7
|
+
@procedures = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def include_app(app, prefix = "")
|
11
|
+
if prefix&.length&.zero?
|
12
|
+
procedures.merge!(app.procedures)
|
13
|
+
else
|
14
|
+
app.procedures.each do |procedure, func|
|
15
|
+
procedures.merge!({ "#{prefix}#{procedure}" => func })
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def procedures
|
21
|
+
return {} if self.class.procedures && self.class.procedures.empty?
|
22
|
+
return @procedures if @procedures.any?
|
23
|
+
|
24
|
+
self.class.procedures.map do |procedure, registration_name|
|
25
|
+
@procedures[registration_name.to_s] = method(procedure)
|
26
|
+
end
|
27
|
+
@procedures
|
28
|
+
end
|
29
|
+
|
30
|
+
class << self
|
31
|
+
attr_reader :procedures
|
32
|
+
|
33
|
+
def register(procedures = {})
|
34
|
+
@procedures ||= {}
|
35
|
+
@procedures.merge!(procedures)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wamp
|
4
|
+
module Connection
|
5
|
+
# Client Session
|
6
|
+
class Session
|
7
|
+
attr_reader :joiner, :session, :store, :api
|
8
|
+
attr_accessor :executor, :stream
|
9
|
+
|
10
|
+
def initialize(joiner = Wampproto::Joiner.new("realm1"))
|
11
|
+
@joiner = joiner
|
12
|
+
@session = Wampproto::Session.new(joiner.serializer)
|
13
|
+
@api = MessageHandler::Api.new(self)
|
14
|
+
@store = {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def on_join(&block)
|
18
|
+
self.executor = block
|
19
|
+
end
|
20
|
+
|
21
|
+
def on_open
|
22
|
+
stream.on_message joiner.send_hello
|
23
|
+
end
|
24
|
+
|
25
|
+
def on_message(data)
|
26
|
+
handler = MessageHandler.resolve(data, self)
|
27
|
+
handler.handle
|
28
|
+
end
|
29
|
+
|
30
|
+
def transmit(data)
|
31
|
+
stream.on_message data
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "nio4r"
|
4
|
+
|
5
|
+
module Wamp
|
6
|
+
module Connection
|
7
|
+
# creates actual socket and provides a way to read and write to it
|
8
|
+
class Stream
|
9
|
+
def initialize(socket_object)
|
10
|
+
@socket_object = socket_object
|
11
|
+
uri = URI.parse(socket_object.url)
|
12
|
+
|
13
|
+
@selector = NIO::Selector.new
|
14
|
+
@socket = TCPSocket.new(uri.host, uri.port)
|
15
|
+
monitor = @selector.register(@socket, :r)
|
16
|
+
monitor.value = proc { read_nonblock(monitor.io) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def write(data)
|
20
|
+
written = @socket.write_nonblock(data, exception: false)
|
21
|
+
|
22
|
+
case written
|
23
|
+
when :wait_writable
|
24
|
+
# procceed
|
25
|
+
when data.bytesize
|
26
|
+
data.bytesize
|
27
|
+
else
|
28
|
+
puts [:incomplete_write]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def receive(data)
|
33
|
+
@socket_object.parse(data)
|
34
|
+
end
|
35
|
+
|
36
|
+
def run
|
37
|
+
loop do
|
38
|
+
@selector.select { |monitor| monitor.value.call if monitor.readable? }
|
39
|
+
break if @closed
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def read_nonblock(io)
|
44
|
+
incoming = io.read_nonblock(4096, exception: false)
|
45
|
+
|
46
|
+
case incoming
|
47
|
+
when :wait_readable
|
48
|
+
nil
|
49
|
+
when nil
|
50
|
+
close
|
51
|
+
else
|
52
|
+
receive incoming
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def shutdown
|
57
|
+
@selector.deregister(@socket)
|
58
|
+
@socket.close
|
59
|
+
end
|
60
|
+
|
61
|
+
def close
|
62
|
+
shutdown
|
63
|
+
@socket_object.connection_gone
|
64
|
+
@closed = true
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "websocket/driver"
|
4
|
+
require_relative "stream"
|
5
|
+
|
6
|
+
module Wamp
|
7
|
+
module Connection
|
8
|
+
# handles opening connection and providing callbacks when data is avaialble
|
9
|
+
class WebsocketClient
|
10
|
+
CONNECTING = 0
|
11
|
+
OPEN = 1
|
12
|
+
CLOSING = 2
|
13
|
+
CLOSED = 3
|
14
|
+
|
15
|
+
attr_reader :url
|
16
|
+
|
17
|
+
def initialize(event_target, protocols) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
18
|
+
@event_target = event_target
|
19
|
+
|
20
|
+
@driver = @driver_started = nil
|
21
|
+
@close_params = ["", 1006]
|
22
|
+
|
23
|
+
@url = event_target.url
|
24
|
+
@ready_state = CONNECTING
|
25
|
+
|
26
|
+
@driver = WebSocket::Driver.client(self, protocols: protocols)
|
27
|
+
|
28
|
+
@driver.on(:open) { |_e| open }
|
29
|
+
@driver.on(:message) { |e| receive_message(e.data) }
|
30
|
+
@driver.on(:close) { |e| begin_close(e.reason, e.code) }
|
31
|
+
@driver.on(:error) { |e| emit_error(e.message) }
|
32
|
+
|
33
|
+
@stream = Wamp::Connection::Stream.new(self)
|
34
|
+
end
|
35
|
+
|
36
|
+
def run
|
37
|
+
start_driver
|
38
|
+
@stream.run
|
39
|
+
end
|
40
|
+
|
41
|
+
def start_driver
|
42
|
+
return if @driver_started
|
43
|
+
|
44
|
+
@driver_started = true
|
45
|
+
@driver.start
|
46
|
+
end
|
47
|
+
|
48
|
+
def write(data)
|
49
|
+
@stream.write(data)
|
50
|
+
rescue StandardError => e
|
51
|
+
emit_error(e.message)
|
52
|
+
end
|
53
|
+
|
54
|
+
def transmit(message)
|
55
|
+
return false if @ready_state > OPEN
|
56
|
+
|
57
|
+
case message
|
58
|
+
when Numeric then @driver.text(message.to_s)
|
59
|
+
when String then @driver.text(message)
|
60
|
+
when Array then @driver.binary(message)
|
61
|
+
else false
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def connection_gone
|
66
|
+
finalize_close
|
67
|
+
end
|
68
|
+
|
69
|
+
def close(code = nil, reason = nil)
|
70
|
+
code ||= 1000
|
71
|
+
reason ||= ""
|
72
|
+
|
73
|
+
unless code == 1000 || (code >= 3000 && code <= 4999)
|
74
|
+
raise ArgumentError, "Failed to execute 'close' on WebSocket: " \
|
75
|
+
"The code must be either 1000, or between 3000 and 4999. " \
|
76
|
+
"#{code} is neither."
|
77
|
+
end
|
78
|
+
|
79
|
+
@ready_state = CLOSING unless @ready_state == CLOSED
|
80
|
+
@driver.close(reason, code)
|
81
|
+
end
|
82
|
+
|
83
|
+
def parse(data)
|
84
|
+
@driver.parse(data)
|
85
|
+
end
|
86
|
+
|
87
|
+
def alive?
|
88
|
+
@ready_state == OPEN
|
89
|
+
end
|
90
|
+
|
91
|
+
# This is populated after successful handeshake
|
92
|
+
def protocol
|
93
|
+
@driver.protocol
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def open
|
99
|
+
return unless @ready_state == CONNECTING
|
100
|
+
|
101
|
+
@ready_state = OPEN
|
102
|
+
|
103
|
+
@event_target.on_open
|
104
|
+
end
|
105
|
+
|
106
|
+
def receive_message(data)
|
107
|
+
return unless @ready_state == OPEN
|
108
|
+
|
109
|
+
@event_target.on_message(data)
|
110
|
+
end
|
111
|
+
|
112
|
+
def emit_error(message)
|
113
|
+
return if @ready_state >= CLOSING
|
114
|
+
|
115
|
+
@event_target.on_error(message)
|
116
|
+
end
|
117
|
+
|
118
|
+
def begin_close(reason, code)
|
119
|
+
return if @ready_state == CLOSED
|
120
|
+
|
121
|
+
@ready_state = CLOSING
|
122
|
+
@close_params = [reason, code]
|
123
|
+
|
124
|
+
@stream.close
|
125
|
+
finalize_close
|
126
|
+
end
|
127
|
+
|
128
|
+
def finalize_close
|
129
|
+
return if @ready_state == CLOSED
|
130
|
+
|
131
|
+
@ready_state = CLOSED
|
132
|
+
|
133
|
+
@event_target.on_close(*@close_params)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "wampproto"
|
4
|
+
require_relative "websocket_client"
|
5
|
+
|
6
|
+
module Wamp
|
7
|
+
module Connection
|
8
|
+
# Conn
|
9
|
+
class WebSocketConnection < Session
|
10
|
+
attr_reader :url, :websocket
|
11
|
+
|
12
|
+
def initialize(url = "ws://localhost:8080/ws", joiner = Wampproto::Joiner.new("realm1"))
|
13
|
+
super(joiner)
|
14
|
+
@url = url
|
15
|
+
@websocket = Wamp::Connection::WebsocketClient.new(self, protocols)
|
16
|
+
end
|
17
|
+
|
18
|
+
def run
|
19
|
+
websocket.run
|
20
|
+
ensure
|
21
|
+
p %i[run close]
|
22
|
+
websocket.close
|
23
|
+
end
|
24
|
+
|
25
|
+
def on_open
|
26
|
+
transmit joiner.send_hello
|
27
|
+
end
|
28
|
+
|
29
|
+
def transmit(data)
|
30
|
+
websocket.transmit data
|
31
|
+
end
|
32
|
+
|
33
|
+
def on_close(reason, code)
|
34
|
+
p [:on_close, reason, code]
|
35
|
+
end
|
36
|
+
|
37
|
+
def on_error; end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def protocols
|
42
|
+
case joiner.serializer.name
|
43
|
+
when Wampproto::Serializer::JSON.name then "wamp.2.json"
|
44
|
+
when Wampproto::Serializer::Msgpack.name then "wamp.2.msgpack"
|
45
|
+
when Wampproto::Serializer::Cbor.name then "wamp.2.cbor"
|
46
|
+
end.then do |protocol|
|
47
|
+
[protocol]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "event"
|
4
|
+
require_relative "subscription"
|
5
|
+
|
6
|
+
module Wamp
|
7
|
+
module Manager
|
8
|
+
# no:doc
|
9
|
+
class Base
|
10
|
+
include WebSocket::Driver::EventEmitter
|
11
|
+
attr_reader :session
|
12
|
+
|
13
|
+
def initialize(options = {})
|
14
|
+
super()
|
15
|
+
@options = options
|
16
|
+
@session = Session.new(self)
|
17
|
+
end
|
18
|
+
|
19
|
+
def transmit(data); end
|
20
|
+
|
21
|
+
def on_message(message)
|
22
|
+
manager = Manager::Event.resolve(message, session)
|
23
|
+
manager.emit_event(message)
|
24
|
+
end
|
25
|
+
|
26
|
+
def auth
|
27
|
+
@options.fetch(:auth, Auth::Anonymous.new)
|
28
|
+
end
|
29
|
+
|
30
|
+
def run
|
31
|
+
message = Message::Hello.new("realm1")
|
32
|
+
manager = Manager::Event::Hello.new(message, session)
|
33
|
+
manager.add_event_listener # adds on :join event listener
|
34
|
+
end
|
35
|
+
|
36
|
+
def authenticate(challenge)
|
37
|
+
auth.authenticate(challenge)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wamp
|
4
|
+
module Manager
|
5
|
+
# connection
|
6
|
+
class Connection < Connection::Base
|
7
|
+
attr_reader :session
|
8
|
+
|
9
|
+
def initialize(*args)
|
10
|
+
super
|
11
|
+
@session = Session.new(self)
|
12
|
+
end
|
13
|
+
|
14
|
+
def on_message(data)
|
15
|
+
message = Message.resolve(coder.decode(data))
|
16
|
+
session.on_message(message)
|
17
|
+
end
|
18
|
+
|
19
|
+
def on_open
|
20
|
+
send_hello_message
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def send_hello_message
|
26
|
+
message = Message::Hello.new(@realm, auth.details)
|
27
|
+
manager = Manager::Event::Hello.new(message, self)
|
28
|
+
manager.add_event_listener # adds on :join event listener
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base"
|
4
|
+
|
5
|
+
module Wamp
|
6
|
+
module Manager
|
7
|
+
module Event
|
8
|
+
# Abort Message Event
|
9
|
+
class Abort < Base
|
10
|
+
def emit_event_name
|
11
|
+
:close
|
12
|
+
end
|
13
|
+
|
14
|
+
def emit_event(message)
|
15
|
+
session.emit(emit_event_name, message)
|
16
|
+
session.close(1000, message.reason)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|