rom-ldap 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +251 -0
- data/CONTRIBUTING.md +18 -0
- data/README.md +172 -0
- data/TODO.md +33 -0
- data/config/responses.yml +328 -0
- data/lib/dry/monitor/ldap/colorizers/default.rb +17 -0
- data/lib/dry/monitor/ldap/colorizers/rouge.rb +31 -0
- data/lib/dry/monitor/ldap/logger.rb +58 -0
- data/lib/rom-ldap.rb +1 -0
- data/lib/rom/ldap.rb +22 -0
- data/lib/rom/ldap/alias.rb +30 -0
- data/lib/rom/ldap/associations.rb +6 -0
- data/lib/rom/ldap/associations/core.rb +23 -0
- data/lib/rom/ldap/associations/many_to_many.rb +18 -0
- data/lib/rom/ldap/associations/many_to_one.rb +22 -0
- data/lib/rom/ldap/associations/one_to_many.rb +32 -0
- data/lib/rom/ldap/associations/one_to_one.rb +19 -0
- data/lib/rom/ldap/associations/self_ref.rb +35 -0
- data/lib/rom/ldap/attribute.rb +327 -0
- data/lib/rom/ldap/client.rb +185 -0
- data/lib/rom/ldap/client/authentication.rb +118 -0
- data/lib/rom/ldap/client/operations.rb +233 -0
- data/lib/rom/ldap/commands.rb +6 -0
- data/lib/rom/ldap/commands/create.rb +41 -0
- data/lib/rom/ldap/commands/delete.rb +17 -0
- data/lib/rom/ldap/commands/update.rb +35 -0
- data/lib/rom/ldap/constants.rb +193 -0
- data/lib/rom/ldap/dataset.rb +286 -0
- data/lib/rom/ldap/dataset/conversion.rb +62 -0
- data/lib/rom/ldap/dataset/dsl.rb +299 -0
- data/lib/rom/ldap/dataset/persistence.rb +44 -0
- data/lib/rom/ldap/directory.rb +126 -0
- data/lib/rom/ldap/directory/capabilities.rb +71 -0
- data/lib/rom/ldap/directory/entry.rb +200 -0
- data/lib/rom/ldap/directory/env.rb +155 -0
- data/lib/rom/ldap/directory/operations.rb +282 -0
- data/lib/rom/ldap/directory/password.rb +122 -0
- data/lib/rom/ldap/directory/root.rb +187 -0
- data/lib/rom/ldap/directory/tokenization.rb +66 -0
- data/lib/rom/ldap/directory/transactions.rb +31 -0
- data/lib/rom/ldap/directory/vendors/active_directory.rb +129 -0
- data/lib/rom/ldap/directory/vendors/apache_ds.rb +27 -0
- data/lib/rom/ldap/directory/vendors/e_directory.rb +16 -0
- data/lib/rom/ldap/directory/vendors/open_directory.rb +12 -0
- data/lib/rom/ldap/directory/vendors/open_dj.rb +25 -0
- data/lib/rom/ldap/directory/vendors/open_ldap.rb +35 -0
- data/lib/rom/ldap/directory/vendors/three_eight_nine.rb +16 -0
- data/lib/rom/ldap/directory/vendors/unknown.rb +22 -0
- data/lib/rom/ldap/dsl.rb +76 -0
- data/lib/rom/ldap/errors.rb +47 -0
- data/lib/rom/ldap/expression.rb +77 -0
- data/lib/rom/ldap/expression_encoder.rb +174 -0
- data/lib/rom/ldap/extensions.rb +50 -0
- data/lib/rom/ldap/extensions/active_support_notifications.rb +26 -0
- data/lib/rom/ldap/extensions/compatibility.rb +11 -0
- data/lib/rom/ldap/extensions/dsml.rb +165 -0
- data/lib/rom/ldap/extensions/msgpack.rb +23 -0
- data/lib/rom/ldap/extensions/optimised_json.rb +25 -0
- data/lib/rom/ldap/extensions/rails_log_subscriber.rb +38 -0
- data/lib/rom/ldap/formatter.rb +26 -0
- data/lib/rom/ldap/functions.rb +207 -0
- data/lib/rom/ldap/gateway.rb +145 -0
- data/lib/rom/ldap/ldif.rb +74 -0
- data/lib/rom/ldap/ldif/exporter.rb +77 -0
- data/lib/rom/ldap/ldif/importer.rb +95 -0
- data/lib/rom/ldap/mapper_compiler.rb +19 -0
- data/lib/rom/ldap/matchers.rb +69 -0
- data/lib/rom/ldap/message_queue.rb +7 -0
- data/lib/rom/ldap/oid.rb +101 -0
- data/lib/rom/ldap/parsers/abstract_syntax.rb +91 -0
- data/lib/rom/ldap/parsers/attribute.rb +290 -0
- data/lib/rom/ldap/parsers/filter_syntax.rb +133 -0
- data/lib/rom/ldap/pdu.rb +285 -0
- data/lib/rom/ldap/plugin/pagination.rb +145 -0
- data/lib/rom/ldap/plugins.rb +7 -0
- data/lib/rom/ldap/projection_dsl.rb +38 -0
- data/lib/rom/ldap/relation.rb +135 -0
- data/lib/rom/ldap/relation/exporting.rb +72 -0
- data/lib/rom/ldap/relation/reading.rb +461 -0
- data/lib/rom/ldap/relation/writing.rb +64 -0
- data/lib/rom/ldap/responses.rb +17 -0
- data/lib/rom/ldap/restriction_dsl.rb +45 -0
- data/lib/rom/ldap/schema.rb +123 -0
- data/lib/rom/ldap/schema/attributes_inferrer.rb +59 -0
- data/lib/rom/ldap/schema/dsl.rb +13 -0
- data/lib/rom/ldap/schema/inferrer.rb +50 -0
- data/lib/rom/ldap/schema/type_builder.rb +133 -0
- data/lib/rom/ldap/scope.rb +19 -0
- data/lib/rom/ldap/search_request.rb +249 -0
- data/lib/rom/ldap/socket.rb +210 -0
- data/lib/rom/ldap/tasks/ldap.rake +103 -0
- data/lib/rom/ldap/tasks/ldif.rake +80 -0
- data/lib/rom/ldap/transaction.rb +29 -0
- data/lib/rom/ldap/type_map.rb +88 -0
- data/lib/rom/ldap/types.rb +158 -0
- data/lib/rom/ldap/version.rb +17 -0
- data/lib/rom/plugins/relation/ldap/active_directory.rb +182 -0
- data/lib/rom/plugins/relation/ldap/auto_restrictions.rb +69 -0
- data/lib/rom/plugins/relation/ldap/e_directory.rb +27 -0
- data/lib/rom/plugins/relation/ldap/instrumentation.rb +35 -0
- data/lib/rouge/lexers/ldap.rb +72 -0
- data/lib/rouge/themes/ldap.rb +49 -0
- metadata +231 -0
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ROM
|
4
|
+
module LDAP
|
5
|
+
#
|
6
|
+
# Search Scope
|
7
|
+
#
|
8
|
+
# @see https://ldapwiki.com/wiki/LDAP%20Search%20Scopes
|
9
|
+
#
|
10
|
+
# Constrained to the entry named by baseObject.
|
11
|
+
SCOPE_BASE = 0 # "base"
|
12
|
+
# Constrained to the immediate subordinates of the entry named by baseObject.
|
13
|
+
SCOPE_ONE = 1 # "one"
|
14
|
+
# Constrained to the entry named by baseObject and to all its subordinates.
|
15
|
+
SCOPE_SUB = 2 # "sub"
|
16
|
+
|
17
|
+
SCOPES = [SCOPE_BASE, SCOPE_ONE, SCOPE_SUB].freeze
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,249 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
using ::BER
|
4
|
+
|
5
|
+
require 'rom/ldap/types'
|
6
|
+
require 'rom/ldap/expression'
|
7
|
+
|
8
|
+
module ROM
|
9
|
+
module LDAP
|
10
|
+
# The Search request is defined as follows:
|
11
|
+
#
|
12
|
+
# SearchRequest ::= [APPLICATION 3] SEQUENCE {
|
13
|
+
# baseObject LDAPDN,
|
14
|
+
# scope ENUMERATED {
|
15
|
+
# baseObject (0),
|
16
|
+
# singleLevel (1),
|
17
|
+
# wholeSubtree (2),
|
18
|
+
# ... },
|
19
|
+
# derefAliases ENUMERATED {
|
20
|
+
# neverDerefAliases (0),
|
21
|
+
# derefInSearching (1),
|
22
|
+
# derefFindingBaseObj (2),
|
23
|
+
# derefAlways (3) },
|
24
|
+
# sizeLimit INTEGER (0 .. maxInt),
|
25
|
+
# timeLimit INTEGER (0 .. maxInt),
|
26
|
+
# typesOnly BOOLEAN,
|
27
|
+
# filter Filter,
|
28
|
+
# attributes AttributeSelection }
|
29
|
+
#
|
30
|
+
# AttributeSelection ::= SEQUENCE OF selector LDAPString
|
31
|
+
# -- The LDAPString is constrained to
|
32
|
+
# -- <attributeSelector> in Section 4.5.1.8
|
33
|
+
#
|
34
|
+
# Filter ::= CHOICE {
|
35
|
+
# and [0] SET SIZE (1..MAX) OF filter Filter,
|
36
|
+
# or [1] SET SIZE (1..MAX) OF filter Filter,
|
37
|
+
# not [2] Filter,
|
38
|
+
# equalityMatch [3] AttributeValueAssertion,
|
39
|
+
# substrings [4] SubstringFilter,
|
40
|
+
# greaterOrEqual [5] AttributeValueAssertion,
|
41
|
+
# lessOrEqual [6] AttributeValueAssertion,
|
42
|
+
# present [7] AttributeDescription,
|
43
|
+
# approxMatch [8] AttributeValueAssertion,
|
44
|
+
# extensibleMatch [9] MatchingRuleAssertion,
|
45
|
+
# ... }
|
46
|
+
#
|
47
|
+
# SubstringFilter ::= SEQUENCE {
|
48
|
+
# type AttributeDescription,
|
49
|
+
# substrings SEQUENCE SIZE (1..MAX) OF substring CHOICE {
|
50
|
+
# initial [0] AssertionValue, -- can occur at most once
|
51
|
+
# any [1] AssertionValue,
|
52
|
+
# final [2] AssertionValue } -- can occur at most once
|
53
|
+
# }
|
54
|
+
#
|
55
|
+
# MatchingRuleAssertion ::= SEQUENCE {
|
56
|
+
# matchingRule [1] MatchingRuleId OPTIONAL,
|
57
|
+
# type [2] AttributeDescription OPTIONAL,
|
58
|
+
# matchValue [3] AssertionValue,
|
59
|
+
# dnAttributes [4] BOOLEAN DEFAULT FALSE }
|
60
|
+
#
|
61
|
+
#
|
62
|
+
#
|
63
|
+
#
|
64
|
+
# @see https://tools.ietf.org/html/rfc4511#section-4.5.1
|
65
|
+
#
|
66
|
+
# @api private
|
67
|
+
class SearchRequest
|
68
|
+
|
69
|
+
extend Initializer
|
70
|
+
|
71
|
+
# @see https://tools.ietf.org/html/rfc4511#section-4.5.1.7
|
72
|
+
#
|
73
|
+
# @!attribute [r] expression
|
74
|
+
# @return [Expression] Required.
|
75
|
+
option :expression, type: Types.Instance(Expression)
|
76
|
+
|
77
|
+
# @see https://tools.ietf.org/html/rfc4511#section-4.5.1.1
|
78
|
+
#
|
79
|
+
# @!attribute [r] base
|
80
|
+
# @return [String] Set to Relation default_base:
|
81
|
+
option :base, proc(&:to_s), type: Types::DN, default: -> { EMPTY_STRING }
|
82
|
+
|
83
|
+
# Defaults to only searching entries under base object.
|
84
|
+
#
|
85
|
+
# @see https://tools.ietf.org/html/rfc4511#section-4.5.1.2
|
86
|
+
#
|
87
|
+
# @!attribute [r] scope
|
88
|
+
# @return [Integer]
|
89
|
+
option :scope, type: Types::Scope, default: -> { SCOPE_SUB }
|
90
|
+
|
91
|
+
# Defaults to dereferencing both when searching and when locating the search base.
|
92
|
+
#
|
93
|
+
# @see https://tools.ietf.org/html/rfc4511#section-4.5.1.3
|
94
|
+
#
|
95
|
+
# @!attribute [r] deref
|
96
|
+
# @return [Integer]
|
97
|
+
option :deref, type: Types::Deref, default: -> { DEREF_ALWAYS }
|
98
|
+
|
99
|
+
# Defaults to all attributes '*' but not operational.
|
100
|
+
#
|
101
|
+
# @see https://tools.ietf.org/html/rfc4511#section-4.5.1.8
|
102
|
+
#
|
103
|
+
# @!attribute [r] attributes
|
104
|
+
# @return [Array<String>] Restrict attributes returned.
|
105
|
+
option :attributes, type: Types::Strings, default: -> { [WILDCARD] }
|
106
|
+
|
107
|
+
# @see https://tools.ietf.org/html/rfc4511#section-4.5.1.6
|
108
|
+
#
|
109
|
+
# @!attribute [r] attributes_only
|
110
|
+
# @return [Boolean] Do not include values.
|
111
|
+
option :attributes_only, type: Types::Strict::Bool, default: -> { false }
|
112
|
+
|
113
|
+
# @!attribute [r] reverse
|
114
|
+
# @return [Boolean]
|
115
|
+
option :reverse, type: Types::Strict::Bool, default: -> { false }
|
116
|
+
|
117
|
+
# Defaults to not paging results
|
118
|
+
#
|
119
|
+
# Adds :paged_result control to the request.
|
120
|
+
#
|
121
|
+
# @!attribute [r] paged
|
122
|
+
# @return [Boolean]
|
123
|
+
option :paged, type: Types::Strict::Bool, default: -> { false }
|
124
|
+
|
125
|
+
# ads-maxTimeLimit: 15000
|
126
|
+
# Defaults to zero, no timeout.
|
127
|
+
#
|
128
|
+
# @see https://tools.ietf.org/html/rfc4511#section-4.5.1.5
|
129
|
+
#
|
130
|
+
# @!attribute [r] timeout
|
131
|
+
# @return [Integer]
|
132
|
+
option :timeout, type: Types::Strict::Integer, default: -> { 0 }
|
133
|
+
|
134
|
+
# ads-maxSizeLimit: 200
|
135
|
+
#
|
136
|
+
# @see https://tools.ietf.org/html/rfc4511#section-4.5.1.4
|
137
|
+
#
|
138
|
+
# @!attribute [r] max
|
139
|
+
# @return [Integer]
|
140
|
+
option :max, type: Types::Strict::Integer, optional: true
|
141
|
+
|
142
|
+
# @!attribute [r] sort
|
143
|
+
# @return [Array<String>]
|
144
|
+
option :sorted, type: Types::Strict::Array, optional: true
|
145
|
+
|
146
|
+
# Search request components.
|
147
|
+
#
|
148
|
+
# @return [Array]
|
149
|
+
def parts
|
150
|
+
[
|
151
|
+
base.to_ber, # 4.5.1.1. SearchRequest.baseObject
|
152
|
+
scope.to_ber_enumerated, # 4.5.1.2. SearchRequest.scope
|
153
|
+
deref.to_ber_enumerated, # 4.5.1.3. SearchRequest.derefAliases
|
154
|
+
limit.to_ber, # 4.5.1.4. SearchRequest.sizeLimit
|
155
|
+
timeout.to_ber, # 4.5.1.5. SearchRequest.timeLimit
|
156
|
+
attributes_only.to_ber, # 4.5.1.6. SearchRequest.typesOnly
|
157
|
+
expression.to_ber, # 4.5.1.7. SearchRequest.filter
|
158
|
+
ber_attrs.to_ber_sequence # 4.5.1.8. SearchRequest.attributes
|
159
|
+
]
|
160
|
+
end
|
161
|
+
|
162
|
+
#
|
163
|
+
# Controls sent by clients are termed 'request controls', and those
|
164
|
+
# sent by servers are termed 'response controls'.
|
165
|
+
#
|
166
|
+
# Controls ::= SEQUENCE OF control Control
|
167
|
+
#
|
168
|
+
# Control ::= SEQUENCE {
|
169
|
+
# controlType LDAPOID,
|
170
|
+
# criticality BOOLEAN DEFAULT FALSE,
|
171
|
+
# controlValue OCTET STRING OPTIONAL }
|
172
|
+
#
|
173
|
+
#
|
174
|
+
# @see https://tools.ietf.org/html/rfc4511#section-4.1.11
|
175
|
+
#
|
176
|
+
# @return [Array]
|
177
|
+
def controls
|
178
|
+
ctrls = []
|
179
|
+
ctrls << build_controls(:paged_results, cookie) if paged
|
180
|
+
ctrls << build_controls(:sort_request, sort_rules) if sorted
|
181
|
+
ctrls.empty? ? nil : ctrls.to_ber_contextspecific(0)
|
182
|
+
end
|
183
|
+
|
184
|
+
private
|
185
|
+
|
186
|
+
# Set test server to only serve 200 at a time to check paging
|
187
|
+
#
|
188
|
+
# Limit to no more than 126 entries.
|
189
|
+
#
|
190
|
+
# @return [Integer]
|
191
|
+
#
|
192
|
+
# @api private
|
193
|
+
def limit
|
194
|
+
(0..126).cover?(max) ? max : 0
|
195
|
+
end
|
196
|
+
|
197
|
+
# @return [Array]
|
198
|
+
#
|
199
|
+
# @api private
|
200
|
+
def ber_attrs
|
201
|
+
Array(attributes).map { |attr| attr.to_s.to_ber }
|
202
|
+
end
|
203
|
+
|
204
|
+
# @see https://tools.ietf.org/html/rfc2696
|
205
|
+
#
|
206
|
+
# @return [Array]
|
207
|
+
#
|
208
|
+
# @api private
|
209
|
+
def cookie
|
210
|
+
[126.to_ber, EMPTY_STRING.to_ber]
|
211
|
+
# [99.to_ber, EMPTY_STRING.to_ber]
|
212
|
+
end
|
213
|
+
|
214
|
+
# Control ::= SEQUENCE {
|
215
|
+
# controlType LDAPOID,
|
216
|
+
# criticality BOOLEAN DEFAULT FALSE,
|
217
|
+
# controlValue OCTET STRING OPTIONAL }
|
218
|
+
#
|
219
|
+
# @return [String] LDAP 'control'
|
220
|
+
#
|
221
|
+
# @see PDU#result_controls
|
222
|
+
#
|
223
|
+
def build_controls(type, payload)
|
224
|
+
[
|
225
|
+
OID[type].to_ber,
|
226
|
+
false.to_ber,
|
227
|
+
payload.to_ber_sequence.to_s.to_ber
|
228
|
+
].to_ber_sequence
|
229
|
+
end
|
230
|
+
|
231
|
+
# Only uses attribute names because not all vendors have fully implemented SSS.
|
232
|
+
#
|
233
|
+
# SortKeyList ::= SEQUENCE OF SEQUENCE {
|
234
|
+
# attributeType AttributeDescription,
|
235
|
+
# orderingRule [0] MatchingRuleId OPTIONAL,
|
236
|
+
# reverseOrder [1] BOOLEAN DEFAULT FALSE }
|
237
|
+
#
|
238
|
+
#
|
239
|
+
# @see https://tools.ietf.org/html/rfc2891
|
240
|
+
# @see https://docs.ldap.com/ldap-sdk/docs/javadoc/com/unboundid/ldap/sdk/controls/ServerSideSortRequestControl.html
|
241
|
+
#
|
242
|
+
# @api private
|
243
|
+
def sort_rules
|
244
|
+
sorted.map { |attr| [attr.to_ber].to_ber_sequence }
|
245
|
+
end
|
246
|
+
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
@@ -0,0 +1,210 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'socket'
|
4
|
+
require 'rom/initializer'
|
5
|
+
|
6
|
+
module GetbyteForSSLSocket
|
7
|
+
def getbyte
|
8
|
+
byte = getc
|
9
|
+
return nil if byte.nil?
|
10
|
+
|
11
|
+
byte.ord
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module FixSSLSocketSyncClose
|
16
|
+
def close
|
17
|
+
super
|
18
|
+
io.close
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
module ROM
|
23
|
+
module LDAP
|
24
|
+
#
|
25
|
+
# Builds either TCP or UNIX.
|
26
|
+
#
|
27
|
+
# @api private
|
28
|
+
class Socket
|
29
|
+
|
30
|
+
extend Initializer
|
31
|
+
|
32
|
+
# Unix socket absolute file path
|
33
|
+
#
|
34
|
+
# @!attribute [r] path
|
35
|
+
# @return [String]
|
36
|
+
option :path, type: Types::Strict::String, reader: :private, optional: true
|
37
|
+
|
38
|
+
# Domain name or IP for TCP connection
|
39
|
+
#
|
40
|
+
# @!attribute [r] host
|
41
|
+
# @return [String]
|
42
|
+
option :host, type: Types::Strict::String, reader: :private, optional: true
|
43
|
+
|
44
|
+
# TCP port
|
45
|
+
#
|
46
|
+
# @!attribute [r] host
|
47
|
+
# @return [Integer]
|
48
|
+
option :port, type: Types::Strict::Integer, reader: :private, optional: true
|
49
|
+
|
50
|
+
# OpenSSL
|
51
|
+
# OpenSSL::SSL::SSLContext::DEFAULT_PARAMS
|
52
|
+
option :ssl, type: Types::Strict::Hash, reader: :private, optional: true
|
53
|
+
|
54
|
+
# Config
|
55
|
+
# option :timeout, type: Types::Strict::Integer, reader: :private, default: -> { 10 }
|
56
|
+
|
57
|
+
option :read_timeout, type: Types::Strict::Integer, reader: :private, default: -> { 20 }
|
58
|
+
|
59
|
+
# Timeout limit in seconds when writing to the socket
|
60
|
+
#
|
61
|
+
# @!attribute [r] write_timeout
|
62
|
+
# @return [Integer] default: 10
|
63
|
+
option :write_timeout, type: Types::Strict::Integer, reader: :private, default: -> { 10 }
|
64
|
+
|
65
|
+
# Retry limit when establishing connection
|
66
|
+
#
|
67
|
+
# @!attribute [r] retry_count
|
68
|
+
# @return [Integer] default: 3
|
69
|
+
option :retry_count, type: Types::Strict::Integer, reader: :private, default: -> { 3 }
|
70
|
+
|
71
|
+
#
|
72
|
+
#
|
73
|
+
# @!attribute [r] retry_count
|
74
|
+
# @return [Boolean] default: true
|
75
|
+
option :keep_alive, type: Types::Strict::Bool, reader: :private, default: -> { true }
|
76
|
+
|
77
|
+
#
|
78
|
+
#
|
79
|
+
# @!attribute [r] buffered
|
80
|
+
# @return [Boolean] default: true
|
81
|
+
option :buffered, type: Types::Strict::Bool, reader: :private, default: -> { true }
|
82
|
+
|
83
|
+
# @return [::Socket, ::OpenSSL::SSL::SSLSocket]
|
84
|
+
#
|
85
|
+
def call
|
86
|
+
socket.do_not_reverse_lookup = true
|
87
|
+
socket.sync = buffered
|
88
|
+
socket.setsockopt(:SOCKET, :KEEPALIVE, keep_alive)
|
89
|
+
socket.setsockopt(:TCP, :NODELAY, buffered) unless path
|
90
|
+
|
91
|
+
connect!
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
# @return [::Socket]
|
97
|
+
#
|
98
|
+
# @raise [ConnectionError]
|
99
|
+
#
|
100
|
+
def connect!
|
101
|
+
@counter ||= 1
|
102
|
+
|
103
|
+
if ssl
|
104
|
+
require 'openssl'
|
105
|
+
|
106
|
+
ctx = OpenSSL::SSL::SSLContext.new
|
107
|
+
ctx.set_params(ssl)
|
108
|
+
@socket = OpenSSL::SSL::SSLSocket.new(socket, ctx)
|
109
|
+
# socket.extend(GetbyteForSSLSocket) unless socket.respond_to?(:getbyte)
|
110
|
+
# socket.extend(FixSSLSocketSyncClose)
|
111
|
+
socket.connect_nonblock
|
112
|
+
else
|
113
|
+
socket.connect_nonblock(sockaddr)
|
114
|
+
end
|
115
|
+
|
116
|
+
socket
|
117
|
+
rescue Errno::EISCONN
|
118
|
+
socket
|
119
|
+
rescue IO::WaitWritable
|
120
|
+
# OpenSSL::SSL::SSLErrorWaitWritable
|
121
|
+
if writable?
|
122
|
+
connect!
|
123
|
+
else
|
124
|
+
disconnect!
|
125
|
+
raise ConnectionError, "Connection write timeout - #{host}:#{port}"
|
126
|
+
end
|
127
|
+
rescue IO::WaitReadable
|
128
|
+
if readable?
|
129
|
+
@counter += 1
|
130
|
+
retry unless @counter > retry_count
|
131
|
+
else
|
132
|
+
raise ConnectionError, "Connection read timeout - #{host}:#{port}"
|
133
|
+
end
|
134
|
+
rescue Errno::EADDRNOTAVAIL
|
135
|
+
raise ConnectionError, "Host or port is invalid - #{host}:#{port}"
|
136
|
+
rescue SocketError
|
137
|
+
raise ConnectionError, "Host could not be resolved - #{host}:#{port}"
|
138
|
+
rescue Errno::ENOENT
|
139
|
+
raise ConnectionError, "Path to unix socket is invalid - #{path}"
|
140
|
+
rescue Errno::EHOSTDOWN
|
141
|
+
raise ConnectionError, "Server is down - #{host}:#{port}"
|
142
|
+
rescue Errno::ECONNREFUSED
|
143
|
+
raise ConnectionError, "Connection refused - #{host}:#{port}"
|
144
|
+
rescue Errno::EAFNOSUPPORT
|
145
|
+
raise ConnectionError, "Connection is not supported - #{host}:#{port}"
|
146
|
+
rescue
|
147
|
+
disconnect!
|
148
|
+
raise ConnectionError, "Connection failed - #{host}:#{port}"
|
149
|
+
end
|
150
|
+
|
151
|
+
#
|
152
|
+
#
|
153
|
+
# @return [::Socket]
|
154
|
+
#
|
155
|
+
def socket
|
156
|
+
@socket ||= ::Socket.new((path ? :UNIX : :INET), :STREAM)
|
157
|
+
end
|
158
|
+
|
159
|
+
# @return [NilClass]
|
160
|
+
#
|
161
|
+
def disconnect!
|
162
|
+
socket.close
|
163
|
+
@socket = nil
|
164
|
+
end
|
165
|
+
|
166
|
+
# IPV4 or UNIX socket address
|
167
|
+
#
|
168
|
+
# @return [String] ASCII-8BIT
|
169
|
+
#
|
170
|
+
# @api private
|
171
|
+
def sockaddr
|
172
|
+
if addrinfo.unix?
|
173
|
+
::Socket.pack_sockaddr_un(addrinfo.unix_path)
|
174
|
+
|
175
|
+
elsif addrinfo.ipv4?
|
176
|
+
::Socket.pack_sockaddr_in(addrinfo.ip_port, addrinfo.ip_address)
|
177
|
+
|
178
|
+
elsif addrinfo.ipv6_loopback?
|
179
|
+
::Socket.pack_sockaddr_in(addrinfo.ip_port, '127.0.0.1')
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
# Performs DNS lookup
|
184
|
+
#
|
185
|
+
# @return [Addrinfo]
|
186
|
+
#
|
187
|
+
# @api private
|
188
|
+
def addrinfo
|
189
|
+
return Addrinfo.unix(path) if path
|
190
|
+
|
191
|
+
Addrinfo.tcp(host, port)
|
192
|
+
end
|
193
|
+
|
194
|
+
# @return [TrueClass,FalseClass]
|
195
|
+
#
|
196
|
+
# @api private
|
197
|
+
def writable?
|
198
|
+
!IO.select(nil, [socket], nil, write_timeout).nil?
|
199
|
+
end
|
200
|
+
|
201
|
+
# @return [TrueClass,FalseClass]
|
202
|
+
#
|
203
|
+
# @api private
|
204
|
+
def readable?
|
205
|
+
!IO.select([socket], nil, nil, read_timeout).nil?
|
206
|
+
end
|
207
|
+
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|