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