webtube 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []