tcp-client 0.9.1 → 0.10.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.
@@ -2,7 +2,8 @@
2
2
 
3
3
  class TCPClient
4
4
  #
5
- # Raised when a SSL connection should be establshed but the OpenSSL gem is not available.
5
+ # Raised when a SSL connection should be established but the OpenSSL gem is
6
+ # not available.
6
7
  #
7
8
  class NoOpenSSLError < RuntimeError
8
9
  def initialize
@@ -11,7 +12,8 @@ class TCPClient
11
12
  end
12
13
 
13
14
  #
14
- # Raised when a method requires a callback block but no such block is specified.
15
+ # Raised when a method requires a callback block but no such block is
16
+ # specified.
15
17
  #
16
18
  class NoBlockGivenError < ArgumentError
17
19
  def initialize
@@ -20,9 +22,12 @@ class TCPClient
20
22
  end
21
23
 
22
24
  #
23
- # Raised when a an invalid timeout value was specified.
25
+ # Raised when an invalid timeout value was specified.
24
26
  #
25
27
  class InvalidDeadLineError < ArgumentError
28
+ #
29
+ # @param timeout [Object] the invalid value
30
+ #
26
31
  def initialize(timeout)
27
32
  super("invalid deadline - #{timeout}")
28
33
  end
@@ -32,6 +37,9 @@ class TCPClient
32
37
  # Raised by {Configuration} when an undefined attribute should be set.
33
38
  #
34
39
  class UnknownAttributeError < ArgumentError
40
+ #
41
+ # @param attribute [Object] the undefined attribute
42
+ #
35
43
  def initialize(attribute)
36
44
  super("unknown attribute - #{attribute}")
37
45
  end
@@ -41,6 +49,9 @@ class TCPClient
41
49
  # Raised when a given timeout exception parameter is not an exception class.
42
50
  #
43
51
  class NotAnExceptionError < TypeError
52
+ #
53
+ # @param object [Object] the invalid object
54
+ #
44
55
  def initialize(object)
45
56
  super("exception class required - #{object.inspect}")
46
57
  end
@@ -49,15 +60,18 @@ class TCPClient
49
60
  #
50
61
  # Base exception class for all network related errors.
51
62
  #
52
- # Will be raised for any system level network error when {Configuration.normalize_network_errors} is configured.
63
+ # Will be raised for any system level network error when
64
+ # {Configuration.normalize_network_errors} is configured.
53
65
  #
54
- # You should catch this exception class when you like to handle any relevant {TCPClient} error.
66
+ # You should catch this exception class when you like to handle any relevant
67
+ # {TCPClient} error.
55
68
  #
56
69
  class NetworkError < StandardError
57
70
  end
58
71
 
59
72
  #
60
- # Raised when a {TCPClient} instance should read/write from/to the network but is not connected.
73
+ # Raised when a {TCPClient} instance should read/write from/to the network
74
+ # but is not connected.
61
75
  #
62
76
  class NotConnectedError < NetworkError
63
77
  def initialize
@@ -68,23 +82,26 @@ class TCPClient
68
82
  #
69
83
  # Base exception class for a detected timeout.
70
84
  #
71
- # You should catch this exception class when you like to handle any timeout error.
85
+ # You should catch this exception class when you like to handle any timeout
86
+ # error.
72
87
  #
73
88
  class TimeoutError < NetworkError
74
89
  #
75
90
  # Initializes the instance with an optional message.
76
91
  #
77
- # the message will be generated from {#action} when not specified.
92
+ # The message will be generated from {#action} when not specified.
93
+ #
78
94
  # @overload initialize
79
95
  # @overload initialize(message)
80
96
  #
81
- # @param message [String, #to_s] the error message
97
+ # @param message [#to_s] the error message
82
98
  #
83
99
  def initialize(message = nil)
84
100
  super(message || "unable to #{action} in time")
85
101
  end
86
102
 
87
103
  #
104
+ # @attribute [r] action
88
105
  # @return [Symbol] the action which timed out
89
106
  #
90
107
  def action
@@ -97,7 +114,8 @@ class TCPClient
97
114
  #
98
115
  class ConnectTimeoutError < TimeoutError
99
116
  #
100
- # @return [Symbol] the action which timed out: +:connect+
117
+ # @attribute [r] action
118
+ # @return [Symbol] the action which timed out: `:connect`
101
119
  #
102
120
  def action
103
121
  :connect
@@ -105,11 +123,12 @@ class TCPClient
105
123
  end
106
124
 
107
125
  #
108
- # Raised by default whenever a {TCPClient.read} timed out.
126
+ # Raised by default whenever a {TCPClient#read} timed out.
109
127
  #
110
128
  class ReadTimeoutError < TimeoutError
111
129
  #
112
- # @return [Symbol] the action which timed out: +:read+
130
+ # @attribute [r] action
131
+ # @return [Symbol] the action which timed out: :read`
113
132
  #
114
133
  def action
115
134
  :read
@@ -117,11 +136,12 @@ class TCPClient
117
136
  end
118
137
 
119
138
  #
120
- # Raised by default whenever a {TCPClient.write} timed out.
139
+ # Raised by default whenever a {TCPClient#write} timed out.
121
140
  #
122
141
  class WriteTimeoutError < TimeoutError
123
142
  #
124
- # @return [Symbol] the action which timed out: +:write+
143
+ # @attribute [r] action
144
+ # @return [Symbol] the action which timed out: `:write`
125
145
  #
126
146
  def action
127
147
  :write
@@ -13,25 +13,30 @@ module IOWithDeadlineMixin # :nodoc:
13
13
  end
14
14
  end
15
15
 
16
- def read_with_deadline(bytes_to_read, deadline, exception)
16
+ def read_with_deadline(nbytes, deadline, exception)
17
17
  raise(exception) unless deadline.remaining_time
18
- if bytes_to_read.nil?
19
- return(
20
- with_deadline(deadline, exception) do
21
- read_nonblock(65_536, exception: false)
22
- end
23
- )
18
+ return fetch_avail(deadline, exception) if nbytes.nil?
19
+ return ''.b if nbytes.zero?
20
+ @buf ||= ''.b
21
+ while @buf.bytesize < nbytes
22
+ read = fetch_next(deadline, exception) and next @buf << read
23
+ close
24
+ break
24
25
  end
25
- result = ''.b
26
- while result.bytesize < bytes_to_read
27
- read =
28
- with_deadline(deadline, exception) do
29
- read_nonblock(bytes_to_read - result.bytesize, exception: false)
30
- end
31
- next result += read if read
26
+ fetch_buffer_slice(nbytes)
27
+ end
28
+
29
+ def readto_with_deadline(sep, deadline, exception)
30
+ raise(exception) unless deadline.remaining_time
31
+ @buf ||= ''.b
32
+ while (index = @buf.index(sep)).nil?
33
+ read = fetch_next(deadline, exception) and next @buf << read
32
34
  close
33
35
  break
34
36
  end
37
+ index = @buf.index(sep) and return fetch_buffer_slice(index + sep.bytesize)
38
+ result = @buf
39
+ @buf = nil
35
40
  result
36
41
  end
37
42
 
@@ -44,12 +49,37 @@ module IOWithDeadlineMixin # :nodoc:
44
49
  with_deadline(deadline, exception) do
45
50
  write_nonblock(data, exception: false)
46
51
  end
47
- result += written
48
- return result if result >= size
52
+ (result += written) >= size and return result
49
53
  data = data.byteslice(written, data.bytesize - written)
50
54
  end
51
55
  end
52
56
 
57
+ private
58
+
59
+ def fetch_avail(deadline, exception)
60
+ if @buf.nil?
61
+ result = fetch_next(deadline, exception) and return result
62
+ close
63
+ return ''.b
64
+ end
65
+ result = @buf
66
+ @buf = nil
67
+ result
68
+ end
69
+
70
+ def fetch_buffer_slice(size)
71
+ result = @buf.byteslice(0, size)
72
+ rest = @buf.bytesize - result.bytesize
73
+ @buf = rest.zero? ? nil : @buf.byteslice(size, rest)
74
+ result
75
+ end
76
+
77
+ def fetch_next(deadline, exception)
78
+ with_deadline(deadline, exception) do
79
+ read_nonblock(65_536, exception: false)
80
+ end
81
+ end
82
+
53
83
  module ViaWaitMethod
54
84
  private def with_deadline(deadline, exception)
55
85
  loop do
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class TCPClient
4
- #
5
- # The current gem version.
6
- #
7
- VERSION = '0.9.1'
4
+ # The current version number.
5
+ VERSION = '0.10.0'
8
6
  end
data/lib/tcp-client.rb CHANGED
@@ -15,71 +15,85 @@ require_relative 'tcp-client/version'
15
15
  # All connect/read/write actions can be monitored to ensure that all actions
16
16
  # terminate before given time limits - or raise an exception.
17
17
  #
18
- # @example - request to Google.com and limit all network interactions to 1.5 seconds
19
- # TCPClient.with_deadline(1.5, 'www.google.com:443') do |client|
20
- # client.write("GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n")
21
- # client.read(12)
22
- # end
23
- # # => "HTTP/1.1 200"
18
+ # @example request to Google.com and limit network interactions to 1.5 seconds
19
+ # # create a configuration to use at least TLS 1.2
20
+ # cfg = TCPClient::Configuration.create(ssl_params: {min_version: :TLS1_2})
24
21
  #
22
+ # response =
23
+ # TCPClient.with_deadline(1.5, 'www.google.com:443', cfg) do |client|
24
+ # client.write("GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n") #=> 40
25
+ # client.readline("\r\n\r\n") #=> see response
26
+ # end
27
+ # # response contains the returned message and header
25
28
  #
26
29
  class TCPClient
27
30
  #
28
31
  # Creates a new instance which is connected to the server on the given
29
- # address and uses the given or the {.default_configuration}.
32
+ # `address`.
33
+ #
34
+ # If no `configuration` is given, the {.default_configuration} will be used.
35
+ #
36
+ # @overload open(address, configuration = nil)
37
+ # @yieldparam client [TCPClient] the connected client
38
+ #
39
+ # @return [Object] the block result
40
+ #
41
+ # @overload open(address, configuration = nil)
42
+ # @return [TCPClient] the connected client
30
43
  #
31
44
  # If an optional block is given, then the block's result is returned and the
32
45
  # connection will be closed when the block execution ends.
33
- # This can be used to create an ad-hoc connection which is garanteed to be
46
+ # This can be used to create an ad-hoc connection which is guaranteed to be
34
47
  # closed.
35
48
  #
36
- # If no block is giiven the connected client instance is returned.
49
+ # If no block is given the connected client instance is returned.
37
50
  # This can be used as a shorthand to create & connect a client.
38
51
  #
39
- # @param address [Address, String, Addrinfo, Integer] the address to connect to, see {Address#initialize} for valid formats
40
- # @param configuration [Configuration] the {Configuration} to be used for this instance
41
- #
42
- # @yieldparam client [TCPClient] the connected client
43
- # @yieldreturn [Object] any result
44
- #
45
- # @return [Object, TCPClient] the block result or the connected client
52
+ # @param address [Address, String, Addrinfo, Integer] the target address see
53
+ # {Address#initialize} for valid formats
54
+ # @param configuration [Configuration] the {Configuration} to be used for
55
+ # the new instance
46
56
  #
47
57
  # @see #connect
48
58
  #
49
59
  def self.open(address, configuration = nil)
50
60
  client = new
51
- client.connect(Address.new(address), configuration)
61
+ client.connect(address, configuration)
52
62
  block_given? ? yield(client) : client
53
63
  ensure
54
64
  client.close if block_given?
55
65
  end
56
66
 
57
67
  #
58
- # Yields a new instance which is connected to the server on the given
59
- # address and uses the given or the {.default_configuration}.
60
- # It ensures to close the connection when the block execution ends.
61
- # It also limits all {#read} and {#write} actions within the block to a given
62
- # time.
68
+ # Yields an instance which is connected to the server on the given
69
+ # `address`. It limits all {#read} and {#write} actions within the block to
70
+ # the given time.
63
71
  #
64
- # This can be used to create an ad-hoc connection which is garanteed to be
65
- # closed and which read/write calls should not last longer than the timeout
66
- # limit.
72
+ # It ensures to close the connection when the block execution ends and returns
73
+ # the block's result.
67
74
  #
68
- # @param timeout [Numeric] maximum time in seconds for all {#read} and {#write} calls within the block
69
- # @param address [Address, String, Addrinfo, Integer] the address to connect to, see {Address#initialize} for valid formats
70
- # @param configuration [Configuration] the {Configuration} to be used for this instance
75
+ # This can be used to create an ad-hoc connection which is guaranteed to be
76
+ # closed and which {#read}/{#write} call sequence should not last longer than
77
+ # the `timeout` seconds.
78
+ #
79
+ # If no `configuration` is given, the {.default_configuration} will be used.
80
+ #
81
+ # @param timeout [Numeric] maximum time in seconds for all {#read} and
82
+ # {#write} calls within the block
83
+ # @param address [Address, String, Addrinfo, Integer] the target address see
84
+ # {Address#initialize} for valid formats
85
+ # @param configuration [Configuration] the {Configuration} to be used for
86
+ # the instance
71
87
  #
72
88
  # @yieldparam client [TCPClient] the connected client
73
- # @yieldreturn [Object] any result
74
89
  #
75
- # @return [Object] the block result
90
+ # @return [Object] the block's result
76
91
  #
77
92
  # @see #with_deadline
78
93
  #
79
94
  def self.with_deadline(timeout, address, configuration = nil)
80
95
  client = nil
81
96
  raise(NoBlockGivenError) unless block_given?
82
- address = Address.new(address)
83
97
  client = new
84
98
  client.with_deadline(timeout) do
85
99
  yield(client.connect(address, configuration))
@@ -89,89 +103,168 @@ class TCPClient
89
103
  end
90
104
 
91
105
  #
92
- # @return [Address] the address used for this client
106
+ # @return [Address] the address used by this client instance
93
107
  #
94
108
  attr_reader :address
95
109
 
96
110
  #
97
- # @return [Configuration] the configuration used by this client.
111
+ # @return [Configuration] the configuration used by this client instance
98
112
  #
99
113
  attr_reader :configuration
100
114
 
101
115
  #
102
- # @attribute [r] closed?
103
- # @return [Boolean] true when the connection is closed, false when connected
116
+ # @!parse attr_reader :closed?
117
+ # @return [Boolean] whether the connection is closed
104
118
  #
105
119
  def closed?
106
120
  @socket.nil? || @socket.closed?
107
121
  end
108
122
 
109
123
  #
110
- # @return [String] the currently used address as text.
124
+ # Close the current connection if connected.
111
125
  #
112
- # @see Address#to_s
126
+ # @return [TCPClient] itself
113
127
  #
114
- def to_s
115
- @address&.to_s || ''
128
+ def close
129
+ @socket&.close
130
+ self
131
+ rescue *NETWORK_ERRORS
132
+ self
133
+ ensure
134
+ @socket = @deadline = nil
116
135
  end
117
136
 
118
137
  #
119
- # Establishes a new connection to a given address.
138
+ # Establishes a new connection to a server on given `address`.
139
+ #
140
+ # It accepts a connection-specific `configuration` or uses the
141
+ # {.default_configuration}.
120
142
  #
121
- # It accepts a connection-specific configuration or uses the global {.default_configuration}. The {#configuration} used by this instance will
122
- # be a copy of the configuration used for this method call. This allows to
123
- # configure the behavior per connection.
143
+ # The optional `timeout` and `exception` parameters allow to override the
144
+ # `connect_timeout` and `connect_timeout_error` values.
124
145
  #
125
- # @param address [Address, String, Addrinfo, Integer] the address to connect to, see {Address#initialize} for valid formats
126
- # @param configuration [Configuration] the {Configuration} to be used for this instance
127
- # @param timeout [Numeric] maximum time in seconds to read; used to override the configuration's +connect_timeout+.
128
- # @param exception [Class] exception class to be used when the read timeout reached; used to override the configuration's +connect_timeout_error+.
146
+ # @param address [Address, String, Addrinfo, Integer] the target address, see
147
+ # {Address#initialize} for valid formats
148
+ # @param configuration [Configuration] the {Configuration} to be used for
149
+ # this instance
150
+ # @param timeout [Numeric] maximum time in seconds to connect
151
+ # @param exception [Class<Exception>] exception class to be used when the
152
+ # connect timeout reached
129
153
  #
130
- # @return [self]
154
+ # @return [TCPClient] itself
131
155
  #
132
156
  # @raise {NoOpenSSLError} if SSL should be used but OpenSSL is not avail
133
157
  #
158
+ # @see NetworkError
159
+ #
134
160
  def connect(address, configuration = nil, timeout: nil, exception: nil)
135
161
  close if @socket
136
- @address = Address.new(address)
137
162
  @configuration = (configuration || Configuration.default).dup
138
163
  raise(NoOpenSSLError) if @configuration.ssl? && !defined?(SSLSocket)
164
+ @address = stem_errors { Address.new(address) }
139
165
  @socket = create_socket(timeout, exception)
140
166
  self
141
167
  end
142
168
 
143
169
  #
144
- # Close the current connection.
170
+ # Flushes all internal buffers (write all buffered data).
145
171
  #
146
- # @return [self]
172
+ # @return [TCPClient] itself
147
173
  #
148
- def close
149
- @socket&.close
150
- self
151
- rescue *NETWORK_ERRORS
174
+ def flush
175
+ stem_errors { @socket&.flush }
152
176
  self
153
- ensure
154
- @socket = @deadline = nil
155
177
  end
156
178
 
157
179
  #
158
- # Executes a block with a given overall timeout.
180
+ # Read the given `nbytes` or the next available buffer from server.
181
+ #
182
+ # The optional `timeout` and `exception` parameters allow to override the
183
+ # `read_timeout` and `read_timeout_error` values of the used {#configuration}.
184
+ #
185
+ # @param nbytes [Integer] the number of bytes to read
186
+ # @param timeout [Numeric] maximum time in seconds to read
187
+ # @param exception [Class<Exception>] exception class to be used when the
188
+ # read timeout reached
189
+ #
190
+ # @return [String] the read buffer
191
+ #
192
+ # @raise [NotConnectedError] if {#connect} was not called before
193
+ #
194
+ # @see NetworkError
195
+ #
196
+ def read(nbytes = nil, timeout: nil, exception: nil)
197
+ raise(NotConnectedError) if closed?
198
+ deadline = create_deadline(timeout, configuration.read_timeout)
199
+ return stem_errors { @socket.read(nbytes) } unless deadline.valid?
200
+ exception ||= configuration.read_timeout_error
201
+ stem_errors(exception) do
202
+ @socket.read_with_deadline(nbytes, deadline, exception)
203
+ end
204
+ end
205
+
206
+ #
207
+ # Reads the next line from server.
208
+ #
209
+ # The standard record separator is used as `separator`.
159
210
  #
160
- # When you like to ensure that a complete read/write communication sequence
161
- # with the server is finished before a given amount of time you can use this
162
- # method to define such a deadline.
211
+ # The optional `timeout` and `exception` parameters allow to override the
212
+ # `read_timeout` and `read_timeout_error` values of the used {#configuration}.
163
213
  #
164
- # @example - ensure to send a welcome message and receive a 64 byte answer from server
214
+ # @param separator [String] the line separator to be used
215
+ # @param timeout [Numeric] maximum time in seconds to read
216
+ # @param exception [Class<Exception>] exception class to be used when the
217
+ # read timeout reached
218
+ #
219
+ # @return [String] the read line
220
+ #
221
+ # @raise [NotConnectedError] if {#connect} was not called before
222
+ #
223
+ # @see NetworkError
224
+ #
225
+ def readline(separator = $/, chomp: false, timeout: nil, exception: nil)
226
+ raise(NotConnectedError) if closed?
227
+ deadline = create_deadline(timeout, configuration.read_timeout)
228
+ unless deadline.valid?
229
+ return stem_errors { @socket.readline(separator, chomp: chomp) }
230
+ end
231
+ exception ||= configuration.read_timeout_error
232
+ line =
233
+ stem_errors(exception) do
234
+ @socket.readto_with_deadline(separator, deadline, exception)
235
+ end
236
+ chomp ? line.chomp : line
237
+ end
238
+
239
+ #
240
+ # @return [String] the currently used address as text.
241
+ #
242
+ # @see Address#to_s
243
+ #
244
+ def to_s
245
+ @address&.to_s || ''
246
+ end
247
+
248
+ #
249
+ # Executes a block with a given overall time limit.
250
+ #
251
+ # When you like to ensure that a complete {#read}/{#write} communication
252
+ # sequence with the server is finished before a given amount of time you use
253
+ # this method.
254
+ #
255
+ # @example ensure to send SMTP welcome message and receive a 4 byte answer
165
256
  # answer = client.with_deadline(2.5) do
166
- # client.write('Helo')
167
- # client.read(64)
257
+ # client.write('HELO')
258
+ # client.read(4)
168
259
  # end
260
+ # # answer is EHLO when server speaks fluent SMPT
169
261
  #
170
- # @param timeout [Numeric] maximum time in seconds for all {#read} and {#write} calls within the block
262
+ # @param timeout [Numeric] maximum time in seconds for all {#read} and
263
+ # {#write} calls within the block
171
264
  #
172
265
  # @yieldparam client [TCPClient] self
173
266
  #
174
- # @return [Object] result of the given block
267
+ # @return [Object] the block's result
175
268
  #
176
269
  # @raise [NoBlockGivenError] if the block is missing
177
270
  #
@@ -186,37 +279,23 @@ class TCPClient
186
279
  end
187
280
 
188
281
  #
189
- # Read the given nbytes or the next available buffer from server.
282
+ # Writes the given `messages` to the server.
190
283
  #
191
- # @param nbytes [Integer] the number of bytes to read
192
- # @param timeout [Numeric] maximum time in seconds to read; used to override the configuration's +read_timeout+.
193
- # @param exception [Class] exception class to be used when the read timeout reached; used to override the configuration's +read_timeout_error+.
284
+ # The optional `timeout` and `exception` parameters allow to override the
285
+ # `write_timeout` and `write_timeout_error` values of the used
286
+ # {#configuration}.
194
287
  #
195
- # @return [String] buffer read
196
- #
197
- # @raise [NotConnectedError] if {#connect} was not called before
198
- #
199
- def read(nbytes = nil, timeout: nil, exception: nil)
200
- raise(NotConnectedError) if closed?
201
- deadline = create_deadline(timeout, configuration.read_timeout)
202
- return stem_errors { @socket.read(nbytes) } unless deadline.valid?
203
- exception ||= configuration.read_timeout_error
204
- stem_errors(exception) do
205
- @socket.read_with_deadline(nbytes, deadline, exception)
206
- end
207
- end
208
-
209
- #
210
- # Write the given messages to the server.
211
- #
212
- # @param messages [Array<String>] messages to write
213
- # @param timeout [Numeric] maximum time in seconds to read; used to override the configuration's +write_timeout+.
214
- # @param exception [Class] exception class to be used when the read timeout reached; used to override the configuration's +write_timeout_error+.
288
+ # @param messages [Array<String>] one or more messages to write
289
+ # @param timeout [Numeric] maximum time in seconds to write
290
+ # @param exception [Class<Exception>] exception class to be used when the
291
+ # write timeout reached
215
292
  #
216
293
  # @return [Integer] bytes written
217
294
  #
218
295
  # @raise [NotConnectedError] if {#connect} was not called before
219
296
  #
297
+ # @see NetworkError
298
+ #
220
299
  def write(*messages, timeout: nil, exception: nil)
221
300
  raise(NotConnectedError) if closed?
222
301
  deadline = create_deadline(timeout, configuration.write_timeout)
@@ -229,16 +308,6 @@ class TCPClient
229
308
  end
230
309
  end
231
310
 
232
- #
233
- # Flush all internal buffers (write all through).
234
- #
235
- # @return [self]
236
- #
237
- def flush
238
- stem_errors { @socket&.flush }
239
- self
240
- end
241
-
242
311
  private
243
312
 
244
313
  def create_deadline(timeout, default)
data/rakefile.rb CHANGED
@@ -7,7 +7,12 @@ require 'yard'
7
7
 
8
8
  $stdout.sync = $stderr.sync = true
9
9
 
10
- CLOBBER << 'prj' << 'doc'
10
+ CLEAN << 'prj' << 'doc'
11
+
12
+ CLOBBER << '.yardoc'
13
+
11
14
  task(:default) { exec('rake --tasks') }
15
+
12
16
  RSpec::Core::RakeTask.new { |task| task.ruby_opts = %w[-w] }
17
+
13
18
  YARD::Rake::YardocTask.new { |task| task.stats_options = %w[--list-undoc] }
data/sample/google_ssl.rb CHANGED
@@ -18,8 +18,11 @@ cfg =
18
18
  # - limit all network interactions to 1.5 seconds
19
19
  # - use the Configuration cfg
20
20
  # - send a simple HTTP get request
21
- # - read 12 byte: "HTTP/1.1 " + 3 byte HTTP status code
22
- TCPClient.with_deadline(1.5, 'www.google.com:443', cfg) do |client|
23
- p client.write("GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n")
24
- p client.read(12)
25
- end
21
+ # - read the returned message and headers
22
+ response =
23
+ TCPClient.with_deadline(1.5, 'www.google.com:443', cfg) do |client|
24
+ client.write("GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n") #=> 40
25
+ client.readline("\r\n\r\n") #=> see response
26
+ end
27
+
28
+ puts(response)