tcp-server 1.0.1-java → 1.0.4-java

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4b24ec50845ec5dac9b5d06a19a27575620319981f812f929e234506c8fbce9d
4
- data.tar.gz: 1fd77e294ea65d8a69d04c25c10b829d649cfda9d745baca45389605c918b4f9
3
+ metadata.gz: 3e13c7b958e72b6551472ad5a12389bc88687984b2d17f915f31a34dc2a420e8
4
+ data.tar.gz: 8682f4628c10fda39dcf7953ce0a31af1947af8507b5fc9ea41593ed8e4e3cba
5
5
  SHA512:
6
- metadata.gz: e6c68d68dc1d5f062d3febb563064730680ffe1099358bb6da27238eca58a7f5e6f221f82d9591b0015e0f1252d20fadf2fc2e70098951bc4da50417d070d85e
7
- data.tar.gz: e2129c54272cd36c5dbf7aa71d54abc0ed082dcd0cd5ad6f3c267aeb0b2c2b6b8475b4273f8fc8b0927f421fb36db95e8abc006f4120397a711462d574da6949
6
+ metadata.gz: 0535ec8e3b2a0c4d03f3150a1c8f551b2a32a4cf0c387d00b82b1d16f2b75e5fda2111fa8686febd3a36be2acaed68f165d08c99a6fa36a1515dbd4e129e9406
7
+ data.tar.gz: c2546356d7833043fbc7664afacba069ed21d9b8d5f460a58688f8714bd51dacaca95a60ce6319e3d19c6f54ad05faa57717af087c9e2085c5755b1d50efefe3
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![License](https://img.shields.io/badge/license-MIT--2.0-blue.svg?style=flat)][license]
4
4
 
5
- This is a small tcp server for [JRuby].
5
+ This is a small tcp server for [JRuby] available as a [ruby gem](https://rubygems.org/gems/tcp-server).
6
6
 
7
7
  It is based on the [Netty project]. Netty is written in java, but I wanted to write ruby.
8
8
 
@@ -14,7 +14,7 @@ Follow these instructions to get a tcp server echo program running.
14
14
 
15
15
  ### Docker
16
16
 
17
- You may run the websocket server in a container.
17
+ You may run the websocket server in a container. The [`colima`](https://github.com/abiosoft/colima) for a container runtime is recommended.
18
18
 
19
19
  ```sh
20
20
  colima start
@@ -24,7 +24,7 @@ docker-compose up
24
24
  Building the image or running the container:
25
25
 
26
26
  ```sh
27
- docker build --squash --tag tcp-server-jruby .
27
+ docker build --tag tcp-server-jruby .
28
28
  docker run --detach --publish 4000:4000 --name tcp-server-jruby tcp-server-jruby
29
29
  ```
30
30
 
@@ -76,7 +76,7 @@ bundle install
76
76
  The entrypoint for the web application service may now be invoked from a command line interface terminal shell.
77
77
 
78
78
  ```sh
79
- bundle exec ./server.rb
79
+ bundle exec ./tcp_server.rb
80
80
  ```
81
81
 
82
82
 
@@ -93,6 +93,15 @@ bundle exec rake
93
93
 
94
94
  To publish the gem after first verifying that the built gem works, execute:
95
95
 
96
+ ```sh
97
+ version=$(ruby -r lib/server/version -I . -e 'puts ::Server::VERSION')
98
+ git tag --annotate --message "Release ${version}" "${version}-release"
99
+ git push origin --tags
100
+ ```
101
+
102
+
103
+ Or manually, if necessary:
104
+
96
105
  ```sh
97
106
  bundle exec rake verify
98
107
  bundle exec rake publish
@@ -113,7 +122,82 @@ bundle exec rake clean clobber
113
122
  Here is a bird's-eye view of the project layout.
114
123
 
115
124
  ```sh
116
- # date && tree
125
+ # date && tree -I "logs|vendor|tmp"
126
+ Thu Jun 16 00:03:23 CDT 2022
127
+ .
128
+ ├── Dockerfile
129
+ ├── Gemfile
130
+ ├── Gemfile.lock
131
+ ├── LICENSE
132
+ ├── README.md
133
+ ├── Rakefile
134
+ ├── docker-compose.yaml
135
+ ├── exe
136
+ │ └── tcp_server
137
+ ├── lib
138
+ │ ├── client.rb
139
+ │ ├── demo_listener.rb
140
+ │ ├── log.rb
141
+ │ ├── server
142
+ │ │ ├── argument_parser.rb
143
+ │ │ ├── channel_initializer.rb
144
+ │ │ ├── config.rb
145
+ │ │ ├── instance_methods.rb
146
+ │ │ ├── listenable.rb
147
+ │ │ ├── message_handler.rb
148
+ │ │ ├── modular_handler.rb
149
+ │ │ ├── server.rb
150
+ │ │ ├── shutdown_hook.rb
151
+ │ │ └── version.rb
152
+ │ ├── server.rb
153
+ │ ├── tcp-server.rb
154
+ │ └── tcp_server.rb
155
+ ├── spec
156
+ │ ├── spec_helper.rb
157
+ │ ├── test_spec.rb
158
+ │ └── verify
159
+ │ └── verify_spec.rb
160
+ ├── tcp-server-1.0.2-java.gem
161
+ ├── tcp-server-jruby.gemspec
162
+ ├── tcp_server.png
163
+ └── tcp_server.rb
164
+
165
+ 5 directories, 31 files
166
+ ```
167
+
168
+ ## CI linting
169
+
170
+ Use the GitLab CI Linting API to validate the syntax of a CI definition file.
171
+
172
+ ```sh
173
+ jq --null-input --arg yaml "$(<.gitlab/ci/gem.gitlab-ci.yml)" '.content=$yaml' | curl --silent --location https://gitlab.com/api/v4/ci/lint --header "PRIVATE-TOKEN: ${GITLAB_COM_API_PRIVATE_TOKEN}" --header "Content-Type: application/json" --data @- | jq --raw-output '.errors[0]'
174
+ ```
175
+
176
+ ## CI configuration
177
+
178
+ Generate a deploy key.
179
+
180
+ ```sh
181
+ ssh-keygen -t ed25519 -C deploy_key
182
+ ```
183
+
184
+ Use the GitLab Project-level Variables API to add the deploy key as a ssh private key variable.
185
+
186
+ ```sh
187
+ project_path="nelsnelson/$(basename $(pwd))"
188
+
189
+ project=$(curl --silent --show-error --location "https://gitlab.com/api/v4/search?scope=projects&search=${project_path}" --header "PRIVATE-TOKEN: ${GITLAB_COM_API_PRIVATE_TOKEN}" | jq --arg project_path "${project_path}" '.[] | select(.path_with_namespace == $project_path)')
190
+
191
+ project_id=$(curl --silent --show-error --location "https://gitlab.com/api/v4/search?scope=projects&search=${project_path}" --header "PRIVATE-TOKEN: ${GITLAB_COM_API_PRIVATE_TOKEN}" | jq --arg project_path "${project_path}" '.[] | select(.path_with_namespace == $project_path) | .id')
192
+
193
+ # Add the deploy_token as a CI variable:
194
+ curl --silent --show-error --location --request POST "https://gitlab.com/api/v4/projects/${project_id}/variables" --header "PRIVATE-TOKEN: ${GITLAB_COM_API_PRIVATE_TOKEN}" --form "key=SSH_PRIVATE_KEY" --form "value=$(cat ./deploy_token)" --form "protected=true" | jq
195
+ ```
196
+
197
+ Use the Deploy keys API to add a the public deploy key as a deploy key for the project.
198
+
199
+ ```sh
200
+ curl --silent --show-error --location --request POST "https://gitlab.com/api/v4/projects/${project_id}/deploy_keys" --header "PRIVATE-TOKEN: ${GITLAB_COM_API_PRIVATE_TOKEN}" --data '{"title": "deploy_key", "key": "$(cat ./deploy_token.pub)", "can_push": "true"}' | jq
117
201
  ```
118
202
 
119
203
  [license]: https://gitlab.com/nelsnelson/tcp-server-jruby/blob/master/LICENSE
@@ -0,0 +1,31 @@
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
+ # The Demo class
16
+ class Demo
17
+ def channel_active(ctx)
18
+ ::Server.log.info "Channel active: #{ctx.channel}"
19
+ response = 'Hello, world!'
20
+ log.trace "Sending response: #{response.inspect}"
21
+ ctx.channel.writeAndFlush("#{response}\n")
22
+ end
23
+
24
+ def exception_caught(_ctx, cause)
25
+ ::Server.log.error "Exception caught: #{cause}"
26
+ cause.backtrace.each { |t| ::Server.log.error t }
27
+ ctx.close()
28
+ end
29
+ end
30
+ end
31
+ # module Server
@@ -36,17 +36,17 @@ module Server
36
36
  # constant definitions could not be used.
37
37
  Decoder = StringDecoder.new
38
38
  Encoder = StringEncoder.new
39
- attr_accessor :handlers
39
+ attr_accessor :user_handlers
40
40
  attr_reader :options
41
41
 
42
42
  def initialize(options = {})
43
43
  super()
44
44
  @options = options
45
- @handlers = []
45
+ @user_handlers = []
46
46
  end
47
47
 
48
48
  def <<(handler)
49
- @handlers << handler
49
+ @user_handlers << handler
50
50
  end
51
51
 
52
52
  def initChannel(channel)
@@ -64,7 +64,7 @@ module Server
64
64
  protected
65
65
 
66
66
  def add_user_handlers(pipeline)
67
- @handlers.each do |handler|
67
+ @user_handlers.each do |handler|
68
68
  case handler
69
69
  when Class then pipeline.addLast(handler.new)
70
70
  when Proc then pipeline.addLast(Server::MessageHandler.new(&handler))
@@ -93,23 +93,19 @@ module Server
93
93
 
94
94
  def ssl_handler(channel)
95
95
  handler = ssl_handler_instance(channel)
96
- handler.handshake_future.addListener(SslHandshakeFutureListener.new)
96
+ handler.handshake_future.addListener(ssl_handshake_future_listener)
97
97
  handler
98
98
  end
99
99
 
100
- # The SslHandshakeFutureListener class
101
- class SslHandshakeFutureListener
102
- include FutureListener
103
- # @Override
104
- #
105
- # public void operationComplete(Future<Channel> future) throws Exception
106
- def operationComplete(future)
100
+ def ssl_handshake_future_listener(listener = Object.new.extend(FutureListener))
101
+ listener.define_singleton_method(:operationComplete) do |future|
107
102
  raise future.cause unless future.success?
108
103
  session = future.now.pipeline.get('SslHandler#0')&.engine&.session
109
104
  ::Server.log.info "Channel protocol: #{session.protocol}, cipher suite: #{session.cipher_suite}"
110
105
  rescue StandardError => e
111
- ::Server.log.warn e.message
106
+ ::Server.log.warn "Error handling operation complete event: #{e.message}"
112
107
  end
108
+ listener
113
109
  end
114
110
 
115
111
  def ssl_engine(ssl_ctx)
@@ -27,14 +27,14 @@ module Server
27
27
  # The InstanceMethods module
28
28
  module InstanceMethods
29
29
  def configure_handlers(&block)
30
- ::Server::ChannelInitializer::DefaultHandler.add_listener(self)
30
+ add_listener(self)
31
31
  channel_initializer << block if block_given?
32
32
  end
33
33
 
34
34
  def bootstrap
35
35
  @bootstrap = ServerBootstrap.new
36
36
  @bootstrap.group(boss_group, worker_group)
37
- @bootstrap.channel(::Server::CHANNEL_TYPE)
37
+ @bootstrap.channel(Server::CHANNEL_TYPE)
38
38
  @bootstrap.option(ChannelOption::SO_BACKLOG, 100.to_java(java.lang.Integer))
39
39
  @bootstrap.handler(logging_handler) if options[:log_requests]
40
40
  @bootstrap.childHandler(channel_initializer)
@@ -71,8 +71,7 @@ module Server
71
71
  rescue java.net.SocketException => e
72
72
  raise "Socket error: #{e.message}: #{options[:host]}:#{port}"
73
73
  ensure
74
- boss_group&.shutdownGracefully()
75
- worker_group&.shutdownGracefully()
74
+ stop
76
75
  end
77
76
  # rubocop: enable Metrics/AbcSize
78
77
  # rubocop: enable Metrics/MethodLength
@@ -82,9 +81,18 @@ module Server
82
81
  ::Server::Channels.close().awaitUninterruptibly()
83
82
  end
84
83
 
84
+ def stop
85
+ boss_group&.shutdownGracefully()
86
+ worker_group&.shutdownGracefully()
87
+ end
88
+
85
89
  def <<(handler)
86
90
  channel_initializer << handler
87
91
  end
92
+
93
+ def add_listener(listener)
94
+ ::Server::ChannelInitializer::DefaultHandler.add_listener(listener)
95
+ end
88
96
  end
89
97
  # module ServerInstanceMethods
90
98
  end
@@ -104,7 +104,7 @@ module Server
104
104
  ::Server.log.warn "##{__method__} channel: #{ctx.channel}, cause: #{cause.message}"
105
105
  cause.backtrace.each { |t| ::Server.log.error t }
106
106
  listeners = notify :exception_caught, ctx, cause
107
- super(ctx, cause) if listeners.empty?
107
+ super(ctx, cause) if listeners.nil? || listeners.empty?
108
108
  end
109
109
 
110
110
  IdentiferTemplate = '#<%<class>s:0x%<id>s>'.freeze
data/lib/server/server.rb CHANGED
@@ -18,15 +18,14 @@ require_relative 'listenable'
18
18
 
19
19
  # The Server module
20
20
  module Server
21
- CHANNEL_TYPE = Java::io.netty.channel.socket.nio.NioServerSocketChannel.java_class
22
-
23
21
  # The Server class sets up the netty server.
24
22
  class Server
23
+ CHANNEL_TYPE = Java::io.netty.channel.socket.nio.NioServerSocketChannel.java_class
25
24
  include ::Server::InstanceMethods
26
25
  attr_reader :options
27
26
 
28
27
  def initialize(params = {}, &block)
29
- @options = params.fetch(:options, {})
28
+ @options = ::Server::Config::DEFAULTS.merge(params.fetch(:options, {}))
30
29
  configure_handlers(&block)
31
30
  end
32
31
 
@@ -40,10 +39,6 @@ module Server
40
39
  log.debug "Sending response: #{response.inspect}"
41
40
  ctx.writeAndFlush("#{response}\n")
42
41
  end
43
-
44
- def add_listener(listener)
45
- ::Server::ChannelInitializer::DefaultHandler.add_listener(listener)
46
- end
47
42
  # rubocop: enable Metrics/AbcSize
48
43
  end
49
44
  # class Server
@@ -28,7 +28,7 @@ module Server
28
28
  def run
29
29
  $stdout.write "\r\e[0K"
30
30
  $stdout.flush
31
- Server.log.info 'Shutting down'
31
+ ::Server.log.info 'Shutting down'
32
32
  @server.shutdown if server.respond_to?(:shutdown)
33
33
  end
34
34
  end
@@ -12,5 +12,5 @@
12
12
 
13
13
  # The Server module
14
14
  module Server
15
- VERSION = '1.0.1'.freeze
15
+ VERSION = '1.0.4'.freeze
16
16
  end
data/lib/server.rb CHANGED
@@ -20,22 +20,6 @@ require_relative 'server/server'
20
20
  module Server
21
21
  InterruptTemplate = "\r%<class>s".freeze
22
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
23
  # rubocop: disable Metrics/AbcSize
40
24
  # rubocop: disable Metrics/MethodLength
41
25
  def main(args = parse_arguments)
@@ -56,4 +40,6 @@ module Server
56
40
  end
57
41
  # module Server
58
42
 
43
+ require_relative 'demo_listener'
44
+
59
45
  Object.new.extend(::Server).main if $PROGRAM_NAME == __FILE__
data/lib/tcp-server.rb ADDED
@@ -0,0 +1,13 @@
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_relative 'server'
data/lib/tcp_server.rb ADDED
@@ -0,0 +1,13 @@
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_relative 'server'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tcp-server
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.4
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-04-17 00:00:00.000000000 Z
11
+ date: 2022-06-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -107,6 +107,7 @@ files:
107
107
  - Rakefile
108
108
  - exe/tcp_server
109
109
  - lib/client.rb
110
+ - lib/demo_listener.rb
110
111
  - lib/log.rb
111
112
  - lib/server.rb
112
113
  - lib/server/argument_parser.rb
@@ -119,6 +120,8 @@ files:
119
120
  - lib/server/server.rb
120
121
  - lib/server/shutdown_hook.rb
121
122
  - lib/server/version.rb
123
+ - lib/tcp-server.rb
124
+ - lib/tcp_server.rb
122
125
  homepage: https://rubygems.org/gems/tcp-server-jruby
123
126
  licenses:
124
127
  - MIT
@@ -144,5 +147,5 @@ requirements: []
144
147
  rubygems_version: 3.2.29
145
148
  signing_key:
146
149
  specification_version: 4
147
- summary: Server for JRuby packaged as a gem.
150
+ summary: TCP Server for JRuby packaged as a gem.
148
151
  test_files: []