telnet-server 1.0.4-java → 1.1.2-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +22 -22
- data/exe/telnet +1 -1
- data/lib/logging.rb +253 -0
- data/lib/telnet/argument_parser.rb +11 -4
- data/lib/telnet/config.rb +1 -1
- data/lib/telnet/instance_methods.rb +2 -2
- data/lib/telnet/server.rb +4 -4
- data/lib/telnet/version.rb +2 -2
- data/lib/telnet-server.rb +1 -1
- data/lib/telnet_client.rb +12 -9
- data/lib/telnet_server.rb +3 -3
- metadata +7 -48
- data/lib/log.rb +0 -241
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 84d2494fa8c37050f8ab4f7187ef39d352bc1569b1346bfded57de2901594cd8
|
4
|
+
data.tar.gz: 37b08f5eac69e685ca09e9be008bc230a93407747bb7e022caa07570d7f07041
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a34f127f66a713c02b0044717f89433bb0b057adcd29a78551ccf955e89bc4b00b4666e10b5a1777a673fd508e225da5f42a3bc8c7f997be6de7cc7077a93745
|
7
|
+
data.tar.gz: 4c61a18edc92a8b2445f68a3c6a72ed042aa13ed8825bb91befa822e21d476016e6890767498fe50106513bfbee60535c6c5ab572a2e9b42ee4a58bb51d1849a
|
data/README.md
CHANGED
@@ -27,7 +27,7 @@ docker-compose down
|
|
27
27
|
Building the image or running the container:
|
28
28
|
|
29
29
|
```sh
|
30
|
-
docker build --
|
30
|
+
docker build --tag telnet-server-jruby .
|
31
31
|
docker run --detach --publish 21:21 --name telnet-server-jruby telnet-server-jruby
|
32
32
|
```
|
33
33
|
|
@@ -36,39 +36,40 @@ docker run --detach --publish 21:21 --name telnet-server-jruby telnet-server-jru
|
|
36
36
|
|
37
37
|
Run directly with the required dependencies installed.
|
38
38
|
|
39
|
-
### Install asdf
|
40
39
|
|
41
|
-
|
40
|
+
## Install mise-en-place
|
41
|
+
|
42
|
+
The [mise] CLI tool used to manage multiple runtime versions.
|
43
|
+
|
44
|
+
See: https://mise.jdx.dev/getting-started.html
|
42
45
|
|
43
46
|
```sh
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
+
curl https://mise.jdx.dev/install.sh | sh
|
48
|
+
~/.local/bin/mise --version
|
49
|
+
mise 2024.x.x
|
47
50
|
```
|
48
51
|
|
49
|
-
|
50
|
-
|
51
|
-
Download and install the latest version of the [Java JDK].
|
52
|
+
Enable mise activation in future zsh sessions.
|
52
53
|
|
53
54
|
```sh
|
54
|
-
|
55
|
-
asdf install java openjdk-17.0.2
|
55
|
+
echo 'eval "$(~/.local/bin/mise activate zsh)"' >> ~/.zshrc
|
56
56
|
```
|
57
57
|
|
58
58
|
|
59
|
-
|
59
|
+
## Install required runtime software
|
60
|
+
|
61
|
+
Use mise to install the runtime software defined as requirements
|
62
|
+
in the .tool-versions file.
|
60
63
|
|
61
64
|
```sh
|
62
|
-
|
63
|
-
asdf plugin update --all
|
64
|
-
asdf list all ruby
|
65
|
-
asdf install
|
65
|
+
mise install
|
66
66
|
```
|
67
67
|
|
68
68
|
|
69
69
|
Install the project dependencies.
|
70
70
|
|
71
71
|
```sh
|
72
|
+
gem install bundler
|
72
73
|
bundle install
|
73
74
|
```
|
74
75
|
|
@@ -106,12 +107,11 @@ bundle exec rake publish
|
|
106
107
|
Here is a bird's-eye view of the project layout.
|
107
108
|
|
108
109
|
```sh
|
109
|
-
# date && tree -A -I "logs|vendor|tmp"
|
110
|
-
|
110
|
+
# date && tree -A -I "logs|vendor|tmp|Gemfile.lock"
|
111
|
+
Sun Jul 24 14:18:45 CDT 2022
|
111
112
|
.
|
112
113
|
├── Dockerfile
|
113
114
|
├── Gemfile
|
114
|
-
├── Gemfile.lock
|
115
115
|
├── LICENSE
|
116
116
|
├── README.md
|
117
117
|
├── Rakefile
|
@@ -138,12 +138,12 @@ Sat Jul 23 22:13:21 CDT 2022
|
|
138
138
|
│ ├── test_spec.rb
|
139
139
|
│ └── verify
|
140
140
|
│ └── verify_spec.rb
|
141
|
-
├── telnet-server-1.0.
|
141
|
+
├── telnet-server-1.0.4-java.gem
|
142
142
|
├── telnet-server-jruby.gemspec
|
143
143
|
├── telnet-server-jruby.png
|
144
144
|
└── telnet.rb
|
145
145
|
|
146
|
-
7 directories,
|
146
|
+
7 directories, 25 files
|
147
147
|
```
|
148
148
|
|
149
149
|
|
@@ -187,7 +187,7 @@ curl --silent --show-error --location --request POST "https://gitlab.com/api/v4/
|
|
187
187
|
```
|
188
188
|
|
189
189
|
[license]: https://gitlab.com/nelsnelson/telnet-server-jruby/blob/master/LICENSE
|
190
|
-
[
|
190
|
+
[mise]: https://mise.jdx.dev/
|
191
191
|
[Netty project]: https://github.com/netty/netty
|
192
192
|
[Java JDK]: https://www.java.com/en/download/
|
193
193
|
[JRuby]: https://jruby.org/download
|
data/exe/telnet
CHANGED
data/lib/logging.rb
ADDED
@@ -0,0 +1,253 @@
|
|
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-2024 but freely usable (see license)
|
10
|
+
|
11
|
+
# =end
|
12
|
+
|
13
|
+
require 'java'
|
14
|
+
require 'fileutils'
|
15
|
+
require 'logger'
|
16
|
+
|
17
|
+
require 'apache-log4j-2'
|
18
|
+
|
19
|
+
# The Logging module
|
20
|
+
module Logging
|
21
|
+
module_function
|
22
|
+
|
23
|
+
# rubocop: disable Metrics/MethodLength
|
24
|
+
def config
|
25
|
+
@config ||= begin
|
26
|
+
lib_dir_path = File.expand_path(__dir__)
|
27
|
+
project_dir_path = File.expand_path(File.dirname(lib_dir_path))
|
28
|
+
logs_dir_path = File.expand_path(File.join(project_dir_path, 'logs'))
|
29
|
+
FileUtils.mkdir_p(logs_dir_path)
|
30
|
+
log_file_path = File.expand_path(File.join(logs_dir_path, 'server.log'))
|
31
|
+
FileUtils.touch(log_file_path)
|
32
|
+
{
|
33
|
+
level: Logger::INFO,
|
34
|
+
name: 'telnet',
|
35
|
+
lib_dir_path: lib_dir_path,
|
36
|
+
logs_dir_path: logs_dir_path,
|
37
|
+
log_file_path: log_file_path,
|
38
|
+
rolling_log_file_name_template: File.expand_path(
|
39
|
+
File.join(logs_dir_path, 'server-%d{yyyy-MM-dd}.log.gz')),
|
40
|
+
logging_pattern_template: {
|
41
|
+
java: '%d{ABSOLUTE} %-5p [%c{1}] %m%n',
|
42
|
+
ruby: "%<timestamp>s %-5<severity>s [%<progname>s] %<msg>s\n"
|
43
|
+
},
|
44
|
+
schedule: '0 0 0 * * ?',
|
45
|
+
size: '100M'
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
# rubocop: enable Metrics/MethodLength
|
50
|
+
end
|
51
|
+
|
52
|
+
# The Logging module
|
53
|
+
module Logging
|
54
|
+
if defined?(Java)
|
55
|
+
java_import Java::org.apache.logging.log4j.core.appender::ConsoleAppender
|
56
|
+
java_import Java::org.apache.logging.log4j.core.config::Configurator
|
57
|
+
java_import Java::org.apache.logging.log4j.core.config.builder.api::ConfigurationBuilderFactory
|
58
|
+
end
|
59
|
+
|
60
|
+
# rubocop: disable Metrics/AbcSize
|
61
|
+
# rubocop: disable Metrics/MethodLength
|
62
|
+
def init_log4j(log_level = org.apache.logging.log4j.Level::INFO)
|
63
|
+
java.lang::System.setProperty('log4j.shutdownHookEnabled', java.lang::Boolean.toString(false))
|
64
|
+
config = ConfigurationBuilderFactory.newConfigurationBuilder()
|
65
|
+
|
66
|
+
log_level = org.apache.logging.log4j::Level.to_level(log_level.to_s.upcase) if log_level.is_a? Symbol
|
67
|
+
config.setStatusLevel(log_level)
|
68
|
+
config.setConfigurationName('websocket')
|
69
|
+
|
70
|
+
# create a console appender
|
71
|
+
target = ConsoleAppender::Target::SYSTEM_OUT
|
72
|
+
pattern = Logging.config[:logging_pattern_template][:java]
|
73
|
+
layout = config.newLayout('PatternLayout')
|
74
|
+
layout = layout.addAttribute('pattern', pattern)
|
75
|
+
appender = config.newAppender('stdout', 'CONSOLE')
|
76
|
+
appender = appender.addAttribute('target', target)
|
77
|
+
appender = appender.add(layout)
|
78
|
+
config.add(appender)
|
79
|
+
|
80
|
+
# create a root logger
|
81
|
+
root_logger = config.newRootLogger(log_level)
|
82
|
+
root_logger = root_logger.add(config.newAppenderRef('stdout'))
|
83
|
+
|
84
|
+
# create a rolling file appender
|
85
|
+
cron = config.newComponent('CronTriggeringPolicy')
|
86
|
+
cron = cron.addAttribute('schedule', '0 0 0 * * ?')
|
87
|
+
|
88
|
+
size = config.newComponent('SizeBasedTriggeringPolicy')
|
89
|
+
size = size.addAttribute('size', '100M')
|
90
|
+
|
91
|
+
policies = config.newComponent('Policies')
|
92
|
+
policies = policies.addComponent(cron)
|
93
|
+
policies = policies.addComponent(size)
|
94
|
+
|
95
|
+
appender = config.newAppender('rolling_file', 'RollingFile')
|
96
|
+
appender = appender.addAttribute('fileName', Logging.config[:log_file_path])
|
97
|
+
appender = appender.addAttribute('filePattern', Logging.config[:rolling_log_file_name_template])
|
98
|
+
appender = appender.add(layout)
|
99
|
+
appender = appender.addComponent(policies)
|
100
|
+
config.add(appender)
|
101
|
+
|
102
|
+
root_logger = root_logger.addAttribute('additivity', false)
|
103
|
+
root_logger = root_logger.add(config.newAppenderRef('rolling_file'))
|
104
|
+
config.add(root_logger)
|
105
|
+
|
106
|
+
logging_configuration = config.build()
|
107
|
+
ctx = Configurator.initialize(logging_configuration)
|
108
|
+
ctx.updateLoggers()
|
109
|
+
end
|
110
|
+
module_function :init_log4j
|
111
|
+
# rubocop: enable Metrics/AbcSize
|
112
|
+
# rubocop: enable Metrics/MethodLength
|
113
|
+
# def init_log4j
|
114
|
+
|
115
|
+
init_log4j if defined?(Java)
|
116
|
+
end
|
117
|
+
# module Logging
|
118
|
+
|
119
|
+
# Namespace for methods to help with implicit backtrace printing
|
120
|
+
module LoggerHelpers
|
121
|
+
def generate_message(error_or_message, error)
|
122
|
+
error_message = "#{error_or_message}: #{error.class.name}"
|
123
|
+
error_message << ": #{error.message}" if error.respond_to?(:message)
|
124
|
+
error_message
|
125
|
+
end
|
126
|
+
|
127
|
+
def extract_backtrace(error, default_result = nil)
|
128
|
+
if error.respond_to?(:backtrace)
|
129
|
+
error.backtrace.each { |trace| original_error(trace) unless trace.nil? }
|
130
|
+
elsif error.respond_to?(:getStackTrace)
|
131
|
+
error.getStackTrace().each { |trace| original_error(trace) unless trace.nil? }
|
132
|
+
else
|
133
|
+
default_result
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# Monkey-patch the built-in Ruby Logger class to support
|
139
|
+
# implicit backtrace printing
|
140
|
+
# TODO: Figure out if this is actually useful.
|
141
|
+
class Logger
|
142
|
+
include LoggerHelpers
|
143
|
+
|
144
|
+
alias original_error error
|
145
|
+
def error(error_or_message, error = nil)
|
146
|
+
return extract_backtrace(error_or_message) if error.nil?
|
147
|
+
original_error(generate_message(error_or_message, error))
|
148
|
+
extract_backtrace(original_error(error))
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
# The Logging module
|
153
|
+
module Logging
|
154
|
+
if defined?(Java)
|
155
|
+
java_import Java::org.apache.logging.log4j.Level
|
156
|
+
java_import Java::org.apache.logging.log4j.LogManager
|
157
|
+
end
|
158
|
+
|
159
|
+
FORWARD_SLASH_PATTERN = %r{/} unless defined? FORWARD_SLASH_PATTERN
|
160
|
+
|
161
|
+
def init_logger(level = :info, logger_name = nil)
|
162
|
+
return init_java_logger(level, logger_name, caller[2]) if defined?(Java)
|
163
|
+
init_ruby_logger(level, logger_name, caller[2])
|
164
|
+
end
|
165
|
+
|
166
|
+
def ruby_log_formatter(severity_level, datetime, program_name, message)
|
167
|
+
format(
|
168
|
+
Logging.config[:logging_pattern_template][:ruby],
|
169
|
+
timestamp: datetime.strftime(Logging.config[:logging_timestamp_format]),
|
170
|
+
progname: program_name, severity: severity_level, msg: message)
|
171
|
+
end
|
172
|
+
|
173
|
+
def init_ruby_logger(level = nil, logger_name = nil, source_location = nil)
|
174
|
+
logger_name = get_formatted_logger_name(logger_name)
|
175
|
+
logger_name = source_location.split(FORWARD_SLASH_PATTERN).last if logger_name.empty?
|
176
|
+
log = Logger.new($stdout, progname: logger_name)
|
177
|
+
log.level = level.to_s unless level.nil?
|
178
|
+
log.formatter = method(:ruby_log_formatter)
|
179
|
+
log
|
180
|
+
end
|
181
|
+
|
182
|
+
def init_java_logger(level = nil, logger_name = nil, source_location = nil)
|
183
|
+
logger_name = get_formatted_logger_name(logger_name)
|
184
|
+
logger_name = source_location.split(FORWARD_SLASH_PATTERN).last if logger_name.empty?
|
185
|
+
log = LogManager.getLogger(logger_name)
|
186
|
+
log.level = Level.to_level(level.to_s.upcase) unless level.nil?
|
187
|
+
log
|
188
|
+
end
|
189
|
+
|
190
|
+
def get_formatted_logger_name(logger_name = nil)
|
191
|
+
return logger_name.to_s[/\w+$/] unless logger_name.nil?
|
192
|
+
return name[/\w+$/] if is_a?(Class) || is_a?(Module)
|
193
|
+
self.class.name[/\w+$/]
|
194
|
+
end
|
195
|
+
|
196
|
+
# rubocop: disable Metrics/CyclomaticComplexity
|
197
|
+
# OFF: 0
|
198
|
+
# FATAL: 100
|
199
|
+
# ERROR: 200
|
200
|
+
# WARN: 300
|
201
|
+
# INFO: 400
|
202
|
+
# DEBUG: 500
|
203
|
+
# TRACE: 600
|
204
|
+
# ALL: 2147483647
|
205
|
+
# See: https://logging.apache.org/log4j/2.x/log4j-api/apidocs/org/apache/logging/log4j/Level.html
|
206
|
+
def symbolize_numeric_log_level(level)
|
207
|
+
case level
|
208
|
+
when 5..Float::INFINITY then :off
|
209
|
+
when 4 then :fatal
|
210
|
+
when 3 then :error
|
211
|
+
when 2 then :warn
|
212
|
+
when 1 then :info
|
213
|
+
when 0 then :debug
|
214
|
+
when -1 then :trace
|
215
|
+
when -Float::INFINITY..-2 then :all
|
216
|
+
end
|
217
|
+
end
|
218
|
+
# rubocop: enable Metrics/CyclomaticComplexity
|
219
|
+
|
220
|
+
def log_level=(level)
|
221
|
+
Logging.config[:level] = symbolize_numeric_log_level(level)
|
222
|
+
end
|
223
|
+
module_function :log_level=
|
224
|
+
|
225
|
+
def log_level
|
226
|
+
Logging.config[:level]
|
227
|
+
end
|
228
|
+
module_function :log_level
|
229
|
+
|
230
|
+
def log(level = Logging.log_level, log_name = Logging.config[:app_name])
|
231
|
+
@log ||= init_logger(level, log_name)
|
232
|
+
end
|
233
|
+
alias logger log
|
234
|
+
end
|
235
|
+
# module Logging
|
236
|
+
|
237
|
+
# The Module class
|
238
|
+
class Module
|
239
|
+
# Universally include Logging
|
240
|
+
include ::Logging
|
241
|
+
end
|
242
|
+
|
243
|
+
# The Class class
|
244
|
+
class Class
|
245
|
+
# Universally include Logging
|
246
|
+
include ::Logging
|
247
|
+
end
|
248
|
+
|
249
|
+
# The Object class
|
250
|
+
class Object
|
251
|
+
# Universally include Logging
|
252
|
+
include ::Logging
|
253
|
+
end
|
@@ -6,7 +6,7 @@
|
|
6
6
|
|
7
7
|
# =begin
|
8
8
|
#
|
9
|
-
# Copyright Nels Nelson 2016-
|
9
|
+
# Copyright Nels Nelson 2016-2024 but freely usable (see license)
|
10
10
|
#
|
11
11
|
# =end
|
12
12
|
|
@@ -25,7 +25,7 @@ module Telnet
|
|
25
25
|
@parser = option_parser
|
26
26
|
@options = ::Telnet.server_config.dup
|
27
27
|
@flags = %i[banner port idle_reading idle_writing log_requests log_level help version]
|
28
|
-
@flags.each { |method_name| method(method_name)
|
28
|
+
@flags.each { |method_name| method(method_name)&.call if respond_to?(method_name) }
|
29
29
|
end
|
30
30
|
|
31
31
|
def banner
|
@@ -35,7 +35,9 @@ module Telnet
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def validated_port(val, integer_pattern = /^\d+$/)
|
38
|
-
raise "Invalid port: #{v}" unless
|
38
|
+
raise OptionParser::InvalidArgument, "Invalid port: #{v}" unless \
|
39
|
+
integer_pattern.match?(val.to_s) && val.positive? && val < 65_536
|
40
|
+
|
39
41
|
val
|
40
42
|
end
|
41
43
|
|
@@ -90,7 +92,12 @@ module Telnet
|
|
90
92
|
def parse_arguments(arguments_parser = ::Telnet::ArgumentsParser.new)
|
91
93
|
arguments_parser.parser.parse!(ARGV)
|
92
94
|
arguments_parser.options
|
93
|
-
rescue OptionParser::
|
95
|
+
rescue OptionParser::InvalidArgument, OptionParser::InvalidOption,
|
96
|
+
OptionParser::MissingArgument, OptionParser::NeedlessArgument => e
|
97
|
+
puts e.message
|
98
|
+
puts parser
|
99
|
+
exit
|
100
|
+
rescue OptionParser::AmbiguousOption => e
|
94
101
|
abort e.message
|
95
102
|
end
|
96
103
|
end
|
data/lib/telnet/config.rb
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
|
7
7
|
# =begin
|
8
8
|
#
|
9
|
-
# Copyright Nels Nelson 2016-
|
9
|
+
# Copyright Nels Nelson 2016-2024 but freely usable (see license)
|
10
10
|
#
|
11
11
|
# =end
|
12
12
|
|
@@ -41,7 +41,7 @@ module Telnet
|
|
41
41
|
# Writing to a ChannelBuffer is not needed here.
|
42
42
|
# The encoder will do the conversion.
|
43
43
|
def handle_message(ctx, message)
|
44
|
-
request =
|
44
|
+
request = message.to_s.strip
|
45
45
|
return handle_empty_request(ctx) if request.empty?
|
46
46
|
return close(ctx) if quit_command?(request)
|
47
47
|
ctx.write "Server echo: #{request}\r\n"
|
data/lib/telnet/server.rb
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
|
7
7
|
# =begin
|
8
8
|
#
|
9
|
-
# Copyright Nels Nelson 2016-
|
9
|
+
# Copyright Nels Nelson 2016-2024 but freely usable (see license)
|
10
10
|
#
|
11
11
|
# =end
|
12
12
|
|
@@ -22,9 +22,9 @@ module Telnet
|
|
22
22
|
class Server < Server::Server
|
23
23
|
include ::Telnet::InstanceMethods
|
24
24
|
|
25
|
-
def initialize(
|
26
|
-
|
27
|
-
super(
|
25
|
+
def initialize(options = {}, *handlers, &block)
|
26
|
+
raise ArgumentError, 'Parameter may not be nil: options' if options.nil?
|
27
|
+
super(::Telnet.server_config.merge(options), *handlers, &block)
|
28
28
|
end
|
29
29
|
|
30
30
|
def bootstrap
|
data/lib/telnet/version.rb
CHANGED
@@ -6,11 +6,11 @@
|
|
6
6
|
|
7
7
|
# =begin
|
8
8
|
#
|
9
|
-
# Copyright Nels Nelson 2016-
|
9
|
+
# Copyright Nels Nelson 2016-2024 but freely usable (see license)
|
10
10
|
#
|
11
11
|
# =end
|
12
12
|
|
13
13
|
# The Telnet module
|
14
14
|
module Telnet
|
15
|
-
VERSION = '1.
|
15
|
+
VERSION = '1.1.2'.freeze
|
16
16
|
end
|
data/lib/telnet-server.rb
CHANGED
data/lib/telnet_client.rb
CHANGED
@@ -8,21 +8,25 @@
|
|
8
8
|
|
9
9
|
# =begin
|
10
10
|
#
|
11
|
-
# Copyright Nels Nelson 2016-
|
11
|
+
# Copyright Nels Nelson 2016-2024 but freely usable (see license)
|
12
12
|
#
|
13
13
|
# =end
|
14
14
|
|
15
|
-
require 'logger'
|
16
15
|
require 'optparse'
|
17
16
|
|
18
17
|
require 'java'
|
19
18
|
require 'netty'
|
20
19
|
|
21
|
-
require_relative '
|
20
|
+
require_relative 'logging'
|
22
21
|
require_relative 'telnet/version'
|
23
22
|
|
24
23
|
# Simple telnet client
|
25
24
|
|
25
|
+
# The TelnetClient module
|
26
|
+
module TelnetClient
|
27
|
+
VERSION = '1.0.2'.freeze unless defined?(VERSION)
|
28
|
+
end
|
29
|
+
|
26
30
|
# The Telnet module
|
27
31
|
module Telnet
|
28
32
|
def client_config
|
@@ -416,14 +420,13 @@ end
|
|
416
420
|
module Telnet
|
417
421
|
# The ArgumentsParser class
|
418
422
|
class ArgumentsParser
|
419
|
-
IntegerPattern = /^\d+$/.freeze
|
420
|
-
Flags = %i[banner ssl log_level help version].freeze
|
421
423
|
attr_reader :parser, :options
|
422
424
|
|
423
425
|
def initialize(parser = OptionParser.new, options = ::Telnet.client_config.dup)
|
424
426
|
@parser = parser
|
425
427
|
@options = options
|
426
|
-
|
428
|
+
@flags = %i[banner ssl log_level help version]
|
429
|
+
@flags.each { |method_name| method(method_name)&.call if respond_to?(method_name) }
|
427
430
|
end
|
428
431
|
|
429
432
|
def banner
|
@@ -448,14 +451,14 @@ module Telnet
|
|
448
451
|
|
449
452
|
def version
|
450
453
|
@parser.on_tail('--version', 'Show version') do
|
451
|
-
puts "#{$PROGRAM_NAME} version #{
|
454
|
+
puts "#{File.basename($PROGRAM_NAME)} version #{::TelnetClient::VERSION}"
|
452
455
|
exit
|
453
456
|
end
|
454
457
|
end
|
455
458
|
|
456
459
|
def validated_port(val)
|
457
460
|
raise OptionParser::InvalidArgument, "Invalid port: #{val}" unless \
|
458
|
-
|
461
|
+
/^\d+$/.match?(val.to_s) && val.positive? && val < 65_536
|
459
462
|
|
460
463
|
val
|
461
464
|
end
|
@@ -515,4 +518,4 @@ module Telnet
|
|
515
518
|
end
|
516
519
|
# module Telnet
|
517
520
|
|
518
|
-
Object.new.extend(
|
521
|
+
Object.new.extend(Telnet).main if $PROGRAM_NAME == __FILE__
|
data/lib/telnet_server.rb
CHANGED
@@ -8,14 +8,14 @@
|
|
8
8
|
|
9
9
|
# =begin
|
10
10
|
#
|
11
|
-
# Copyright Nels Nelson 2016-
|
11
|
+
# Copyright Nels Nelson 2016-2024 but freely usable (see license)
|
12
12
|
#
|
13
13
|
# =end
|
14
14
|
|
15
15
|
require 'java'
|
16
16
|
require 'tcp-server'
|
17
17
|
|
18
|
-
require_relative '
|
18
|
+
require_relative 'logging'
|
19
19
|
require_relative 'telnet/argument_parser'
|
20
20
|
require_relative 'telnet/server'
|
21
21
|
|
@@ -23,7 +23,7 @@ require_relative 'telnet/server'
|
|
23
23
|
module Telnet
|
24
24
|
def main(args = parse_arguments)
|
25
25
|
Logging.log_level = args[:log_level]
|
26
|
-
::Telnet::Server.new(
|
26
|
+
::Telnet::Server.new(args).run
|
27
27
|
rescue Interrupt => e
|
28
28
|
warn format("\r%<class>s", class: e.class)
|
29
29
|
exit
|
metadata
CHANGED
@@ -1,71 +1,30 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: telnet-server
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 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:
|
11
|
+
date: 2024-04-12 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.
|
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.12
|
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.
|
26
|
+
version: 1.1.3
|
27
|
+
force_ruby_platform: false
|
69
28
|
description: Telnet Server for JRuby is a telnet server with a file server to support
|
70
29
|
a demo javascript client application which interfaces with a demo echo server application.
|
71
30
|
email: nels@nelsnelson.org
|
@@ -78,7 +37,7 @@ files:
|
|
78
37
|
- README.md
|
79
38
|
- Rakefile
|
80
39
|
- exe/telnet
|
81
|
-
- lib/
|
40
|
+
- lib/logging.rb
|
82
41
|
- lib/telnet-server.rb
|
83
42
|
- lib/telnet/argument_parser.rb
|
84
43
|
- lib/telnet/config.rb
|
@@ -109,7 +68,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
109
68
|
- !ruby/object:Gem::Version
|
110
69
|
version: '0'
|
111
70
|
requirements: []
|
112
|
-
rubygems_version: 3.
|
71
|
+
rubygems_version: 3.3.26
|
113
72
|
signing_key:
|
114
73
|
specification_version: 4
|
115
74
|
summary: Telnet Server for JRuby packaged as a gem.
|
data/lib/log.rb
DELETED
@@ -1,241 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
# frozen_string_literal: false
|
3
|
-
|
4
|
-
# =begin
|
5
|
-
|
6
|
-
# Copyright Nels Nelson 2016-2019 but freely usable (see license)
|
7
|
-
|
8
|
-
# =end
|
9
|
-
|
10
|
-
require 'java'
|
11
|
-
require 'logger'
|
12
|
-
|
13
|
-
require 'log4j-2'
|
14
|
-
|
15
|
-
require 'fileutils'
|
16
|
-
|
17
|
-
# The Logging module
|
18
|
-
module Logging
|
19
|
-
module_function
|
20
|
-
|
21
|
-
# rubocop: disable Metrics/MethodLength
|
22
|
-
def config
|
23
|
-
@config ||= begin
|
24
|
-
lib_dir_path = File.expand_path(__dir__)
|
25
|
-
project_dir_path = File.expand_path(File.dirname(lib_dir_path))
|
26
|
-
logs_dir_path = File.expand_path(File.join(project_dir_path, 'logs'))
|
27
|
-
server_log_file = File.expand_path(File.join(logs_dir_path, 'server.log'))
|
28
|
-
{
|
29
|
-
level: :info,
|
30
|
-
name: 'telnet',
|
31
|
-
logs_dir_path: logs_dir_path,
|
32
|
-
server_log_file: server_log_file,
|
33
|
-
rolling_log_file_name_template: 'server-%d{yyyy-MM-dd}.log.gz',
|
34
|
-
logger_pattern_template: '%d{ABSOLUTE} %-5p [%c{1}] %m%n',
|
35
|
-
schedule: '0 0 0 * * ?',
|
36
|
-
size: '100M'
|
37
|
-
}
|
38
|
-
end
|
39
|
-
end
|
40
|
-
# rubocop: enable Metrics/MethodLength
|
41
|
-
end
|
42
|
-
|
43
|
-
# The LogInitialization module
|
44
|
-
module LogInitialization
|
45
|
-
module_function
|
46
|
-
|
47
|
-
def init
|
48
|
-
init_log_file
|
49
|
-
init_log4j if defined? Java
|
50
|
-
end
|
51
|
-
|
52
|
-
def init_log_file
|
53
|
-
FileUtils.mkdir_p(Logging.config[:logs_dir_path])
|
54
|
-
return if File.file?(Logging.config[:server_log_file])
|
55
|
-
|
56
|
-
File.write(Logging.config[:server_log_file], '')
|
57
|
-
end
|
58
|
-
|
59
|
-
# rubocop: disable Metrics/AbcSize
|
60
|
-
# rubocop: disable Metrics/MethodLength
|
61
|
-
def init_log4j(log_level = org.apache.logging.log4j.Level::INFO)
|
62
|
-
server_log_file = Logging.config[:server_log_file]
|
63
|
-
logs_dir_path = Logging.config[:logs_dir_path]
|
64
|
-
rolling_log_file_name_template = Logging.config[:rolling_log_file_name_template]
|
65
|
-
rolling_log_file_path = File.join(logs_dir_path, rolling_log_file_name_template)
|
66
|
-
|
67
|
-
java.lang::System.setProperty('log4j.shutdownHookEnabled', java.lang::Boolean.toString(false))
|
68
|
-
factory = org.apache.logging.log4j.core.config.builder.api::ConfigurationBuilderFactory
|
69
|
-
config = factory.newConfigurationBuilder()
|
70
|
-
|
71
|
-
if log_level.is_a?(Symbol)
|
72
|
-
log_level = org.apache.logging.log4j.Level.to_level(
|
73
|
-
log_level.to_s.upcase
|
74
|
-
)
|
75
|
-
end
|
76
|
-
config.setStatusLevel(log_level)
|
77
|
-
config.setConfigurationName(Logging.config['name'])
|
78
|
-
|
79
|
-
# Create a console appender
|
80
|
-
target = org.apache.logging.log4j.core.appender::ConsoleAppender::Target::SYSTEM_OUT
|
81
|
-
layout = config.newLayout('PatternLayout')
|
82
|
-
layout = layout.addAttribute('pattern', Logging.config[:logger_pattern_template])
|
83
|
-
appender = config.newAppender('stdout', 'CONSOLE')
|
84
|
-
appender = appender.addAttribute('target', target)
|
85
|
-
appender = appender.add(layout)
|
86
|
-
config.add(appender)
|
87
|
-
|
88
|
-
# Create a root logger
|
89
|
-
root_logger = config.newRootLogger(log_level)
|
90
|
-
root_logger = root_logger.add(config.newAppenderRef('stdout'))
|
91
|
-
|
92
|
-
# Create a rolling file appender
|
93
|
-
cron = config.newComponent('CronTriggeringPolicy')
|
94
|
-
cron = cron.addAttribute('schedule', Logging.config[:schedule])
|
95
|
-
|
96
|
-
size = config.newComponent('SizeBasedTriggeringPolicy')
|
97
|
-
size = size.addAttribute('size', Logging.config[:size])
|
98
|
-
|
99
|
-
policies = config.newComponent('Policies')
|
100
|
-
policies = policies.addComponent(cron)
|
101
|
-
policies = policies.addComponent(size)
|
102
|
-
|
103
|
-
appender = config.newAppender('rolling_file', 'RollingFile')
|
104
|
-
appender = appender.addAttribute('fileName', server_log_file)
|
105
|
-
appender = appender.addAttribute('filePattern', rolling_log_file_path)
|
106
|
-
appender = appender.add(layout)
|
107
|
-
appender = appender.addComponent(policies)
|
108
|
-
config.add(appender)
|
109
|
-
|
110
|
-
root_logger = root_logger.addAttribute('additivity', false)
|
111
|
-
root_logger = root_logger.add(config.newAppenderRef('rolling_file'))
|
112
|
-
config.add(root_logger)
|
113
|
-
|
114
|
-
logging_configuration = config.build()
|
115
|
-
ctx = org.apache.logging.log4j.core.config::Configurator.initialize(logging_configuration)
|
116
|
-
ctx.updateLoggers()
|
117
|
-
end
|
118
|
-
# rubocop: enable Metrics/AbcSize
|
119
|
-
# rubocop: enable Metrics/MethodLength
|
120
|
-
# def init_log4j
|
121
|
-
end
|
122
|
-
# module LogInitialization
|
123
|
-
|
124
|
-
::LogInitialization.init
|
125
|
-
|
126
|
-
# The Apache log4j Logger class
|
127
|
-
# rubocop: disable Style/ClassAndModuleChildren
|
128
|
-
class org.apache.logging.log4j.core::Logger
|
129
|
-
alias log4j_error error
|
130
|
-
def error(error_or_message, error = nil)
|
131
|
-
return extract_backtrace(error_or_message) if error.nil?
|
132
|
-
log4j_error(generate_message(error_or_message, error))
|
133
|
-
extract_backtrace(error)
|
134
|
-
end
|
135
|
-
|
136
|
-
def generate_message(error_or_message, error)
|
137
|
-
error_message = "#{error_or_message}: #{error.class.name}"
|
138
|
-
error_message << ": #{error.message}" if error.respond_to?(:message)
|
139
|
-
error_message
|
140
|
-
end
|
141
|
-
|
142
|
-
def extract_backtrace(error, default_result = nil)
|
143
|
-
log4j_error(error)
|
144
|
-
if error.respond_to?(:backtrace)
|
145
|
-
error.backtrace.each { |trace| log4j_error(trace) unless trace.nil? }
|
146
|
-
elsif error.respond_to?(:getStackTrace)
|
147
|
-
error.getStackTrace().each { |trace| log4j_error(trace) unless trace.nil? }
|
148
|
-
else
|
149
|
-
default_result
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
153
|
-
# rubocop: enable Style/ClassAndModuleChildren
|
154
|
-
|
155
|
-
# The Logging module
|
156
|
-
module Logging
|
157
|
-
def init_logger(level = :all, logger_name = nil)
|
158
|
-
return init_java_logger(level, logger_name, caller[2]) if defined?(Java)
|
159
|
-
init_ruby_logger(level)
|
160
|
-
end
|
161
|
-
|
162
|
-
def init_ruby_logger(level)
|
163
|
-
logger_instance = Logger.new
|
164
|
-
logger_instance.level = Logging::Level.to_level(level.to_s.upcase)
|
165
|
-
logger_instance
|
166
|
-
end
|
167
|
-
|
168
|
-
# rubocop: disable Metrics/AbcSize
|
169
|
-
def init_java_logger(level, logger_name = nil, source_location = nil)
|
170
|
-
logger_name = get_formatted_logger_name(logger_name)
|
171
|
-
logger_name = source_location.split(/\//).last if logger_name.empty?
|
172
|
-
logger_instance = org.apache.logging.log4j.LogManager.getLogger(logger_name)
|
173
|
-
logger_instance.level = org.apache.logging.log4j.Level.to_level(level.to_s.upcase)
|
174
|
-
logger_instance
|
175
|
-
end
|
176
|
-
# rubocop: enable Metrics/AbcSize
|
177
|
-
|
178
|
-
def get_formatted_logger_name(logger_name = nil)
|
179
|
-
return logger_name.to_s[/\w+$/] unless logger_name.nil?
|
180
|
-
return name[/\w+$/] if is_a?(Class) || is_a?(Module)
|
181
|
-
self.class.name[/\w+$/]
|
182
|
-
end
|
183
|
-
|
184
|
-
def log(level = Logging.log_level, log_name = nil)
|
185
|
-
@log ||= init_logger(level, log_name)
|
186
|
-
end
|
187
|
-
alias logger log
|
188
|
-
|
189
|
-
module_function
|
190
|
-
|
191
|
-
# rubocop: disable Metrics/CyclomaticComplexity
|
192
|
-
# OFF: 0
|
193
|
-
# FATAL: 100
|
194
|
-
# ERROR: 200
|
195
|
-
# WARN: 300
|
196
|
-
# INFO: 400
|
197
|
-
# DEBUG: 500
|
198
|
-
# TRACE: 600
|
199
|
-
# ALL: 2147483647
|
200
|
-
# See: https://logging.apache.org/log4j/2.x/log4j-api/apidocs/org/apache/logging/log4j/Level.html
|
201
|
-
def symbolize_numeric_log_level(level)
|
202
|
-
case level
|
203
|
-
when 5..Float::INFINITY then :off
|
204
|
-
when 4 then :fatal
|
205
|
-
when 3 then :error
|
206
|
-
when 2 then :warn
|
207
|
-
when 1 then :info
|
208
|
-
when 0 then :debug
|
209
|
-
when -1 then :trace
|
210
|
-
when -2..-Float::INFINITY then :all
|
211
|
-
end
|
212
|
-
end
|
213
|
-
# rubocop: enable Metrics/CyclomaticComplexity
|
214
|
-
|
215
|
-
def log_level=(log_level)
|
216
|
-
Logging.config[:level] = symbolize_numeric_log_level(log_level)
|
217
|
-
end
|
218
|
-
|
219
|
-
def log_level
|
220
|
-
Logging.config[:level]
|
221
|
-
end
|
222
|
-
end
|
223
|
-
# module Logging
|
224
|
-
|
225
|
-
# The Module class
|
226
|
-
class Module
|
227
|
-
# Universally include Logging
|
228
|
-
include ::Logging
|
229
|
-
end
|
230
|
-
|
231
|
-
# The Class class
|
232
|
-
class Class
|
233
|
-
# Universally include Logging
|
234
|
-
include ::Logging
|
235
|
-
end
|
236
|
-
|
237
|
-
# The Object class
|
238
|
-
class Object
|
239
|
-
# Universally include Logging
|
240
|
-
include ::Logging
|
241
|
-
end
|