async-websocket 0.14.0 → 0.19.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/async/websocket/adapters/http.rb +64 -0
- data/lib/async/websocket/adapters/rack.rb +11 -28
- data/{spec/async/websocket/upgrade.rb → lib/async/websocket/adapters/rails.rb} +20 -19
- data/lib/async/websocket/client.rb +19 -13
- data/lib/async/websocket/connect_request.rb +4 -0
- data/lib/async/websocket/connection.rb +1 -0
- data/lib/async/websocket/version.rb +1 -1
- metadata +37 -101
- data/.editorconfig +0 -6
- data/.gitignore +0 -13
- data/.rspec +0 -3
- data/.travis.yml +0 -21
- data/Gemfile +0 -7
- data/README.md +0 -143
- data/async-websocket.gemspec +0 -29
- data/examples/chat/.env +0 -3
- data/examples/chat/README.md +0 -147
- data/examples/chat/client.rb +0 -32
- data/examples/chat/config.ru +0 -150
- data/examples/chat/multi-client.rb +0 -79
- data/examples/mud/client.rb +0 -34
- data/examples/mud/config.ru +0 -142
- data/examples/rack/client.rb +0 -19
- data/examples/rack/config.ru +0 -12
- data/examples/utopia/.bowerrc +0 -4
- data/examples/utopia/.gitignore +0 -9
- data/examples/utopia/.rspec +0 -4
- data/examples/utopia/Gemfile +0 -33
- data/examples/utopia/Guardfile +0 -29
- data/examples/utopia/README.md +0 -16
- data/examples/utopia/Rakefile +0 -8
- data/examples/utopia/config.ru +0 -47
- data/examples/utopia/config/README.md +0 -7
- data/examples/utopia/config/environment.rb +0 -8
- data/examples/utopia/lib/readme.txt +0 -1
- data/examples/utopia/pages/_heading.xnode +0 -2
- data/examples/utopia/pages/_page.xnode +0 -30
- data/examples/utopia/pages/client/client.js +0 -28
- data/examples/utopia/pages/client/index.xnode +0 -8
- data/examples/utopia/pages/errors/exception.xnode +0 -5
- data/examples/utopia/pages/errors/file-not-found.xnode +0 -5
- data/examples/utopia/pages/links.yaml +0 -2
- data/examples/utopia/pages/server/controller.rb +0 -26
- data/examples/utopia/public/_static/icon.png +0 -0
- data/examples/utopia/public/_static/site.css +0 -205
- data/examples/utopia/public/_static/utopia-background.svg +0 -1
- data/examples/utopia/public/_static/utopia.svg +0 -1
- data/examples/utopia/public/readme.txt +0 -1
- data/examples/utopia/spec/spec_helper.rb +0 -31
- data/examples/utopia/spec/website_context.rb +0 -11
- data/examples/utopia/spec/website_spec.rb +0 -56
- data/examples/utopia/tasks/bower.rake +0 -45
- data/examples/utopia/tasks/deploy.rake +0 -13
- data/examples/utopia/tasks/development.rake +0 -34
- data/examples/utopia/tasks/environment.rake +0 -17
- data/examples/utopia/tasks/log.rake +0 -17
- data/examples/utopia/tasks/static.rake +0 -43
- data/spec/async/websocket/adapters/rack/client.rb +0 -38
- data/spec/async/websocket/adapters/rack/config.ru +0 -23
- data/spec/async/websocket/adapters/rack_spec.rb +0 -84
- data/spec/async/websocket/connection_spec.rb +0 -34
- data/spec/async/websocket/server_examples.rb +0 -117
- data/spec/async/websocket/server_spec.rb +0 -31
- data/spec/spec_helper.rb +0 -16
@@ -1,79 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'async'
|
4
|
-
require 'async/semaphore'
|
5
|
-
require 'async/clock'
|
6
|
-
require 'async/io/stream'
|
7
|
-
require 'async/http/endpoint'
|
8
|
-
require_relative '../../lib/async/websocket/client'
|
9
|
-
|
10
|
-
require 'samovar'
|
11
|
-
|
12
|
-
GC.disable
|
13
|
-
|
14
|
-
class Command < Samovar::Command
|
15
|
-
options do
|
16
|
-
option "-c/--count <integer>", "The total number of connections to make.", default: 1000, type: Integer
|
17
|
-
option "--bind <address>", "The local address to bind to before making a connection."
|
18
|
-
option "--connect <string>", "The remote server to connect to.", default: "https://localhost:8080"
|
19
|
-
|
20
|
-
option "-s/--semaphore <integer>", "The number of simultaneous connections to perform."
|
21
|
-
end
|
22
|
-
|
23
|
-
def local_address
|
24
|
-
if bind = @options[:bind]
|
25
|
-
Async::IO::Address.tcp(bind, 0)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def call
|
30
|
-
endpoint = Async::HTTP::Endpoint.parse(@options[:connect])
|
31
|
-
# endpoint = endpoint.each.first
|
32
|
-
|
33
|
-
count = @options[:count]
|
34
|
-
|
35
|
-
connections = Async::Queue.new
|
36
|
-
|
37
|
-
Async do |task|
|
38
|
-
task.logger.info!
|
39
|
-
|
40
|
-
task.async do |subtask|
|
41
|
-
while connection = connections.dequeue
|
42
|
-
subtask.async(connection) do |subtask, connection|
|
43
|
-
while message = connection.read
|
44
|
-
puts "> #{message.inspect}"
|
45
|
-
end
|
46
|
-
ensure
|
47
|
-
connection.close
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
GC.start
|
52
|
-
end
|
53
|
-
|
54
|
-
client = Async::WebSocket::Client.open(endpoint)
|
55
|
-
start_time = Async::Clock.now
|
56
|
-
|
57
|
-
count.times do |i|
|
58
|
-
connections.enqueue(client.connect(endpoint.path))
|
59
|
-
|
60
|
-
if (i % 10000).zero?
|
61
|
-
count = i+1
|
62
|
-
duration = Async::Clock.now - start_time
|
63
|
-
Async.logger.info(self) {"Made #{count} connections: #{(count/duration).round(2)} connections/second..."}
|
64
|
-
end
|
65
|
-
|
66
|
-
if (i % 10000).zero?
|
67
|
-
duration = Async::Clock.measure{GC.start(full_mark: false, immediate_sweep: false)}
|
68
|
-
Async.logger.info(self) {"GC.start duration=#{duration.round(2)}s GC.count=#{GC.count}"}
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
connections.enqueue(nil)
|
73
|
-
|
74
|
-
Async.logger.info(self) {"Finished top level connection loop..."}
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
Command.call
|
data/examples/mud/client.rb
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'async'
|
4
|
-
require 'async/io/stream'
|
5
|
-
require 'async/http/endpoint'
|
6
|
-
require 'async/websocket/client'
|
7
|
-
|
8
|
-
USER = ARGV.pop || "anonymous"
|
9
|
-
URL = ARGV.pop || "http://127.0.0.1:7070"
|
10
|
-
|
11
|
-
Async do |task|
|
12
|
-
stdin = Async::IO::Stream.new(
|
13
|
-
Async::IO::Generic.new($stdin)
|
14
|
-
)
|
15
|
-
|
16
|
-
endpoint = Async::HTTP::Endpoint.parse(URL)
|
17
|
-
|
18
|
-
Async::WebSocket::Client.connect(endpoint) do |connection|
|
19
|
-
task.async do
|
20
|
-
$stdout.write "> "
|
21
|
-
|
22
|
-
while line = stdin.read_until("\n")
|
23
|
-
connection.write({input: line})
|
24
|
-
connection.flush
|
25
|
-
|
26
|
-
$stdout.write "> "
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
while message = connection.read
|
31
|
-
$stdout.puts message
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
data/examples/mud/config.ru
DELETED
@@ -1,142 +0,0 @@
|
|
1
|
-
#!/usr/bin/env -S falcon serve --count 1 --bind http://127.0.0.1:7070 -c
|
2
|
-
|
3
|
-
require 'async/websocket/adapters/rack'
|
4
|
-
|
5
|
-
class Room
|
6
|
-
def initialize(name, description = nil)
|
7
|
-
@name = name
|
8
|
-
@description = description
|
9
|
-
|
10
|
-
@actions = {}
|
11
|
-
@users = []
|
12
|
-
end
|
13
|
-
|
14
|
-
attr :name
|
15
|
-
attr :description
|
16
|
-
|
17
|
-
attr :actions
|
18
|
-
|
19
|
-
def connect(key, room)
|
20
|
-
@actions[key] = lambda do |user|
|
21
|
-
self.exit(user)
|
22
|
-
room.enter(user)
|
23
|
-
end
|
24
|
-
|
25
|
-
return room
|
26
|
-
end
|
27
|
-
|
28
|
-
def broadcast(message)
|
29
|
-
@users.each do |user|
|
30
|
-
user.write(message)
|
31
|
-
user.flush
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def enter(user)
|
36
|
-
user.notify("You have entered the #{@name}.")
|
37
|
-
user.room = self
|
38
|
-
|
39
|
-
@users << user
|
40
|
-
|
41
|
-
@users.each do |user|
|
42
|
-
user.notify("#{user.name} entered the room.")
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def exit(user)
|
47
|
-
if @users.delete(user)
|
48
|
-
@users.each do |user|
|
49
|
-
user.notify("#{user.name} left the room.")
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def as_json
|
55
|
-
{
|
56
|
-
name: @name,
|
57
|
-
description: @description,
|
58
|
-
actions: @actions.keys,
|
59
|
-
}
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
module Command
|
64
|
-
def self.split(line)
|
65
|
-
line.scan(/(?:"")|(?:"(.*[^\\])")|(\w+)/).flatten.compact
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
class User < Async::WebSocket::Connection
|
70
|
-
def initialize(*)
|
71
|
-
super
|
72
|
-
|
73
|
-
@name = name
|
74
|
-
@room = nil
|
75
|
-
@inventory = []
|
76
|
-
end
|
77
|
-
|
78
|
-
attr_accessor :room
|
79
|
-
|
80
|
-
ANONYMOUS = "Anonymous"
|
81
|
-
|
82
|
-
def name
|
83
|
-
@name || ANONYMOUS
|
84
|
-
end
|
85
|
-
|
86
|
-
def handle(message)
|
87
|
-
key, *arguments = Command.split(message[:input])
|
88
|
-
case key
|
89
|
-
when "name"
|
90
|
-
@name = arguments.first
|
91
|
-
when "look"
|
92
|
-
self.write({room: @room.as_json})
|
93
|
-
else
|
94
|
-
if action = @room.actions[key]
|
95
|
-
action.call(self, *arguments)
|
96
|
-
else
|
97
|
-
message[:user]
|
98
|
-
@room.broadcast(message)
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
def notify(text)
|
104
|
-
self.write({notify: text})
|
105
|
-
self.flush
|
106
|
-
end
|
107
|
-
|
108
|
-
def close
|
109
|
-
if @room
|
110
|
-
@room.exit(self)
|
111
|
-
end
|
112
|
-
|
113
|
-
super
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
class Server
|
118
|
-
def initialize(app)
|
119
|
-
@app = app
|
120
|
-
|
121
|
-
@entrance = Room.new("Portal", "A vast entrance foyer with a flowing portal.")
|
122
|
-
@entrance.connect("forward", Room.new("Training Room"))
|
123
|
-
@entrance.connect("corridor", Room.new("Shop"))
|
124
|
-
end
|
125
|
-
|
126
|
-
def call(env)
|
127
|
-
Async::WebSocket::Adapters::Rack.open(env, handler: User) do |user|
|
128
|
-
@entrance.enter(user)
|
129
|
-
|
130
|
-
while message = user.read
|
131
|
-
user.handle(message)
|
132
|
-
end
|
133
|
-
ensure
|
134
|
-
# Async.logger.error(self, $!) if $!
|
135
|
-
user.close
|
136
|
-
end or @app.call(env)
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
use Server
|
141
|
-
|
142
|
-
run lambda {|env| [200, {}, []]}
|
data/examples/rack/client.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'async'
|
4
|
-
require 'async/http/endpoint'
|
5
|
-
require 'async/websocket/client'
|
6
|
-
|
7
|
-
URL = ARGV.pop || "http://127.0.0.1:7070"
|
8
|
-
|
9
|
-
Async do |task|
|
10
|
-
endpoint = Async::HTTP::Endpoint.parse(URL)
|
11
|
-
|
12
|
-
Async::WebSocket::Client.connect(endpoint) do |connection|
|
13
|
-
connection.write ["Hello", "World"]
|
14
|
-
|
15
|
-
while message = connection.read
|
16
|
-
p message
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
data/examples/rack/config.ru
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
#!/usr/bin/env -S falcon serve --bind http://127.0.0.1:7070 --count 1 -c
|
2
|
-
|
3
|
-
require 'async/websocket/adapters/rack'
|
4
|
-
|
5
|
-
app = lambda do |env|
|
6
|
-
Async::WebSocket::Adapters::Rack.open(env) do |connection|
|
7
|
-
message = connection.read
|
8
|
-
connection.write message.reverse
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
run app
|
data/examples/utopia/.bowerrc
DELETED
data/examples/utopia/.gitignore
DELETED
data/examples/utopia/.rspec
DELETED
data/examples/utopia/Gemfile
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
|
2
|
-
source "https://rubygems.org"
|
3
|
-
|
4
|
-
gem "utopia", "~> 2.9.3"
|
5
|
-
|
6
|
-
gem "rake"
|
7
|
-
gem "bundler"
|
8
|
-
|
9
|
-
gem 'async-websocket'
|
10
|
-
|
11
|
-
gem "rack-freeze", "~> 1.2"
|
12
|
-
|
13
|
-
group :development do
|
14
|
-
# For `rake server`:
|
15
|
-
gem "guard-falcon", require: false
|
16
|
-
gem 'guard-rspec', require: false
|
17
|
-
|
18
|
-
# For `rake console`:
|
19
|
-
gem "pry"
|
20
|
-
gem "rack-test"
|
21
|
-
|
22
|
-
# For `rspec` testing:
|
23
|
-
gem "rspec"
|
24
|
-
gem "simplecov"
|
25
|
-
|
26
|
-
# For testing:
|
27
|
-
gem 'async-rspec'
|
28
|
-
end
|
29
|
-
|
30
|
-
group :production do
|
31
|
-
# Used for passenger-config to restart server after deployment:
|
32
|
-
gem "passenger"
|
33
|
-
end
|
data/examples/utopia/Guardfile
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
|
2
|
-
group :development do
|
3
|
-
guard :falcon, port: 9292 do
|
4
|
-
watch('Gemfile.lock')
|
5
|
-
watch('config.ru')
|
6
|
-
watch(%r{^config|lib|pages/.*})
|
7
|
-
|
8
|
-
notification :off
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
group :test do
|
13
|
-
guard :rspec, cmd: 'rspec' do
|
14
|
-
# Notifications can get a bit tedious:
|
15
|
-
# notification :off
|
16
|
-
|
17
|
-
# Re-run specs if they are changed:
|
18
|
-
watch(%r{^spec/.+_spec\.rb$})
|
19
|
-
watch('spec/spec_helper.rb') {'spec'}
|
20
|
-
|
21
|
-
# Run relevent specs if files in `lib/` or `pages/` are changed:
|
22
|
-
watch(%r{^lib/(.+)\.rb$}) {|match| "spec/lib/#{match[1]}_spec.rb" }
|
23
|
-
watch(%r{^pages/(.+)\.(rb|xnode)$}) {|match| "spec/pages/#{match[1]}_spec.rb"}
|
24
|
-
watch(%r{^pages/(.+)controller\.rb$}) {|match| Dir.glob("spec/pages/#{match[1]}*_spec.rb")}
|
25
|
-
|
26
|
-
# If any files in pages changes, ensure the website still works:
|
27
|
-
watch(%r{^pages/.*}) {'spec/website_spec.rb'}
|
28
|
-
end
|
29
|
-
end
|
data/examples/utopia/README.md
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
# Example WebSocket Chat Server
|
2
|
-
|
3
|
-
This is a simple chat client/server implementation with specs.
|
4
|
-
|
5
|
-
## Starting Development Server
|
6
|
-
|
7
|
-
To start the development server, simply execute
|
8
|
-
|
9
|
-
> rake
|
10
|
-
Generating transient session key for development...
|
11
|
-
20:57:36 - INFO - Starting Falcon HTTP server on localhost:9292
|
12
|
-
20:57:36 - INFO - Guard::RSpec is running
|
13
|
-
20:57:36 - INFO - Guard is now watching at '...'
|
14
|
-
[1] guard(main)>
|
15
|
-
|
16
|
-
Then browse http://localhost:9292 (or as specified) to see your new site.
|
data/examples/utopia/Rakefile
DELETED
data/examples/utopia/config.ru
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
#!/usr/bin/env rackup
|
2
|
-
|
3
|
-
require_relative 'config/environment'
|
4
|
-
|
5
|
-
require 'rack/freeze'
|
6
|
-
|
7
|
-
if RACK_ENV == :production
|
8
|
-
# Handle exceptions in production with a error page and send an email notification:
|
9
|
-
use Utopia::Exceptions::Handler
|
10
|
-
use Utopia::Exceptions::Mailer
|
11
|
-
else
|
12
|
-
# We want to propate exceptions up when running tests:
|
13
|
-
use Rack::ShowExceptions unless RACK_ENV == :test
|
14
|
-
|
15
|
-
# Serve the public directory in a similar way to the web server:
|
16
|
-
use Utopia::Static, root: 'public'
|
17
|
-
end
|
18
|
-
|
19
|
-
use Rack::Sendfile
|
20
|
-
|
21
|
-
use Utopia::ContentLength
|
22
|
-
|
23
|
-
use Utopia::Redirection::Rewrite,
|
24
|
-
'/' => '/client/index'
|
25
|
-
|
26
|
-
use Utopia::Redirection::DirectoryIndex
|
27
|
-
|
28
|
-
use Utopia::Redirection::Errors,
|
29
|
-
404 => '/errors/file-not-found'
|
30
|
-
|
31
|
-
use Utopia::Localization,
|
32
|
-
:default_locale => 'en',
|
33
|
-
:locales => ['en', 'de', 'ja', 'zh']
|
34
|
-
|
35
|
-
require 'utopia/session'
|
36
|
-
use Utopia::Session,
|
37
|
-
:expires_after => 3600 * 24,
|
38
|
-
:secret => ENV['UTOPIA_SESSION_SECRET']
|
39
|
-
|
40
|
-
use Utopia::Controller
|
41
|
-
|
42
|
-
use Utopia::Static
|
43
|
-
|
44
|
-
# Serve dynamic content
|
45
|
-
use Utopia::Content
|
46
|
-
|
47
|
-
run lambda { |env| [404, {}, []] }
|