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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9a78b709d9b064cd44737d76a24c27f0df37e9f0d5897829043e9d884287219d
4
- data.tar.gz: a2350c480d0f9cc883526c47021505bfd511ffa12622436ac5bafbe4d050c6df
3
+ metadata.gz: 3129d25d05cbc0292eb186416db04f305f3c8fa09c525daafe1926ea2c833a76
4
+ data.tar.gz: 417380ff03d49890bd4161a1db3811c3e4c105c5357082579801318aadb828cf
5
5
  SHA512:
6
- metadata.gz: b1cc3c89258eaa0d4511fdcd1dc17cae4b82061ebdb747732a8cc60467a9a39c3414a337f6f85acc4dd6768f16bc45f9fe037405e5e7aeb19f0723deeb01759a
7
- data.tar.gz: eb6918fb66bbaec142dd88abf4c00b69d5204fb88b03f00532e52d12d8a03822275efb3cac4584177a8f9ab40bc549bc5dff09977410f3cf6f99435f594e41ad
6
+ metadata.gz: e20f44b5bd79b67d7b0d33c5edd16ba34321f1815bf3641c7bf986798e9bfc0ed3495015625b58bc541385fb4b6f35e16c080eac1e9c92404b35db255c815d23
7
+ data.tar.gz: 3638cb26446495bf95154d1e3d836b2b5660023491bd53b45175fb8701012d5de6fc3e5832381f4a0fe165b3858bc52056f8087c8a8026f73c8f8c096e5683ae
data/Gemfile CHANGED
@@ -11,3 +11,7 @@ gem 'json', '~> 2.3'
11
11
  gem 'timeout', '~> 0.1.0'
12
12
 
13
13
  gem 'logger', '~> 1.4'
14
+
15
+ gem 'openssl', '~> 2.2'
16
+
17
+ gem 'pry', '~> 0.13.1'
@@ -4,12 +4,5 @@
4
4
  require 'bundler/setup'
5
5
  require 'io_request'
6
6
 
7
- # You can add fixtures and/or initialization code here to make experimenting
8
- # with your gem easier. You can also use a different console, if you like.
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__)
@@ -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
@@ -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 message is received from outside.
14
- # @param to [Utility::ExtendedID, String, nil] if message is response, it should include integer
15
- # of original request.
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
@@ -2,5 +2,5 @@
2
2
 
3
3
  module IORequest
4
4
  # Gem version.
5
- VERSION = '2.0.0'
5
+ VERSION = '2.1.0'
6
6
  end
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.0.0
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
@@ -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