async-websocket 0.13.1 → 0.18.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/lib/async/websocket/adapters/rack.rb +7 -1
  3. data/{spec/async/websocket/upgrade.rb → lib/async/websocket/adapters/rails.rb} +20 -19
  4. data/lib/async/websocket/client.rb +39 -17
  5. data/lib/async/websocket/connect_request.rb +31 -16
  6. data/lib/async/websocket/connect_response.rb +2 -2
  7. data/lib/async/websocket/connection.rb +21 -2
  8. data/lib/async/websocket/request.rb +1 -1
  9. data/lib/async/websocket/response.rb +1 -1
  10. data/lib/async/websocket/server.rb +2 -0
  11. data/lib/async/websocket/upgrade_request.rb +9 -9
  12. data/lib/async/websocket/upgrade_response.rb +3 -3
  13. data/lib/async/websocket/version.rb +1 -1
  14. metadata +36 -103
  15. data/.editorconfig +0 -6
  16. data/.gitignore +0 -13
  17. data/.rspec +0 -3
  18. data/.travis.yml +0 -18
  19. data/Gemfile +0 -12
  20. data/README.md +0 -129
  21. data/Rakefile +0 -6
  22. data/async-websocket.gemspec +0 -29
  23. data/examples/chat/README.md +0 -3
  24. data/examples/chat/client.rb +0 -32
  25. data/examples/chat/config.ru +0 -113
  26. data/examples/chat/multi-client.rb +0 -81
  27. data/examples/mud/client.rb +0 -34
  28. data/examples/mud/config.ru +0 -142
  29. data/examples/rack/client.rb +0 -20
  30. data/examples/rack/config.ru +0 -14
  31. data/examples/utopia/.bowerrc +0 -4
  32. data/examples/utopia/.gitignore +0 -9
  33. data/examples/utopia/.rspec +0 -4
  34. data/examples/utopia/Gemfile +0 -33
  35. data/examples/utopia/Guardfile +0 -29
  36. data/examples/utopia/README.md +0 -16
  37. data/examples/utopia/Rakefile +0 -8
  38. data/examples/utopia/config.ru +0 -47
  39. data/examples/utopia/config/README.md +0 -7
  40. data/examples/utopia/config/environment.rb +0 -8
  41. data/examples/utopia/lib/readme.txt +0 -1
  42. data/examples/utopia/pages/_heading.xnode +0 -2
  43. data/examples/utopia/pages/_page.xnode +0 -30
  44. data/examples/utopia/pages/client/client.js +0 -28
  45. data/examples/utopia/pages/client/index.xnode +0 -8
  46. data/examples/utopia/pages/errors/exception.xnode +0 -5
  47. data/examples/utopia/pages/errors/file-not-found.xnode +0 -5
  48. data/examples/utopia/pages/links.yaml +0 -2
  49. data/examples/utopia/pages/server/controller.rb +0 -26
  50. data/examples/utopia/public/_static/icon.png +0 -0
  51. data/examples/utopia/public/_static/site.css +0 -205
  52. data/examples/utopia/public/_static/utopia-background.svg +0 -1
  53. data/examples/utopia/public/_static/utopia.svg +0 -1
  54. data/examples/utopia/public/readme.txt +0 -1
  55. data/examples/utopia/spec/spec_helper.rb +0 -31
  56. data/examples/utopia/spec/website_context.rb +0 -11
  57. data/examples/utopia/spec/website_spec.rb +0 -56
  58. data/examples/utopia/tasks/bower.rake +0 -45
  59. data/examples/utopia/tasks/deploy.rake +0 -13
  60. data/examples/utopia/tasks/development.rake +0 -34
  61. data/examples/utopia/tasks/environment.rake +0 -17
  62. data/examples/utopia/tasks/log.rake +0 -17
  63. data/examples/utopia/tasks/static.rake +0 -43
  64. data/spec/async/websocket/adapters/rack/client.rb +0 -38
  65. data/spec/async/websocket/adapters/rack/config.ru +0 -23
  66. data/spec/async/websocket/adapters/rack_spec.rb +0 -84
  67. data/spec/async/websocket/client_spec.rb +0 -48
  68. data/spec/async/websocket/connection_spec.rb +0 -34
  69. data/spec/async/websocket/server_examples.rb +0 -81
  70. data/spec/async/websocket/server_spec.rb +0 -31
  71. data/spec/spec_helper.rb +0 -16
data/.editorconfig DELETED
@@ -1,6 +0,0 @@
1
- root = true
2
-
3
- [*]
4
- indent_style = tab
5
- indent_size = 2
6
-
data/.gitignore DELETED
@@ -1,13 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /_yardoc/
4
- /coverage/
5
- /doc/
6
- /pkg/
7
- /spec/reports/
8
- /tmp/
9
-
10
- # rspec failure tracking
11
- .rspec_status
12
- Gemfile.lock
13
- .covered.db
data/.rspec DELETED
@@ -1,3 +0,0 @@
1
- --format documentation
2
- --warnings
3
- --require spec_helper
data/.travis.yml DELETED
@@ -1,18 +0,0 @@
1
- language: ruby
2
- dist: xenial
3
- cache: bundler
4
-
5
- matrix:
6
- include:
7
- - rvm: 2.4
8
- - rvm: 2.5
9
- - rvm: 2.6
10
- - rvm: 2.6
11
- env: COVERAGE=PartialSummary,Coveralls
12
- - rvm: truffleruby
13
- - rvm: jruby-head
14
- env: JRUBY_OPTS="--debug -X+O"
15
- - rvm: ruby-head
16
- allow_failures:
17
- - rvm: ruby-head
18
- - rvm: jruby-head
data/Gemfile DELETED
@@ -1,12 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec
4
-
5
- group :test do
6
- gem 'rack-test'
7
- gem 'pry'
8
- end
9
-
10
- group :development do
11
- gem 'tty-progressbar'
12
- end
data/README.md DELETED
@@ -1,129 +0,0 @@
1
- # Async::WebSocket
2
-
3
- A simple asynchronous websocket client/server implementation for [HTTP/1](https://tools.ietf.org/html/rfc6455) and [HTTP/2](https://tools.ietf.org/html/rfc8441).
4
-
5
- [![Build Status](https://secure.travis-ci.org/socketry/async-websocket.svg)](http://travis-ci.org/socketry/async-websocket)
6
- [![Code Climate](https://codeclimate.com/github/socketry/async-websocket.svg)](https://codeclimate.com/github/socketry/async-websocket)
7
- [![Coverage Status](https://coveralls.io/repos/socketry/async-websocket/badge.svg)](https://coveralls.io/r/socketry/async-websocket)
8
-
9
- ## Installation
10
-
11
- Add this line to your application's Gemfile:
12
-
13
- gem 'async-websocket'
14
-
15
- And then execute:
16
-
17
- $ bundle
18
-
19
- Or install it yourself as:
20
-
21
- $ gem install async-websocket
22
-
23
- ## Usage
24
-
25
- There are [examples](examples/) which include:
26
-
27
- - [A command line chat client/server](examples/chat) which can read input from `stdin` and send messages to the server.
28
- - [A small MUD client/server](examples/mud) which uses JSON for communation between client/server.
29
- - [A utopia-based web application](examples/utopia) which uses a JavaScript client to connect to a web application server.
30
-
31
- ### Client Side with Async
32
-
33
- ```ruby
34
- #!/usr/bin/env ruby
35
-
36
- require 'async'
37
- require 'async/io/stream'
38
- require 'async/http/endpoint'
39
- require 'async/websocket/client'
40
-
41
- USER = ARGV.pop || "anonymous"
42
- URL = ARGV.pop || "http://localhost:7070"
43
-
44
- Async do |task|
45
- stdin = Async::IO::Stream.new(
46
- Async::IO::Generic.new($stdin)
47
- )
48
-
49
- endpoint = Async::HTTP::Endpoint.parse(URL)
50
-
51
- Async::WebSocket::Client.open(endpoint) do |connection|
52
- input_task = task.async do
53
- while line = stdin.read_until("\n")
54
- connection.write({user: USER, text: line})
55
- connection.flush
56
- end
57
- end
58
-
59
- connection.write({
60
- user: USER,
61
- status: "connected",
62
- })
63
-
64
- while message = connection.read
65
- puts message.inspect
66
- end
67
- ensure
68
- input_task&.stop
69
- end
70
- end
71
- ```
72
-
73
- ### Server Side with Rack & Falcon
74
-
75
- ```ruby
76
- #!/usr/bin/env -S falcon serve --bind http://localhost:7070 --count 1 -c
77
-
78
- require 'async/websocket/adapters/rack'
79
- require 'set'
80
-
81
- $connections = Set.new
82
-
83
- run lambda {|env|
84
- Async::WebSocket::Adapters::Rack.open(env, protocols: ['ws']) do |connection|
85
- $connections << connection
86
-
87
- while message = connection.read
88
- $connections.each do |connection|
89
- connection.write(message)
90
- connection.flush
91
- end
92
- end
93
- ensure
94
- $connections.delete(connection)
95
- end or [200, {}, ["Hello World"]]
96
- }
97
- ```
98
-
99
- ## Contributing
100
-
101
- 1. Fork it
102
- 2. Create your feature branch (`git checkout -b my-new-feature`)
103
- 3. Commit your changes (`git commit -am 'Add some feature'`)
104
- 4. Push to the branch (`git push origin my-new-feature`)
105
- 5. Create new Pull Request
106
-
107
- ## License
108
-
109
- Released under the MIT license.
110
-
111
- Copyright, 2015, by [Samuel G. D. Williams](http://www.codeotaku.com/samuel-williams).
112
-
113
- Permission is hereby granted, free of charge, to any person obtaining a copy
114
- of this software and associated documentation files (the "Software"), to deal
115
- in the Software without restriction, including without limitation the rights
116
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
117
- copies of the Software, and to permit persons to whom the Software is
118
- furnished to do so, subject to the following conditions:
119
-
120
- The above copyright notice and this permission notice shall be included in
121
- all copies or substantial portions of the Software.
122
-
123
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
124
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
125
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
126
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
127
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
128
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
129
- THE SOFTWARE.
data/Rakefile DELETED
@@ -1,6 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
3
-
4
- RSpec::Core::RakeTask.new(:spec)
5
-
6
- task :default => :spec
@@ -1,29 +0,0 @@
1
-
2
- require_relative 'lib/async/websocket/version'
3
-
4
- Gem::Specification.new do |spec|
5
- spec.name = "async-websocket"
6
- spec.version = Async::WebSocket::VERSION
7
- spec.authors = ["Samuel Williams"]
8
- spec.email = ["samuel.williams@oriontransfer.co.nz"]
9
- spec.summary = %q{An async websocket library on top of websocket-driver.}
10
- spec.homepage = ""
11
- spec.license = "MIT"
12
-
13
- spec.files = `git ls-files -z`.split("\x0")
14
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
15
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
16
- spec.require_paths = ["lib"]
17
-
18
- spec.add_dependency "async-io", "~> 1.23"
19
- spec.add_dependency "async-http", "~> 0.43"
20
- spec.add_dependency "protocol-websocket", "~> 0.7.0"
21
-
22
- spec.add_development_dependency "async-rspec"
23
- spec.add_development_dependency "falcon", "~> 0.32"
24
-
25
- spec.add_development_dependency "covered"
26
- spec.add_development_dependency "bundler"
27
- spec.add_development_dependency "rspec", "~> 3.6"
28
- spec.add_development_dependency "rake"
29
- end
@@ -1,3 +0,0 @@
1
- # The Journey to One Million
2
-
3
-
@@ -1,32 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'async'
4
- require 'async/io/stream'
5
- require 'async/http/endpoint'
6
- require_relative '../../lib/async/websocket/client'
7
-
8
- USER = ARGV.pop || "anonymous"
9
- URL = ARGV.pop || "https://localhost:8080"
10
- ENDPOINT = Async::HTTP::Endpoint.parse(URL)
11
-
12
- Async do |task|
13
- stdin = Async::IO::Stream.new(
14
- Async::IO::Generic.new($stdin)
15
- )
16
-
17
- Async::WebSocket::Client.connect(ENDPOINT) do |connection|
18
- input_task = task.async do
19
- while line = stdin.read_until("\n")
20
- connection.write({text: line})
21
- connection.flush
22
- end
23
- end
24
-
25
- puts "Connected..."
26
- while message = connection.read
27
- puts "> #{message.inspect}"
28
- end
29
- ensure
30
- input_task&.stop
31
- end
32
- end
@@ -1,113 +0,0 @@
1
- #!/usr/bin/env -S falcon serve --bind https://localhost:8080 --count 1 -c
2
-
3
- require_relative '../../lib/async/websocket/adapters/rack'
4
- require 'async/clock'
5
- require 'async/semaphore'
6
- require 'async/logger'
7
-
8
- require 'set'
9
-
10
- GC.disable
11
-
12
- class Room
13
- def initialize
14
- @connections = Set.new
15
- @semaphore = Async::Semaphore.new(512)
16
- end
17
-
18
- def connect connection
19
- @connections << connection
20
- end
21
-
22
- def disconnect connection
23
- @connections.delete(connection)
24
- end
25
-
26
- def each(&block)
27
- @connections.each(&block)
28
- end
29
-
30
- def allocations
31
- counts = Hash.new{|h,k| h[k] = 0}
32
-
33
- ObjectSpace.each_object do |object|
34
- counts[object.class] += 1
35
- end
36
-
37
- return counts
38
- end
39
-
40
- def show_allocations(key, limit = 1000)
41
- Async.logger.info(self) do |buffer|
42
- ObjectSpace.each_object(key).each do |object|
43
- buffer.puts object
44
- end
45
- end
46
- end
47
-
48
- def print_allocations(minimum = @connections.count)
49
- count = 0
50
-
51
- Async.logger.info(self) do |buffer|
52
- allocations.select{|k,v| v >= minimum}.sort_by{|k,v| -v}.each do |key, value|
53
- count += value
54
- buffer.puts "#{key}: #{value} allocations"
55
- end
56
-
57
- buffer.puts "** #{count.to_f / @connections.count} objects per connection."
58
- end
59
- end
60
-
61
- def command(code)
62
- Async.logger.warn self, "eval(#{code})"
63
-
64
- eval(code)
65
- end
66
-
67
- def broadcast(message)
68
- Async.logger.info "Broadcast: #{message.inspect}"
69
- start_time = Async::Clock.now
70
-
71
- @connections.each do |connection|
72
- @semaphore.async do
73
- connection.write(message)
74
- connection.flush
75
- end
76
- end
77
-
78
- end_time = Async::Clock.now
79
- Async.logger.info "Duration: #{(end_time - start_time).round(3)}s for #{@connections.count} connected clients."
80
- end
81
-
82
- def open(connection)
83
- self.connect(connection)
84
-
85
- while message = connection.read
86
- if message[:text] =~ /^\/(.*?)$/
87
- begin
88
- result = self.command($1)
89
-
90
- if result.is_a? Hash
91
- connection.write(result)
92
- else
93
- connection.write({result: result.inspect})
94
- end
95
- rescue
96
- connection.write({error: $!.inspect})
97
- end
98
- else
99
- self.broadcast(message)
100
- end
101
- end
102
-
103
- connection.close
104
- ensure
105
- self.disconnect(connection)
106
- end
107
-
108
- def call(env)
109
- Async::WebSocket::Adapters::Rack.open(env, &self.method(:open))
110
- end
111
- end
112
-
113
- run Room.new
@@ -1,81 +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
- require 'ruby-prof'
12
-
13
- require 'tty/progressbar'
14
-
15
- GC.disable
16
-
17
- class Command < Samovar::Command
18
- options do
19
- option "-c/--count <integer>", "The total number of connections to make.", default: 1000, type: Integer
20
- option "--bind <address>", "The local address to bind to before making a connection."
21
- option "--connect <string>", "The remote server to connect to.", default: "https://localhost:8080"
22
-
23
- option "-s/--semaphore <integer>", "The number of simultaneous connections to perform."
24
- end
25
-
26
- def local_address
27
- if bind = @options[:bind]
28
- Async::IO::Address.tcp(bind, 0)
29
- end
30
- end
31
-
32
- def call
33
- endpoint = Async::HTTP::Endpoint.parse(@options[:connect], local_address: self.local_address)
34
- count = @options[:count]
35
-
36
- connections = Async::Queue.new
37
- progress = TTY::ProgressBar.new(":rate connection/s [:bar] :current/:total (:eta/:elapsed)", total: count)
38
-
39
- # profile = RubyProf::Profile.new(merge_fibers: true)
40
- # profile.start
41
-
42
- Async do |task|
43
- task.logger.info!
44
-
45
- task.async do |subtask|
46
- while connection = connections.dequeue
47
- subtask.async(connection) do |subtask, connection|
48
- pp connection.read
49
-
50
- while message = connection.read
51
- pp message
52
- end
53
- ensure
54
- connection.close
55
- end
56
- end
57
-
58
- # subtask.children.each(&:stop)
59
- end
60
-
61
- client = Async::WebSocket::Client.open(endpoint)
62
-
63
- count.times do |i|
64
- connections.enqueue(client.connect(endpoint.path))
65
- progress.advance(1)
66
- end
67
-
68
- connections.enqueue(nil)
69
- end
70
-
71
- # ensure
72
- # result = profile.stop
73
- # printer = RubyProf::FlatPrinter.new(result)
74
- # printer.print(STDOUT, min_percent: 0.5)
75
- #
76
- # printer = RubyProf::GraphPrinter.new(result)
77
- # printer.print(STDOUT, min_percent: 0.5)
78
- end
79
- end
80
-
81
- Command.call