websocket-server 1.0.1-java → 1.1.2-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,7 +6,7 @@
6
6
 
7
7
  # =begin
8
8
  #
9
- # Copyright Nels Nelson 2016-2022 but freely usable (see license)
9
+ # Copyright Nels Nelson 2016-2024 but freely usable (see license)
10
10
  #
11
11
  # =end
12
12
 
@@ -23,6 +23,7 @@ module WebSocket
23
23
  # server pipeline.
24
24
  class IdleHandler < WebSocket::IdleStateUserEventHandler
25
25
  def initialize
26
+ # Include additional subclass initialization here.
26
27
  super()
27
28
  end
28
29
 
@@ -6,7 +6,7 @@
6
6
 
7
7
  # =begin
8
8
  #
9
- # Copyright Nels Nelson 2016-2022 but freely usable (see license)
9
+ # Copyright Nels Nelson 2016-2024 but freely usable (see license)
10
10
  #
11
11
  # =end
12
12
 
@@ -6,7 +6,7 @@
6
6
 
7
7
  # =begin
8
8
  #
9
- # Copyright Nels Nelson 2016-2022 but freely usable (see license)
9
+ # Copyright Nels Nelson 2016-2024 but freely usable (see license)
10
10
  #
11
11
  # =end
12
12
 
@@ -63,36 +63,24 @@ module WebSocket
63
63
  # rubocop: disable Metrics/AbcSize
64
64
  # rubocop: disable Metrics/MethodLength
65
65
  def run(params = {})
66
- options.merge!(params)
66
+ @options.merge!(params)
67
67
  channel = bootstrap.bind(port).sync().channel()
68
68
  channel_group.add(channel)
69
69
  ::WebSocket::ShutdownHook.new(self)
70
70
  log.info "Listening on #{channel.local_address}"
71
71
  channel.closeFuture().sync()
72
72
  rescue java.net.BindException => e
73
- raise "Bind error: #{e.message}: #{options[:host]}:#{port}"
73
+ raise "Bind error: #{e.message}: #{@options[:host]}:#{port}"
74
74
  rescue java.net.SocketException => e
75
- raise "Socket error: #{e.message}: #{options[:host]}:#{port}"
75
+ raise "Socket error: #{e.message}: #{@options[:host]}:#{port}"
76
76
  ensure
77
77
  stop
78
78
  end
79
79
  # rubocop: enable Metrics/AbcSize
80
80
  # rubocop: enable Metrics/MethodLength
81
81
 
82
- IntegerPattern = /^\d+$/.freeze
83
-
84
- def valid_port?(val)
85
- IntegerPattern.match?(val.to_s) && val.positive? && val < 65_536
86
- end
87
-
88
- def given_port
89
- value = (options[:ssl] ? options[:ssl_port] : options[:port]).to_i
90
- raise 'Given port parameter is invalid' unless valid_port?(value)
91
- value
92
- end
93
-
94
82
  def port
95
- @port ||= given_port
83
+ @port ||= (@options[:ssl] ? @options[:ssl_port] : @options[:port]).to_i
96
84
  end
97
85
 
98
86
  def shutdown
@@ -109,8 +97,8 @@ module WebSocket
109
97
  channel_initializer.handlers << handler
110
98
  end
111
99
 
112
- def add_listener(listener)
113
- channel_initializer.add_listener(listener)
100
+ def add_listener(*listener)
101
+ channel_initializer.add_listener(*listener)
114
102
  end
115
103
 
116
104
  # def all_exist?(*files)
@@ -6,36 +6,14 @@
6
6
 
7
7
  # =begin
8
8
  #
9
- # Copyright Nels Nelson 2016-2022 but freely usable (see license)
9
+ # Copyright Nels Nelson 2016-2024 but freely usable (see license)
10
10
  #
11
11
  # =end
12
12
 
13
- require 'java'
14
-
15
13
  # The WebSocket module
16
14
  module WebSocket
17
15
  # The Listenable module
18
16
  module Listenable
19
- def listeners
20
- @listeners ||= java.util.concurrent.CopyOnWriteArrayList.new
21
- end
22
-
23
- def add_listener(listener)
24
- listeners << listener
25
- end
26
-
27
- def remove_listener(listener)
28
- listeners.delete(listener)
29
- end
30
-
31
- def notify(message, *args)
32
- return if listeners.empty?
33
- log.trace "Notifying listeners (#{listeners}) of message: #{message}"
34
- listeners.each do |listener|
35
- listener.send(message.to_sym, *args) if listener.respond_to?(message.to_sym)
36
- end
37
- end
17
+ include ::Server::Listenable
38
18
  end
39
- # module Listenable
40
19
  end
41
- # module WebSocket
@@ -6,7 +6,7 @@
6
6
 
7
7
  # =begin
8
8
  #
9
- # Copyright Nels Nelson 2016-2022 but freely usable (see license)
9
+ # Copyright Nels Nelson 2016-2024 but freely usable (see license)
10
10
  #
11
11
  # =end
12
12
 
@@ -6,7 +6,7 @@
6
6
 
7
7
  # =begin
8
8
  #
9
- # Copyright Nels Nelson 2016-2022 but freely usable (see license)
9
+ # Copyright Nels Nelson 2016-2024 but freely usable (see license)
10
10
  #
11
11
  # =end
12
12
 
@@ -26,13 +26,13 @@ module WebSocket
26
26
 
27
27
  # The ResponseHelpers helpers
28
28
  module ResponseHelpers
29
- NonSpacesBeforeEOLPattern = %r{([^\s]+)$}.freeze
29
+ NON_SPACES_BEFORE_EOL_PATTERN = %r{([^\s]+)$}
30
30
 
31
31
  def index_listing(path)
32
32
  results = `ls -la #{path}`.strip.split("\n")
33
33
  results.shift
34
34
  index = results.collect do |s|
35
- s.gsub(NonSpacesBeforeEOLPattern) do |resource_name|
35
+ s.gsub(NON_SPACES_BEFORE_EOL_PATTERN) do |resource_name|
36
36
  %(<a href="#{resource_name}">#{resource_name}</a>)
37
37
  end
38
38
  end.join '<br />'
@@ -6,12 +6,10 @@
6
6
 
7
7
  # =begin
8
8
  #
9
- # Copyright Nels Nelson 2016-2022 but freely usable (see license)
9
+ # Copyright Nels Nelson 2016-2024 but freely usable (see license)
10
10
  #
11
11
  # =end
12
12
 
13
- require 'java'
14
- require 'netty'
15
13
  require 'tcp-server'
16
14
 
17
15
  require_relative 'instance_methods'
@@ -6,12 +6,11 @@
6
6
 
7
7
  # =begin
8
8
  #
9
- # Copyright Nels Nelson 2016-2022 but freely usable (see license)
9
+ # Copyright Nels Nelson 2016-2024 but freely usable (see license)
10
10
  #
11
11
  # =end
12
12
 
13
13
  require 'java'
14
- require 'netty'
15
14
 
16
15
  # The WebSocket module
17
16
  module WebSocket
@@ -6,7 +6,7 @@
6
6
 
7
7
  # =begin
8
8
  #
9
- # Copyright Nels Nelson 2016-2022 but freely usable (see license)
9
+ # Copyright Nels Nelson 2016-2024 but freely usable (see license)
10
10
  #
11
11
  # =end
12
12
 
@@ -22,6 +22,7 @@ module WebSocket
22
22
  # cipher configuration and pipeline handling of SSL handshakes.
23
23
  class SslCipherInspector < SimpleChannelInboundHandler
24
24
  def initialize
25
+ # Include additional subclass initialization here.
25
26
  super()
26
27
  end
27
28
 
@@ -6,7 +6,7 @@
6
6
 
7
7
  # =begin
8
8
  #
9
- # Copyright Nels Nelson 2016-2022 but freely usable (see license)
9
+ # Copyright Nels Nelson 2016-2024 but freely usable (see license)
10
10
  #
11
11
  # =end
12
12
 
@@ -6,7 +6,7 @@
6
6
 
7
7
  # =begin
8
8
  #
9
- # Copyright Nels Nelson 2016-2022 but freely usable (see license)
9
+ # Copyright Nels Nelson 2016-2024 but freely usable (see license)
10
10
  #
11
11
  # =end
12
12
 
@@ -6,41 +6,37 @@
6
6
 
7
7
  # =begin
8
8
  #
9
- # Copyright Nels Nelson 2016-2022 but freely usable (see license)
9
+ # Copyright Nels Nelson 2016-2024 but freely usable (see license)
10
10
  #
11
11
  # =end
12
12
 
13
- require 'java'
14
- require 'netty'
15
-
16
13
  require_relative 'encoding'
17
14
 
18
15
  # The WebSocket module
19
16
  module WebSocket
20
17
  # The ValidationHelpers module
21
18
  module ValidationHelpers
22
- FileSeparatorDotPattern = %r{#{File::SEPARATOR}\.}.freeze
23
- DotFileSeparatorPattern = %r{\.#{File::SEPARATOR}}.freeze
19
+ FILE_SEPARATOR_DOT_PATTERN = %r{#{File::SEPARATOR}\.}
20
+ DOT_FILE_SEPARATOR_PATTERN = %r{\.#{File::SEPARATOR}}
21
+ QUERY_STRING_PATTERN = %r{\?.*}
22
+ FORWARD_SLASH_PATTERN = %r{/}
24
23
 
25
24
  # Simplistic dumb security check.
26
25
  # Something more serious is required in a production environment.
27
26
  def insecure_uri?(uri)
28
- FileSeparatorDotPattern.match?(uri) ||
29
- DotFileSeparatorPattern.match?(uri) ||
27
+ FILE_SEPARATOR_DOT_PATTERN.match?(uri) ||
28
+ DOT_FILE_SEPARATOR_PATTERN.match?(uri) ||
30
29
  uri.start_with?('.') ||
31
30
  uri.end_with?('.') ||
32
31
  options[:insecure_uri_pattern].match?(uri)
33
32
  end
34
33
 
35
- QueryStringPattern = %r{\?.*}.freeze
36
- ForwardSlashPattern = %r{/}.freeze
37
-
38
34
  def sanitize_uri(uri)
39
35
  # Decode the path.
40
- uri = CGI.unescape(uri.gsub(QueryStringPattern, ''), WebSocket::Encoding.name)
36
+ uri = CGI.unescape(uri.gsub(QUERY_STRING_PATTERN, ''), WebSocket::Encoding.name)
41
37
  return nil if uri.empty? || !uri.start_with?('/')
42
38
  # Convert file separators.
43
- uri = uri.gsub(ForwardSlashPattern, File::SEPARATOR)
39
+ uri = uri.gsub(FORWARD_SLASH_PATTERN, File::SEPARATOR)
44
40
  return nil if insecure_uri?(uri)
45
41
  # Convert to absolute path.
46
42
  File.join(options[:web_root], uri)
@@ -6,11 +6,11 @@
6
6
 
7
7
  # =begin
8
8
  #
9
- # Copyright Nels Nelson 2016-2022 but freely usable (see license)
9
+ # Copyright Nels Nelson 2016-2024 but freely usable (see license)
10
10
  #
11
11
  # =end
12
12
 
13
13
  # The WebSocket module
14
14
  module WebSocket
15
- VERSION = '1.0.1'.freeze
15
+ VERSION = '1.1.2'.freeze
16
16
  end
@@ -6,7 +6,7 @@
6
6
 
7
7
  # =begin
8
8
  #
9
- # Copyright Nels Nelson 2016-2022 but freely usable (see license)
9
+ # Copyright Nels Nelson 2016-2024 but freely usable (see license)
10
10
  #
11
11
  # =end
12
12
 
@@ -8,16 +8,16 @@
8
8
 
9
9
  # =begin
10
10
  #
11
- # Copyright Nels Nelson 2016-2022 but freely usable (see license)
11
+ # Copyright Nels Nelson 2016-2024 but freely usable (see license)
12
12
  #
13
13
  # =end
14
14
 
15
+ require 'java'
15
16
  require 'optparse'
16
17
 
17
- require 'java'
18
18
  require 'netty'
19
19
 
20
- require 'log'
20
+ require_relative 'logging'
21
21
 
22
22
  # Simple websocket client ported from the example from Netty-io.
23
23
 
@@ -260,23 +260,32 @@ module WebSocket
260
260
  @listeners ||= java.util.concurrent.CopyOnWriteArrayList.new
261
261
  end
262
262
 
263
- def add_listener(listener)
264
- listeners << listener
263
+ def add_listener(*listener)
264
+ listeners.addAll(listener)
265
+ ensure
266
+ log.trace "Listeners: #{listeners}"
267
+ end
268
+
269
+ def remove_listener(*listener)
270
+ listeners.removeAll(listener)
265
271
  end
266
272
 
267
- def remove_listener(listener)
268
- listeners.delete(listener)
273
+ def replace_listeners(*listener)
274
+ listeners.clear
275
+ add_listener(*listener)
269
276
  end
270
277
 
271
- def notify(message, *args)
272
- return if listeners.empty?
273
- log.trace "Notifying listeners (#{listeners}) of message: #{message}"
278
+ def notify(event, *args)
274
279
  listeners.each do |listener|
275
- listener.send(message.to_sym, *args) if listener.respond_to?(message.to_sym)
280
+ next unless listener.respond_to?(event.to_sym)
281
+ log.trace "Notifying listener #{listener} of event: #{event}"
282
+ listener.send(event.to_sym, *args)
276
283
  end
277
284
  end
278
285
  end
286
+ # module Listenable
279
287
  end
288
+ # module WebSocket
280
289
 
281
290
  # The WebSocket module
282
291
  module WebSocket
@@ -326,7 +335,6 @@ module WebSocket
326
335
  end
327
336
 
328
337
  def exceptionCaught(ctx, cause)
329
- log.info "##{__method__} wtf1"
330
338
  cause.printStackTrace()
331
339
  @handshake_future.setFailure(cause) unless @handshake_future.isDone()
332
340
  ctx.close()
@@ -424,10 +432,8 @@ module WebSocket
424
432
  session
425
433
  end
426
434
 
427
- IdentiferTemplate = '#<%<class>s:0x%<id>s>'.freeze
428
-
429
435
  def to_s
430
- format(IdentiferTemplate, class: self.class.name, id: object_id.to_s(16))
436
+ format('#<%<class>s:0x%<id>s>', class: self.class.name, id: object_id.to_s(16))
431
437
  end
432
438
  alias inspect to_s
433
439
  end
@@ -436,31 +442,69 @@ end
436
442
 
437
443
  # The WebSocket module
438
444
  module WebSocket
439
- # rubocop: disable Metrics/AbcSize
440
- # rubocop: disable Metrics/MethodLength
441
- def parse_arguments(options = ::WebSocket.client_config.dup)
442
- parser = OptionParser.new
443
- parser.banner = "Usage: #{File.basename($PROGRAM_NAME)} [options]"
444
- parser.separator ''
445
- parser.separator 'Options:'
446
- parser.on_head('-u', '--uri=<uri>', 'Fully qualified connection string') do |v|
447
- options[:uri] = java.net.URI.new(v)
448
- end
449
- parser.on_tail('-v', '--verbose', 'Increase verbosity') { options[:log_level] -= 1 }
450
- parser.on_tail('-?', '--help', 'Show this message') do
451
- puts parser
452
- exit
453
- end
454
- parser.on_tail('--version', 'Show version') do
455
- puts "#{$PROGRAM_NAME} version #{::WebSocket.version}"
456
- exit
457
- end
458
- parser.parse!
459
- options
445
+ # The ArgumentsParser class
446
+ class ArgumentsParser
447
+ attr_reader :parser, :options
448
+
449
+ def initialize(parser = OptionParser.new, options = ::WebSocket.client_config.dup)
450
+ @parser = parser
451
+ @options = options
452
+ @flags = %i[banner uri log_level help version]
453
+ @flags.each { |method_name| method(method_name)&.call if respond_to?(method_name) }
454
+ end
455
+
456
+ def banner
457
+ @parser.banner = "Usage: #{File.basename($PROGRAM_NAME)} [options]"
458
+ @parser.separator ''
459
+ @parser.separator 'Options:'
460
+ end
461
+
462
+ def uri
463
+ @parser.on_head('-u', '--uri=<uri>', 'Fully qualified connection string') do |v|
464
+ @options[:uri] = java.net.URI.new(v)
465
+ end
466
+ end
467
+
468
+ def log_level
469
+ @parser.on_tail('-v', '--verbose', 'Increase verbosity') do
470
+ @options[:log_level] ||= 0
471
+ @options[:log_level] -= 1
472
+ end
473
+ end
474
+
475
+ def help
476
+ @parser.on_tail('-?', '--help', 'Show this message') do
477
+ puts @parser
478
+ exit
479
+ end
480
+ end
481
+
482
+ def version
483
+ @parser.on_tail('--version', 'Show version') do
484
+ puts "#{File.basename($PROGRAM_NAME)} version #{::WebSocket::VERSION}"
485
+ exit
486
+ end
487
+ end
460
488
  end
461
- # rubocop: enable Metrics/AbcSize
462
- # rubocop: enable Metrics/MethodLength
489
+ # class ArgumentsParser
490
+
491
+ def parse_arguments(arguments_parser = ArgumentsParser.new)
492
+ arguments_parser.parser.parse!(ARGV)
493
+ arguments_parser.parse_positional_arguments!
494
+ arguments_parser.options
495
+ rescue OptionParser::InvalidArgument, OptionParser::InvalidOption,
496
+ OptionParser::MissingArgument, OptionParser::NeedlessArgument => e
497
+ puts e.message
498
+ puts parser
499
+ exit
500
+ rescue OptionParser::AmbiguousOption => e
501
+ abort e.message
502
+ end
503
+ end
504
+ # module WebSocket
463
505
 
506
+ # The WebSocket module
507
+ module WebSocket
464
508
  def main(args = parse_arguments)
465
509
  Logging.log_level = args[:log_level]
466
510
  ::WebSocket::Client.new(args)
@@ -475,4 +519,4 @@ module WebSocket
475
519
  end
476
520
  # module WebSocket
477
521
 
478
- Object.new.extend(::WebSocket).main if $PROGRAM_NAME == __FILE__
522
+ Object.new.extend(WebSocket).main if $PROGRAM_NAME == __FILE__
@@ -8,42 +8,47 @@
8
8
 
9
9
  # =begin
10
10
  #
11
- # Copyright Nels Nelson 2016-2022 but freely usable (see license)
11
+ # Copyright Nels Nelson 2016-2024 but freely usable (see license)
12
12
  #
13
13
  # =end
14
14
 
15
- require_relative 'log'
15
+ require 'java'
16
+
17
+ require_relative 'logging'
16
18
  require_relative 'websocket/arguments_parser'
17
19
  require_relative 'websocket/server'
18
20
  require_relative 'websocket/telnet_proxy'
19
21
 
20
22
  # The WebSocket module
21
23
  module WebSocket
22
- EchoServerMessageTemplate = "%<message>s\n".freeze
23
- InterruptTemplate = "\r%<class>s".freeze
24
-
25
24
  def echo_server(options)
26
- WebSocket::Server.new(options: options) do |_ctx, msg|
27
- format(EchoServerMessageTemplate, message: msg.upcase)
25
+ ::WebSocket::Server.new(options) do |_ctx, msg|
26
+ format("%<message>s\n", message: msg.upcase)
28
27
  end.run
29
28
  end
30
29
 
31
30
  def telnet_proxy(options)
32
- handler = WebSocket::TelnetProxy.new(options[:telnet_proxy_host], options[:telnet_proxy_port])
33
- WebSocket::Server.new(handler: handler, options: options).run
31
+ handler = ::WebSocket::TelnetProxy.new(options[:telnet_proxy_host], options[:telnet_proxy_port])
32
+ ::WebSocket::Server.new(options, handler).run
34
33
  end
35
34
 
35
+ # rubocop: disable Metrics/AbcSize
36
+ # rubocop: disable Metrics/MethodLength
36
37
  def main(args = parse_arguments)
37
38
  Logging.log_level = args[:log_level]
38
39
  return telnet_proxy(args) unless args[:telnet_proxy_host].nil?
39
40
  echo_server(args)
40
41
  rescue Interrupt => e
41
- warn format(InterruptTemplate, class: e.class)
42
+ warn format("\r%<class>s", class: e.class)
42
43
  exit
43
44
  rescue StandardError => e
44
- WebSocket::Server.log.fatal(e.message)
45
+ puts Logging.log_level
46
+ ::WebSocket::Server.log.fatal(e.message)
47
+ e.backtrace.each { |t| WebSocket::Server.log.debug t }
45
48
  abort
46
49
  end
50
+ # rubocop: enable Metrics/AbcSize
51
+ # rubocop: enable Metrics/MethodLength
47
52
  end
48
53
  # module WebSocket
49
54
 
metadata CHANGED
@@ -1,71 +1,30 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: websocket-server
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.2
5
5
  platform: java
6
6
  authors:
7
7
  - Nels Nelson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-06-26 00:00:00.000000000 Z
11
+ date: 2024-04-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: 1.0.5
18
+ version: 1.1.3
19
19
  name: tcp-server
20
- prerelease: false
21
20
  type: :runtime
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: 1.0.5
27
- - !ruby/object:Gem::Dependency
28
- requirement: !ruby/object:Gem::Requirement
29
- requirements:
30
- - - "~>"
31
- - !ruby/object:Gem::Version
32
- version: 12.3.0
33
- name: rake
34
- prerelease: false
35
- type: :development
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: 12.3.0
41
- - !ruby/object:Gem::Dependency
42
- requirement: !ruby/object:Gem::Requirement
43
- requirements:
44
- - - "~>"
45
- - !ruby/object:Gem::Version
46
- version: 3.11.0
47
- name: rspec
48
- prerelease: false
49
- type: :development
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: 3.11.0
55
- - !ruby/object:Gem::Dependency
56
- requirement: !ruby/object:Gem::Requirement
57
- requirements:
58
- - - "~>"
59
- - !ruby/object:Gem::Version
60
- version: 1.25.0
61
- name: rubocop
62
21
  prerelease: false
63
- type: :development
64
22
  version_requirements: !ruby/object:Gem::Requirement
65
23
  requirements:
66
24
  - - "~>"
67
25
  - !ruby/object:Gem::Version
68
- version: 1.25.0
26
+ version: 1.1.3
27
+ force_ruby_platform: false
69
28
  description: Websocket Server for JRuby is a websocket server with a file server to
70
29
  support a demo javascript client application which interfaces with a demo echo server
71
30
  application.
@@ -75,11 +34,11 @@ executables:
75
34
  extensions: []
76
35
  extra_rdoc_files: []
77
36
  files:
78
- - LICENSE
37
+ - LICENSE.txt
79
38
  - README.md
80
39
  - Rakefile
81
40
  - exe/websocket
82
- - lib/log.rb
41
+ - lib/logging.rb
83
42
  - lib/server/mime_types.rb
84
43
  - lib/websocket-server.rb
85
44
  - lib/websocket/arguments_parser.rb
@@ -138,7 +97,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
138
97
  - !ruby/object:Gem::Version
139
98
  version: '0'
140
99
  requirements: []
141
- rubygems_version: 3.2.29
100
+ rubygems_version: 3.3.26
142
101
  signing_key:
143
102
  specification_version: 4
144
103
  summary: Websocket Server for JRuby packaged as a gem.