io_request 2.0.0 → 2.1.0
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 +4 -4
- data/Gemfile +4 -0
- data/bin/console +2 -9
- data/lib/io_request.rb +4 -20
- data/lib/io_request/connection/ssl_sockets.rb +155 -0
- data/lib/io_request/logging.rb +20 -0
- data/lib/io_request/message.rb +4 -3
- data/lib/io_request/version.rb +1 -1
- metadata +3 -2
- data/examples/simple_example.rb +0 -54
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3129d25d05cbc0292eb186416db04f305f3c8fa09c525daafe1926ea2c833a76
|
4
|
+
data.tar.gz: 417380ff03d49890bd4161a1db3811c3e4c105c5357082579801318aadb828cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e20f44b5bd79b67d7b0d33c5edd16ba34321f1815bf3641c7bf986798e9bfc0ed3495015625b58bc541385fb4b6f35e16c080eac1e9c92404b35db255c815d23
|
7
|
+
data.tar.gz: 3638cb26446495bf95154d1e3d836b2b5660023491bd53b45175fb8701012d5de6fc3e5832381f4a0fe165b3858bc52056f8087c8a8026f73c8f8c096e5683ae
|
data/Gemfile
CHANGED
data/bin/console
CHANGED
@@ -4,12 +4,5 @@
|
|
4
4
|
require 'bundler/setup'
|
5
5
|
require 'io_request'
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
-
# require "pry"
|
12
|
-
# Pry.start
|
13
|
-
|
14
|
-
require 'irb'
|
15
|
-
IRB.start(__FILE__)
|
7
|
+
require 'pry'
|
8
|
+
Pry.start(__FILE__)
|
data/lib/io_request.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# Main module.
|
4
|
+
module IORequest; end
|
5
|
+
|
3
6
|
require_relative 'io_request/version'
|
7
|
+
require_relative 'io_request/logging'
|
4
8
|
require_relative 'io_request/utility/multi_thread'
|
5
9
|
require_relative 'io_request/utility/with_id'
|
6
10
|
require_relative 'io_request/utility/with_prog_name'
|
@@ -8,23 +12,3 @@ require_relative 'io_request/utility/with_prog_name'
|
|
8
12
|
require_relative 'io_request/authorizer'
|
9
13
|
require_relative 'io_request/message'
|
10
14
|
require_relative 'io_request/client'
|
11
|
-
|
12
|
-
require 'logger'
|
13
|
-
|
14
|
-
# Main module.
|
15
|
-
module IORequest
|
16
|
-
# @return [Logger]
|
17
|
-
def self.logger
|
18
|
-
@@logger ||= Logger.new( # rubocop:disable Style/ClassVars
|
19
|
-
STDOUT,
|
20
|
-
formatter: proc do |severity, datetime, progname, msg|
|
21
|
-
"[#{datetime}] #{severity} - #{progname}:\t #{msg}\n"
|
22
|
-
end
|
23
|
-
)
|
24
|
-
end
|
25
|
-
|
26
|
-
# @param new_logger [Logger]
|
27
|
-
def self.logger=(new_logger)
|
28
|
-
@@logger = new_logger # rubocop:disable Style/ClassVars
|
29
|
-
end
|
30
|
-
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../io_request'
|
4
|
+
|
5
|
+
require 'socket'
|
6
|
+
require 'openssl'
|
7
|
+
|
8
|
+
module IORequest
|
9
|
+
# Connection via SSL sockets
|
10
|
+
module SSLSockets
|
11
|
+
# SSL socket server.
|
12
|
+
class Server
|
13
|
+
include Utility::MultiThread
|
14
|
+
|
15
|
+
# Initalize new server.
|
16
|
+
# @param port [Integer] port of server.
|
17
|
+
# @param authorizer [Authorizer]
|
18
|
+
# @param certificate [String]
|
19
|
+
# @param key [String]
|
20
|
+
def initialize(
|
21
|
+
port: 8000,
|
22
|
+
authorizer: Authorizer.empty,
|
23
|
+
certificate: nil,
|
24
|
+
key: nil,
|
25
|
+
&requests_handler
|
26
|
+
)
|
27
|
+
@port = port
|
28
|
+
@authorizer = authorizer
|
29
|
+
@requests_handler = requests_handler
|
30
|
+
|
31
|
+
initialize_ssl_context(certificate, key)
|
32
|
+
end
|
33
|
+
|
34
|
+
# @return [Array<IORequest::Client>]
|
35
|
+
attr_reader :clients
|
36
|
+
|
37
|
+
# Start server.
|
38
|
+
def start
|
39
|
+
@clients = []
|
40
|
+
|
41
|
+
@server = TCPServer.new(@port)
|
42
|
+
|
43
|
+
@accept_thread = in_thread(name: 'accept_thr') { accept_loop }
|
44
|
+
end
|
45
|
+
|
46
|
+
# Fully stop server.
|
47
|
+
def stop
|
48
|
+
@clients.each(&:close)
|
49
|
+
@clients = []
|
50
|
+
|
51
|
+
@server.close
|
52
|
+
@server = nil
|
53
|
+
|
54
|
+
@accept_thread&.kill
|
55
|
+
@accept_thread = nil
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def initialize_ssl_context(certificate, key)
|
61
|
+
@ctx = OpenSSL::SSL::SSLContext.new
|
62
|
+
@ctx.cert = OpenSSL::X509::Certificate.new certificate
|
63
|
+
@ctx.key = OpenSSL::PKey::RSA.new key
|
64
|
+
@ctx.ssl_version = :TLSv1_2
|
65
|
+
end
|
66
|
+
|
67
|
+
def accept_loop
|
68
|
+
while (socket = @server.accept)
|
69
|
+
handle_socket(socket)
|
70
|
+
end
|
71
|
+
rescue
|
72
|
+
stop
|
73
|
+
end
|
74
|
+
|
75
|
+
def handle_socket(socket)
|
76
|
+
ssl_socket = OpenSSL::SSL::SSLSocket.new(socket, @ctx)
|
77
|
+
ssl_socket.accept
|
78
|
+
|
79
|
+
client = IORequest::Client.new authorizer: @authorizer
|
80
|
+
begin
|
81
|
+
client.open read_write: ssl_socket
|
82
|
+
client.respond(&@requests_handler)
|
83
|
+
@clients << client
|
84
|
+
rescue StandardError
|
85
|
+
IORequest.debug "Failed to open client: #{e}"
|
86
|
+
ssl_socket.close
|
87
|
+
end
|
88
|
+
rescue StandardError => e
|
89
|
+
IORequest.warn "Unknown error while handling sockets: #{e}"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# SSL socket client.
|
94
|
+
class Client
|
95
|
+
# Initialize new client.
|
96
|
+
# @param authorizer [Authorizer]
|
97
|
+
# @param certificate [String]
|
98
|
+
# @param key [String]
|
99
|
+
def initialize(
|
100
|
+
authorizer: Authorizer.empty,
|
101
|
+
certificate: nil,
|
102
|
+
key: nil,
|
103
|
+
&requests_handler
|
104
|
+
)
|
105
|
+
@authorizer = authorizer
|
106
|
+
@requests_handler = requests_handler
|
107
|
+
|
108
|
+
initialize_ssl_context(certificate, key)
|
109
|
+
end
|
110
|
+
|
111
|
+
# Connect to server.
|
112
|
+
# @param host [String] host of server.
|
113
|
+
# @param port [Integer] port of server.
|
114
|
+
def connect(host = 'localhost', port = 8000)
|
115
|
+
socket = TCPSocket.new(host, port)
|
116
|
+
|
117
|
+
ssl_socket = OpenSSL::SSL::SSLSocket.new(socket, @ctx)
|
118
|
+
ssl_socket.sync_close = true
|
119
|
+
ssl_socket.connect
|
120
|
+
|
121
|
+
@client = IORequest::Client.new authorizer: @authorizer
|
122
|
+
begin
|
123
|
+
@client.open read_write: ssl_socket
|
124
|
+
@client.respond(&@requests_handler)
|
125
|
+
rescue StandardError
|
126
|
+
IORequest.debug "Failed to open client: #{e}"
|
127
|
+
ssl_socket.close
|
128
|
+
@client = nil
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# Closes connection to server.
|
133
|
+
def disconnect
|
134
|
+
return unless defined?(@client) && !@client.nil?
|
135
|
+
|
136
|
+
@client.close
|
137
|
+
@client = nil
|
138
|
+
end
|
139
|
+
|
140
|
+
# Wrapper over {IORequest::Client#request}
|
141
|
+
def request(*args, **options, &block)
|
142
|
+
@client.request(*args, **options, &block)
|
143
|
+
end
|
144
|
+
|
145
|
+
private
|
146
|
+
|
147
|
+
def initialize_ssl_context(certificate, key)
|
148
|
+
@ctx = OpenSSL::SSL::SSLContext.new
|
149
|
+
@ctx.cert = OpenSSL::X509::Certificate.new certificate
|
150
|
+
@ctx.key = OpenSSL::PKey::RSA.new key
|
151
|
+
@ctx.ssl_version = :TLSv1_2
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
module IORequest
|
6
|
+
# @return [Logger]
|
7
|
+
def self.logger
|
8
|
+
@@logger ||= Logger.new( # rubocop:disable Style/ClassVars
|
9
|
+
STDOUT,
|
10
|
+
formatter: proc do |severity, datetime, progname, msg|
|
11
|
+
"[#{datetime}] #{severity} - #{progname}:\t #{msg}\n"
|
12
|
+
end
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
# @param new_logger [Logger]
|
17
|
+
def self.logger=(new_logger)
|
18
|
+
@@logger = new_logger # rubocop:disable Style/ClassVars
|
19
|
+
end
|
20
|
+
end
|
data/lib/io_request/message.rb
CHANGED
@@ -10,9 +10,10 @@ module IORequest
|
|
10
10
|
# Create new message.
|
11
11
|
# @param data [Hash]
|
12
12
|
# @param type [Symbol] one of {TYPES} member.
|
13
|
-
# @param id [Utility::ExtendedID, String, nil] only should be filled if
|
14
|
-
#
|
15
|
-
#
|
13
|
+
# @param id [Utility::ExtendedID, String, nil] only should be filled if
|
14
|
+
# message is received from outside.
|
15
|
+
# @param to [Utility::ExtendedID, String, nil] if message is response, it
|
16
|
+
# should include integer of original request.
|
16
17
|
def initialize(data, type: :request, id: nil, to: nil)
|
17
18
|
@data = data
|
18
19
|
@type = type
|
data/lib/io_request/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: io_request
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fizvlad
|
@@ -110,11 +110,12 @@ files:
|
|
110
110
|
- README.md
|
111
111
|
- Rakefile
|
112
112
|
- bin/console
|
113
|
-
- examples/simple_example.rb
|
114
113
|
- io_request.gemspec
|
115
114
|
- lib/io_request.rb
|
116
115
|
- lib/io_request/authorizer.rb
|
117
116
|
- lib/io_request/client.rb
|
117
|
+
- lib/io_request/connection/ssl_sockets.rb
|
118
|
+
- lib/io_request/logging.rb
|
118
119
|
- lib/io_request/message.rb
|
119
120
|
- lib/io_request/utility/multi_thread.rb
|
120
121
|
- lib/io_request/utility/with_id.rb
|
data/examples/simple_example.rb
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'io_request'
|
4
|
-
|
5
|
-
r1, w1 = IO.pipe
|
6
|
-
r2, w2 = IO.pipe
|
7
|
-
|
8
|
-
client_1 = IORequest::Client.new read: r1, write: w2
|
9
|
-
client_2 = IORequest::Client.new read: r2, write: w1
|
10
|
-
|
11
|
-
# Use
|
12
|
-
# Set up responders
|
13
|
-
# Authorization
|
14
|
-
client_2.respond type: 'auth' do |request|
|
15
|
-
puts "Client 2: Authorization attempt as #{request.data[:username].inspect}"
|
16
|
-
sleep 2 # Some processing
|
17
|
-
{ type: 'auth_success' }
|
18
|
-
end
|
19
|
-
|
20
|
-
# Default
|
21
|
-
client_2.respond do |request|
|
22
|
-
puts "Client 2: #{request.data.inspect}"
|
23
|
-
{ type: 'success' }
|
24
|
-
end
|
25
|
-
|
26
|
-
# Send requests
|
27
|
-
auth = false
|
28
|
-
auth_request = client_1.request(
|
29
|
-
data: { type: 'auth', username: 'mymail@example.com', password: "let's pretend password hash is here" },
|
30
|
-
sync: true
|
31
|
-
) do |response|
|
32
|
-
unless response.data[:type] == 'auth_success'
|
33
|
-
puts "Client 1: Authorization failed. Response: #{response.data.inspect}"
|
34
|
-
next
|
35
|
-
end
|
36
|
-
|
37
|
-
auth = true
|
38
|
-
# Do something
|
39
|
-
end
|
40
|
-
exit unless auth
|
41
|
-
puts 'Client 1: Authorized!'
|
42
|
-
|
43
|
-
message = client_1.request(
|
44
|
-
data: { type: 'message', message: 'Hello!' },
|
45
|
-
sync: true
|
46
|
-
) do |_response|
|
47
|
-
puts 'Client 1: Message responded'
|
48
|
-
end
|
49
|
-
|
50
|
-
# Close
|
51
|
-
r1.close
|
52
|
-
w1.close
|
53
|
-
r2.close
|
54
|
-
w2.close
|