tcp-server 1.0.1-java
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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +123 -0
- data/Rakefile +56 -0
- data/exe/tcp_server +17 -0
- data/lib/client.rb +578 -0
- data/lib/log.rb +207 -0
- data/lib/server/argument_parser.rb +106 -0
- data/lib/server/channel_initializer.rb +124 -0
- data/lib/server/config.rb +30 -0
- data/lib/server/instance_methods.rb +91 -0
- data/lib/server/listenable.rb +41 -0
- data/lib/server/message_handler.rb +56 -0
- data/lib/server/modular_handler.rb +119 -0
- data/lib/server/server.rb +51 -0
- data/lib/server/shutdown_hook.rb +35 -0
- data/lib/server/version.rb +16 -0
- data/lib/server.rb +59 -0
- metadata +148 -0
@@ -0,0 +1,119 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: false
|
3
|
+
|
4
|
+
# -*- mode: ruby -*-
|
5
|
+
# vi: set ft=ruby :
|
6
|
+
|
7
|
+
# =begin
|
8
|
+
#
|
9
|
+
# Copyright Nels Nelson 2016-2022 but freely usable (see license)
|
10
|
+
#
|
11
|
+
# =end
|
12
|
+
|
13
|
+
require 'java'
|
14
|
+
require 'netty'
|
15
|
+
|
16
|
+
require_relative 'listenable'
|
17
|
+
|
18
|
+
# The Server module
|
19
|
+
module Server
|
20
|
+
java_import Java::io.netty.channel.SimpleChannelInboundHandler
|
21
|
+
java_import Java::io.netty.channel.group.DefaultChannelGroup
|
22
|
+
java_import Java::io.netty.util.concurrent.GlobalEventExecutor
|
23
|
+
|
24
|
+
# rubocop: disable Style/IfUnlessModifier
|
25
|
+
unless defined?(::Server::Channels)
|
26
|
+
Channels = DefaultChannelGroup.new('channels', GlobalEventExecutor::INSTANCE)
|
27
|
+
end
|
28
|
+
# rubocop: enable Style/IfUnlessModifier
|
29
|
+
|
30
|
+
# The ModularHandler class notifies listeners about events.
|
31
|
+
class ModularHandler < SimpleChannelInboundHandler
|
32
|
+
include ::Server::Listenable
|
33
|
+
|
34
|
+
def isSharable
|
35
|
+
true
|
36
|
+
end
|
37
|
+
|
38
|
+
def channelRegistered(ctx)
|
39
|
+
log.trace "##{__method__} channel: #{ctx.channel}"
|
40
|
+
notify :channel_registered, ctx
|
41
|
+
super(ctx)
|
42
|
+
end
|
43
|
+
|
44
|
+
def channelUnregistered(ctx)
|
45
|
+
log.trace "##{__method__} channel: #{ctx.channel}"
|
46
|
+
notify :channel_unregistered, ctx
|
47
|
+
super(ctx)
|
48
|
+
end
|
49
|
+
|
50
|
+
def channelActive(ctx)
|
51
|
+
log.trace "##{__method__} channel: #{ctx.channel}"
|
52
|
+
::Server::Channels.add(ctx.channel)
|
53
|
+
notify :channel_active, ctx
|
54
|
+
super(ctx)
|
55
|
+
end
|
56
|
+
|
57
|
+
def channelInactive(ctx)
|
58
|
+
log.trace "##{__method__} channel: #{ctx.channel}"
|
59
|
+
notify :channel_inactive, ctx
|
60
|
+
super(ctx)
|
61
|
+
end
|
62
|
+
|
63
|
+
def channelRead(ctx, msg)
|
64
|
+
log.trace "##{__method__} channel: #{ctx.channel}, message: #{msg.inspect}"
|
65
|
+
notify :channel_read, ctx, msg
|
66
|
+
super(ctx, msg)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Please keep in mind that this method will be renamed to
|
70
|
+
# messageReceived(ChannelHandlerContext, I) in 5.0.
|
71
|
+
#
|
72
|
+
# java_signature 'protected abstract void channelRead0(ChannelHandlerContext ctx, I msg) throws Exception'
|
73
|
+
def channelRead0(ctx, msg)
|
74
|
+
log.trace "##{__method__} channel: #{ctx.channel}, message: #{msg.inspect}"
|
75
|
+
messageReceived(ctx, msg)
|
76
|
+
# super(ctx, msg)
|
77
|
+
end
|
78
|
+
|
79
|
+
def messageReceived(ctx, msg)
|
80
|
+
log.trace "##{__method__} channel: #{ctx.channel}, message: #{msg.inspect}"
|
81
|
+
notify :message_received, ctx, msg
|
82
|
+
# super(ctx, msg)
|
83
|
+
end
|
84
|
+
|
85
|
+
def channelReadComplete(ctx)
|
86
|
+
log.trace "##{__method__} channel: #{ctx.channel}"
|
87
|
+
notify :channel_read_complete, ctx
|
88
|
+
super(ctx)
|
89
|
+
end
|
90
|
+
|
91
|
+
def userEventTriggered(ctx, evt)
|
92
|
+
log.trace "##{__method__} channel: #{ctx.channel}, event: #{evt}"
|
93
|
+
notify :user_event_triggered, ctx, evt
|
94
|
+
super(ctx, evt)
|
95
|
+
end
|
96
|
+
|
97
|
+
def channelWritabilityChanged(ctx)
|
98
|
+
log.trace "##{__method__} channel: #{ctx.channel}"
|
99
|
+
notify :channel_writability_changed, ctx
|
100
|
+
super(ctx)
|
101
|
+
end
|
102
|
+
|
103
|
+
def exceptionCaught(ctx, cause)
|
104
|
+
::Server.log.warn "##{__method__} channel: #{ctx.channel}, cause: #{cause.message}"
|
105
|
+
cause.backtrace.each { |t| ::Server.log.error t }
|
106
|
+
listeners = notify :exception_caught, ctx, cause
|
107
|
+
super(ctx, cause) if listeners.empty?
|
108
|
+
end
|
109
|
+
|
110
|
+
IdentiferTemplate = '#<%<class>s:0x%<id>s>'.freeze
|
111
|
+
|
112
|
+
def to_s
|
113
|
+
format(IdentiferTemplate, class: self.class.name, id: object_id.to_s(16))
|
114
|
+
end
|
115
|
+
alias inspect to_s
|
116
|
+
end
|
117
|
+
# class ModularHandler
|
118
|
+
end
|
119
|
+
# module Server
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: false
|
3
|
+
|
4
|
+
# -*- mode: ruby -*-
|
5
|
+
# vi: set ft=ruby :
|
6
|
+
|
7
|
+
# =begin
|
8
|
+
#
|
9
|
+
# Copyright Nels Nelson 2016-2022 but freely usable (see license)
|
10
|
+
#
|
11
|
+
# =end
|
12
|
+
|
13
|
+
require 'java'
|
14
|
+
require 'netty'
|
15
|
+
|
16
|
+
require_relative 'instance_methods'
|
17
|
+
require_relative 'listenable'
|
18
|
+
|
19
|
+
# The Server module
|
20
|
+
module Server
|
21
|
+
CHANNEL_TYPE = Java::io.netty.channel.socket.nio.NioServerSocketChannel.java_class
|
22
|
+
|
23
|
+
# The Server class sets up the netty server.
|
24
|
+
class Server
|
25
|
+
include ::Server::InstanceMethods
|
26
|
+
attr_reader :options
|
27
|
+
|
28
|
+
def initialize(params = {}, &block)
|
29
|
+
@options = params.fetch(:options, {})
|
30
|
+
configure_handlers(&block)
|
31
|
+
end
|
32
|
+
|
33
|
+
# rubocop: disable Metrics/AbcSize
|
34
|
+
def message_received(ctx, msg)
|
35
|
+
log.trace "##{__method__} channel: #{ctx.channel}, message: #{msg.inspect}"
|
36
|
+
msg&.chomp!
|
37
|
+
return if msg.nil? || msg.empty?
|
38
|
+
return ctx.close() if @options[:quit_commands].include?(msg.downcase.to_sym)
|
39
|
+
response = msg.upcase
|
40
|
+
log.debug "Sending response: #{response.inspect}"
|
41
|
+
ctx.writeAndFlush("#{response}\n")
|
42
|
+
end
|
43
|
+
|
44
|
+
def add_listener(listener)
|
45
|
+
::Server::ChannelInitializer::DefaultHandler.add_listener(listener)
|
46
|
+
end
|
47
|
+
# rubocop: enable Metrics/AbcSize
|
48
|
+
end
|
49
|
+
# class Server
|
50
|
+
end
|
51
|
+
# module Server
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: false
|
3
|
+
|
4
|
+
# -*- mode: ruby -*-
|
5
|
+
# vi: set ft=ruby :
|
6
|
+
|
7
|
+
# =begin
|
8
|
+
#
|
9
|
+
# Copyright Nels Nelson 2016-2022 but freely usable (see license)
|
10
|
+
#
|
11
|
+
# =end
|
12
|
+
|
13
|
+
require 'java'
|
14
|
+
|
15
|
+
# The Server module
|
16
|
+
module Server
|
17
|
+
# The ShutdownHook class specifies a routine to be invoked when the
|
18
|
+
# java runtime is shutdown.
|
19
|
+
class ShutdownHook < java.lang.Thread
|
20
|
+
attr_reader :server
|
21
|
+
|
22
|
+
def initialize(server)
|
23
|
+
super()
|
24
|
+
@server = server
|
25
|
+
java.lang.Runtime.runtime.add_shutdown_hook(self)
|
26
|
+
end
|
27
|
+
|
28
|
+
def run
|
29
|
+
$stdout.write "\r\e[0K"
|
30
|
+
$stdout.flush
|
31
|
+
Server.log.info 'Shutting down'
|
32
|
+
@server.shutdown if server.respond_to?(:shutdown)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: false
|
3
|
+
|
4
|
+
# -*- mode: ruby -*-
|
5
|
+
# vi: set ft=ruby :
|
6
|
+
|
7
|
+
# =begin
|
8
|
+
#
|
9
|
+
# Copyright Nels Nelson 2016-2022 but freely usable (see license)
|
10
|
+
#
|
11
|
+
# =end
|
12
|
+
|
13
|
+
# The Server module
|
14
|
+
module Server
|
15
|
+
VERSION = '1.0.1'.freeze
|
16
|
+
end
|
data/lib/server.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
#! /usr/bin/env jruby
|
2
|
+
|
3
|
+
# encoding: utf-8
|
4
|
+
# frozen_string_literal: false
|
5
|
+
|
6
|
+
# -*- mode: ruby -*-
|
7
|
+
# vi: set ft=ruby :
|
8
|
+
|
9
|
+
# =begin
|
10
|
+
#
|
11
|
+
# Copyright Nels Nelson 2016-2022 but freely usable (see license)
|
12
|
+
#
|
13
|
+
# =end
|
14
|
+
|
15
|
+
require_relative 'log'
|
16
|
+
require_relative 'server/argument_parser'
|
17
|
+
require_relative 'server/server'
|
18
|
+
|
19
|
+
# The Server module
|
20
|
+
module Server
|
21
|
+
InterruptTemplate = "\r%<class>s".freeze
|
22
|
+
|
23
|
+
# The Demo class
|
24
|
+
class Demo
|
25
|
+
def channel_active(ctx)
|
26
|
+
::Server.log.info "Channel active: #{ctx.channel}"
|
27
|
+
response = 'Hello, world!'
|
28
|
+
log.trace "Sending response: #{response.inspect}"
|
29
|
+
ctx.channel.writeAndFlush("#{response}\n")
|
30
|
+
end
|
31
|
+
|
32
|
+
def exception_caught(_ctx, cause)
|
33
|
+
::Server.log.error "Exception caught: #{cause}"
|
34
|
+
cause.backtrace.each { |t| ::Server.log.error t }
|
35
|
+
ctx.close()
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# rubocop: disable Metrics/AbcSize
|
40
|
+
# rubocop: disable Metrics/MethodLength
|
41
|
+
def main(args = parse_arguments)
|
42
|
+
Logging.log_level = args[:log_level]
|
43
|
+
server = ::Server::Server.new(options: args)
|
44
|
+
server.add_listener(::Server::Demo.new)
|
45
|
+
server.run
|
46
|
+
rescue Interrupt => e
|
47
|
+
warn format(InterruptTemplate, class: e.class)
|
48
|
+
exit
|
49
|
+
rescue StandardError => e
|
50
|
+
::Server.log.fatal(e)
|
51
|
+
e.backtrace.each { |t| ::Server.log.fatal t }
|
52
|
+
exit 1
|
53
|
+
end
|
54
|
+
# rubocop: enable Metrics/AbcSize
|
55
|
+
# rubocop: enable Metrics/MethodLength
|
56
|
+
end
|
57
|
+
# module Server
|
58
|
+
|
59
|
+
Object.new.extend(::Server).main if $PROGRAM_NAME == __FILE__
|
metadata
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tcp-server
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.1
|
5
|
+
platform: java
|
6
|
+
authors:
|
7
|
+
- Nels Nelson
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-04-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - "~>"
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: 2.17.1
|
19
|
+
name: apache-log4j-2
|
20
|
+
prerelease: false
|
21
|
+
type: :runtime
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 2.17.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - "~>"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.70.1
|
33
|
+
name: bouncycastle
|
34
|
+
prerelease: false
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.70.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 4.1.74
|
47
|
+
name: netty-io
|
48
|
+
prerelease: false
|
49
|
+
type: :runtime
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 4.1.74
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 12.3.0
|
61
|
+
name: rake
|
62
|
+
prerelease: false
|
63
|
+
type: :development
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 12.3.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 3.11.0
|
75
|
+
name: rspec
|
76
|
+
prerelease: false
|
77
|
+
type: :development
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 3.11.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 1.25.0
|
89
|
+
name: rubocop
|
90
|
+
prerelease: false
|
91
|
+
type: :development
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 1.25.0
|
97
|
+
description: TCP Server for JRuby is a tcp server which supports a demo echo server
|
98
|
+
application.
|
99
|
+
email: nels@nelsnelson.org
|
100
|
+
executables:
|
101
|
+
- tcp_server
|
102
|
+
extensions: []
|
103
|
+
extra_rdoc_files: []
|
104
|
+
files:
|
105
|
+
- LICENSE
|
106
|
+
- README.md
|
107
|
+
- Rakefile
|
108
|
+
- exe/tcp_server
|
109
|
+
- lib/client.rb
|
110
|
+
- lib/log.rb
|
111
|
+
- lib/server.rb
|
112
|
+
- lib/server/argument_parser.rb
|
113
|
+
- lib/server/channel_initializer.rb
|
114
|
+
- lib/server/config.rb
|
115
|
+
- lib/server/instance_methods.rb
|
116
|
+
- lib/server/listenable.rb
|
117
|
+
- lib/server/message_handler.rb
|
118
|
+
- lib/server/modular_handler.rb
|
119
|
+
- lib/server/server.rb
|
120
|
+
- lib/server/shutdown_hook.rb
|
121
|
+
- lib/server/version.rb
|
122
|
+
homepage: https://rubygems.org/gems/tcp-server-jruby
|
123
|
+
licenses:
|
124
|
+
- MIT
|
125
|
+
metadata:
|
126
|
+
source_code_uri: https://gitlab.com/nelsnelson/tcp-server-jruby
|
127
|
+
bug_tracker_uri: https://gitlab.com/nelsnelson/tcp-server-jruby/issues
|
128
|
+
rubygems_mfa_required: 'true'
|
129
|
+
post_install_message:
|
130
|
+
rdoc_options: []
|
131
|
+
require_paths:
|
132
|
+
- lib
|
133
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: 2.6.8
|
138
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
143
|
+
requirements: []
|
144
|
+
rubygems_version: 3.2.29
|
145
|
+
signing_key:
|
146
|
+
specification_version: 4
|
147
|
+
summary: Server for JRuby packaged as a gem.
|
148
|
+
test_files: []
|