webtube 1.0.0 → 1.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.
@@ -3,20 +3,24 @@ require 'thread'
3
3
  require 'webtube'
4
4
 
5
5
  class Webtube
6
- # A tracker for live [[Webtube]] instances and their threads. This allows a
7
- # shutdowning WEBrick to gently close the pending WebSockets.
6
+ # A tracker for live [[Webtube]] instances and their threads.
7
+ # This allows a shutdowning WEBrick to gently close the
8
+ # pending WebSockets.
8
9
  class Vital_Statistics
9
- # A [[ThreadGroup]] into which the Webtube threads can add themselves.
10
- # Note that [[Vital_Statistics]] does not forcefully move them (nor could
11
- # it -- a Webtube does not get a thread before [[Webtube#run]] is called,
12
- # which is normally _after_ [[Vital_Statistics#birth]] gets called).
10
+ # A [[ThreadGroup]] into which the Webtube threads can add
11
+ # themselves. Note that [[Vital_Statistics]] does not
12
+ # forcefully move them (nor could it -- a Webtube does not
13
+ # get a thread before [[Webtube#run]] is called, which is
14
+ # normally _after_ [[Vital_Statistics#birth]] gets called).
13
15
  #
14
- # When Webtube is being integrated with WEBrick by [[webtube/webrick.rb]],
15
- # assigning Webtube-specific threads into this group will cause WEBrick's
16
- # standard shutdown procedure to not try to [[Thread#join]] them as it does
17
- # to ordinary WEBrick threads. Instead, the integration code will call
18
- # [[Vital_Statistics#close_all]], to request that each Webtube close
19
- # itself, and then join the threads from [[Vital_Statistics#thread_group]].
16
+ # When Webtube is being integrated with WEBrick by
17
+ # [[webtube/webrick.rb]], assigning Webtube-specific threads
18
+ # into this group will cause WEBrick's standard shutdown
19
+ # procedure to not try to [[Thread#join]] them as it does to
20
+ # ordinary WEBrick threads. Instead, the integration code
21
+ # will call [[Vital_Statistics#close_all]], to request that
22
+ # each Webtube close itself, and then join the threads from
23
+ # [[Vital_Statistics#thread_group]].
20
24
  attr_reader :thread_group
21
25
 
22
26
  def initialize logger
@@ -42,24 +46,27 @@ class Webtube
42
46
  return
43
47
  end
44
48
 
45
- # Construct a list of all the currently living [[Webtube]] instances. Note
46
- # that while the operation is atomic, the Webtube infrastructure is
47
- # inherently multithreaded, so the list can get slightly stale immediately
48
- # and should, in most contexts, be considered informative.
49
+ # Construct a list of all the currently living [[Webtube]]
50
+ # instances. Note that while the operation is atomic, the
51
+ # Webtube infrastructure is inherently multithreaded, so the
52
+ # list can get slightly stale immediately and should, in
53
+ # most contexts, be considered informative.
49
54
  def to_a
50
55
  return @mutex.synchronize{@webtubes.to_a}
51
56
  end
52
57
 
53
- # The default status code in a shutdown situation is 1001 'going away'.
58
+ # The default status code in a shutdown situation is 1001
59
+ # 'going away'.
54
60
  def close_all status_code = 1001, explanation = ""
55
- # Note that we're only mutexing off extracting the content of
56
- # [[@webtubes]] (see [[to_a]]). We can't mutex the whole block, for as
57
- # the webtubes will be closing, they'll want to notify us about it, and
58
- # that is also mutexed.
61
+ # Note that we're only mutexing off extracting the content
62
+ # of [[@webtubes]] (see [[to_a]]). We can't mutex the
63
+ # whole block, for as the webtubes will be closing,
64
+ # they'll want to notify us about it, and that is also
65
+ # mutexed.
59
66
  #
60
- # This is not as bad as it may sound, for the webserver shouldn't be
61
- # accepting new connections anymore anyway by the time it'll start
62
- # closing the old ones.
67
+ # This is not as bad as it may sound, for the webserver
68
+ # shouldn't be accepting new connections anymore anyway by
69
+ # the time it'll start closing the old ones.
63
70
  self.to_a.each do |webtube|
64
71
  begin
65
72
  webtube.close status_code, explanation
@@ -1,6 +1,7 @@
1
- # webtube/webrick.rb -- WEBrick integration for Webtube, an implementation of
2
- # the WebSocket protocol
1
+ # webtube/webrick.rb -- WEBrick integration for Webtube, an
2
+ # implementation of the WebSocket protocol
3
3
 
4
+ require 'openssl'
4
5
  require 'webrick'
5
6
  require 'webrick/httprequest'
6
7
  require 'webrick/httpserver'
@@ -21,8 +22,9 @@ module WEBrick
21
22
  end
22
23
 
23
24
  class HTTPServer
24
- # Attach a [[Webtube::Vital_Statistics]] to new [[WEBrick::HTTPServer]]
25
- # instances so that the live webtubes could be closed upon shutdown
25
+ # Attach a [[Webtube::Vital_Statistics]] to new
26
+ # [[WEBrick::HTTPServer]] instances so that the live
27
+ # webtubes could be closed upon shutdown
26
28
 
27
29
  alias orig_initialize_before_webtube_integration initialize
28
30
  def initialize config = {}, default = Config::HTTP
@@ -35,106 +37,123 @@ module WEBrick
35
37
  result = @webtubes
36
38
  # Usually, this should be it.
37
39
  if result.nil? then # ... but ...
38
- # Well, it would seem that our extended constructor was not called.
39
- # How could this have happened?
40
+ # Well, it would seem that our extended constructor was
41
+ # not called. How could this have happened?
40
42
  result = @webtubes = Webtube::Vital_Statistics.new
41
- @logger.warn "@webtubes has not been set up before accessing it. I " +
42
- "have attempted to correct this ex post facto, but doing it now " +
43
- "is a race condition, and I may have lost track of some webtubes " +
44
- "as a result. The next time, please load webtube/webrick.rb " +
45
- "/before/ instantiating your WEBrick::Server."
43
+ @logger.warn "@webtubes (in a WEBrick::HTTPServer) " +
44
+ "has not been set up before accessing it. I " +
45
+ "have attempted to correct this ex post facto, " +
46
+ "but doing it now is a race condition, and I may " +
47
+ "have lost track of some webtubes as a result. " +
48
+ "The next time, please load webtube/webrick.rb " +
49
+ "/before/ instantiating your WEBrick::HTTPServer."
46
50
  end
47
51
  return result
48
52
  end
49
53
 
50
54
  alias orig_shutdown_before_webtube_integration shutdown
51
55
  def shutdown
52
- # We'll need to call the original shutdown code first, for we want to
53
- # stop accepting new Webtube connections before 'close all Webtube
54
- # connections' will have a proper, thread-safe meaning.
56
+ # We'll need to call the original shutdown code first, for
57
+ # we want to stop accepting new Webtube connections before
58
+ # 'close all Webtube connections' will have a proper,
59
+ # thread-safe meaning.
55
60
  orig_shutdown_before_webtube_integration
56
61
  webtubes.close_all
57
62
  webtubes.thread_group.list.each &:join
58
63
  return
59
64
  end
60
65
 
61
- # Given a [[request]] and a [[response]] object, as prepared by a
62
- # [[WEBrick::HTTPServer]] for processing in a portlet, attempt to accept
63
- # the client's request to establish a WebSocket connection. The
64
- # [[request]] must actually contain such a request; see
66
+ # Given a [[request]] and a [[response]] object, as prepared
67
+ # by a [[WEBrick::HTTPServer]] for processing in a portlet,
68
+ # attempt to accept the client's request to establish a
69
+ # WebSocket connection. The [[request]] must actually
70
+ # contain such a request; see
65
71
  # [[websocket_upgrade_request?]].
66
72
  #
67
- # The attempt will fail in the theoretical case the client and the server
68
- # can't agree on the protocol version to use. In such a case,
69
- # [[accept_webtube]] will prepare a 426 'Upgrade required' response,
70
- # explaining in plain text what the problem is and advertising, using the
71
- # [[Sec-WebSocket-Version]] header field, the protocol version
72
- # (specifically, 13) it is prepared to speak. When this happens, the
73
- # WebSocket session will never be set up and no [[listener]] events will be
74
- # called.
73
+ # The attempt will fail in the theoretical case the client
74
+ # and the server can't agree on the protocol version to use.
75
+ # In such a case, [[accept_webtube]] will prepare a 426
76
+ # 'Upgrade required' response, explaining in plain text what
77
+ # the problem is and advertising, using the
78
+ # [[Sec-WebSocket-Version]] header field, the protocol
79
+ # version (specifically, 13) it is prepared to speak. When
80
+ # this happens, the WebSocket session will never be set up
81
+ # and no [[listener]] events will be called.
75
82
  #
76
- # Note that [[accept_webtube]] will manipulate [[response]] and return
77
- # immediately. The actual WebSocket session will begin once WEBrick
78
- # attempts to deliver the [[response]], and will be marked by the newly
79
- # constructed [[Webtube]] instance delivering an [[onopen]] event to
80
- # [[listener]].
83
+ # Note that [[accept_webtube]] will manipulate [[response]]
84
+ # and return immediately. The actual WebSocket session will
85
+ # begin once WEBrick attempts to deliver the [[response]],
86
+ # and will be marked by the newly constructed [[Webtube]]
87
+ # instance delivering an [[onopen]] event to [[listener]].
81
88
  #
82
- # Also note that the loop to process incoming WebSocket frames will hog the
83
- # whole thread; in order to deliver asynchronous messages over the
84
- # WebSocket, [[Webtube#send_message]] needs to be called from another
85
- # thread. (For synchronous messages, it can safely be called from the
86
- # handlers inside [[listener]].)
89
+ # Also note that the loop to process incoming WebSocket
90
+ # frames will hog the whole thread; in order to deliver
91
+ # asynchronous messages over the WebSocket,
92
+ # [[Webtube#send_message]] needs to be called from another
93
+ # thread. (For synchronous messages, it can safely be
94
+ # called from the handlers inside [[listener]].)
87
95
  #
88
- # See [[Webtube#run]] for a list of the supported methods for the
89
- # [[listener]].
96
+ # See [[Webtube#run]] for a list of the supported methods
97
+ # for the [[listener]].
90
98
  def accept_webtube request, response, listener,
91
99
  session: nil, context: nil
92
100
  # Check that the client speaks our version
93
- unless (request['Sec-WebSocket-Version'] || '').split(/\s*,\s*/).
101
+ unless (request['Sec-WebSocket-Version'] || '').
102
+ strip.split(/\s*,\s*/).
94
103
  include? '13' then
95
104
  @logger.error "Sec-WebSocket-Version mismatch"
96
- response.status, response.reason_phrase = '426', 'Upgrade required'
105
+ response.status, response.reason_phrase =
106
+ '426', 'Upgrade required'
97
107
  response['Content-type'] = 'text/plain'
98
108
  response['Sec-WebSocket-Version'] = '13'
99
109
  # advertise the version we speak
100
- response.body = "This WebSocket server only speaks version 13 of the " +
101
- "protocol, as specified by RFC 6455.\n"
110
+ response.body = "This WebSocket server only speaks " +
111
+ "version 13 of the protocol, as specified by " +
112
+ "RFC 6455.\n"
102
113
  else
103
- response.status, response.reason_phrase = '101', 'Hello WebSocket'
114
+ response.status, response.reason_phrase =
115
+ '101', 'Hello WebSocket'
104
116
  response['Upgrade'] = 'websocket'
105
- response['Sec-WebSocket-Accept'] = Digest::SHA1.base64digest(
106
- request['Sec-WebSocket-Key'] +
107
- '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')
117
+ response['Sec-WebSocket-Accept'] =
118
+ OpenSSL::Digest::SHA1.base64digest(
119
+ request['Sec-WebSocket-Key'] +
120
+ '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')
108
121
  response['Sec-WebSocket-Version'] = '13'
109
122
  response.keep_alive = false
110
- # so that WEBrick will close the TCP socket when we're done
123
+ # so that WEBrick will close the TCP socket when
124
+ # we're done
111
125
  vital_statistics = self.webtubes
112
126
  (class << response; self; end).instance_eval do
113
- # We'll need to deliver the [[Connection: Upgrade]] header;
114
- # unfortunately, HTTPResponse#setup_header would munge it if we set
115
- # this header field in the ordinary way. Accordingly, we'll have to
116
- # override the method.
127
+ # We'll need to deliver the [[Connection: Upgrade]]
128
+ # header; unfortunately, HTTPResponse#setup_header
129
+ # would munge it if we set this header field in the
130
+ # ordinary way. Accordingly, we'll have to override
131
+ # the method.
117
132
  define_method :setup_header do ||
118
133
  super()
119
134
  @header['connection'] = 'Upgrade'
120
135
  return
121
136
  end
122
137
 
123
- # Replace [[response.send_body]] with the WS engine. WEBrick will
124
- # call it automatically after sending the response header.
138
+ # Replace [[response.send_body]] with the WS engine.
139
+ # WEBrick will call it automatically after sending the
140
+ # response header.
125
141
  #
126
- # Also notify the server's attached [[Webtube::Vital_Statistics]]
127
- # instance so that server shutdown could also close all pending
142
+ # Also notify the server's attached
143
+ # [[Webtube::Vital_Statistics]] instance so that
144
+ # server shutdown could also close all pending
128
145
  # Webtubes.
129
146
  define_method :send_body do |socket|
130
- webtube = Webtube.new(socket, true, close_socket: false)
147
+ webtube = Webtube.new socket, true,
148
+ close_socket: false
131
149
  begin
132
150
  vital_statistics.birth webtube
133
151
  webtube.header = request
134
152
  webtube.session = session
135
153
  webtube.context = context
136
- # Reassign us from the WEBrick's thread group to the one
137
- # maintained by [[Webtube::Vital_Statistics]].
154
+ # Reassign us from the WEBrick's thread group to
155
+ # the one maintained by
156
+ # [[Webtube::Vital_Statistics]].
138
157
  vital_statistics.thread_group.add Thread.current
139
158
  # And now, run!
140
159
  webtube.run listener
@@ -171,7 +190,8 @@ module WEBrick
171
190
  # advertise the version we speak
172
191
  # prepare a human-readable content
173
192
  response['Content-type'] = 'text/plain'
174
- response.body = "426\n\nThis is a WebSocket-only resource."
193
+ response.body =
194
+ "426\n\nThis is a WebSocket-only resource.\n"
175
195
  end
176
196
  return
177
197
  end
@@ -1,9 +1,9 @@
1
1
  #! /usr/bin/ruby
2
2
 
3
- # A sample WEBrick server using the Webtube API. It listens on port 8888 and
4
- # provides two services: [[/diag]], which logs all the events from
5
- # [[Webtube#run]] and remains silent towards the client (although note that
6
- # the Webtube library pongs the pings), and [[/echo]], which echos.
3
+ # A sample WEBrick server using the Webtube API. It listens
4
+ # on port 8888 and provides two services: [[/diag]], which
5
+ # logs all the events from [[Webtube#run]] and remains silent
6
+ # towards the client, and [[/echo]], which echos.
7
7
 
8
8
  require 'webrick'
9
9
  require 'webtube/webrick'
@@ -1,17 +1,17 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'webtube'
3
- s.version = '1.0.0'
4
- s.date = '2014-10-19'
3
+ s.version = '1.1.0'
4
+ s.date = '2018-04-26'
5
5
  s.homepage = 'https://github.com/digwuren/webtube'
6
- s.summary = 'A Ruby implementation of the [[WebSocket]] protocol'
6
+ s.summary = 'A Ruby implementation of the WebSocket protocol'
7
7
  s.author = 'Andres Soolo'
8
8
  s.email = 'dig@mirky.net'
9
9
  s.files = File.read('Manifest.txt').split(/\n/)
10
10
  s.executables << 'wsc'
11
- s.license = 'GPL-3'
11
+ s.license = 'GPL-3.0'
12
12
  s.description = <<EOD
13
- Webtube is an implementation of the [[WebSocket]] protocol for [[Ruby]]. Some
14
- integration with the [[WEBrick]] server is also included.
13
+ Webtube is an implementation of the WebSocket protocol for Ruby.
14
+ Some integration with the WEBrick server is also included.
15
15
  EOD
16
16
  s.has_rdoc = false
17
17
  end
metadata CHANGED
@@ -1,18 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: webtube
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andres Soolo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-19 00:00:00.000000000 Z
11
+ date: 2018-04-26 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |
14
- Webtube is an implementation of the [[WebSocket]] protocol for [[Ruby]]. Some
15
- integration with the [[WEBrick]] server is also included.
14
+ Webtube is an implementation of the WebSocket protocol for Ruby.
15
+ Some integration with the WEBrick server is also included.
16
16
  email: dig@mirky.net
17
17
  executables:
18
18
  - wsc
@@ -30,7 +30,7 @@ files:
30
30
  - webtube.gemspec
31
31
  homepage: https://github.com/digwuren/webtube
32
32
  licenses:
33
- - GPL-3
33
+ - GPL-3.0
34
34
  metadata: {}
35
35
  post_install_message:
36
36
  rdoc_options: []
@@ -38,18 +38,18 @@ require_paths:
38
38
  - lib
39
39
  required_ruby_version: !ruby/object:Gem::Requirement
40
40
  requirements:
41
- - - '>='
41
+ - - ">="
42
42
  - !ruby/object:Gem::Version
43
43
  version: '0'
44
44
  required_rubygems_version: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - '>='
46
+ - - ">="
47
47
  - !ruby/object:Gem::Version
48
48
  version: '0'
49
49
  requirements: []
50
50
  rubyforge_project:
51
- rubygems_version: 2.0.14
51
+ rubygems_version: 2.5.2.1
52
52
  signing_key:
53
53
  specification_version: 4
54
- summary: A Ruby implementation of the [[WebSocket]] protocol
54
+ summary: A Ruby implementation of the WebSocket protocol
55
55
  test_files: []