11# frozen_string_literal: true
22
3+ require "forwardable"
4+
35module Net
46 class IMAP
57 module SASL
@@ -8,18 +10,28 @@ module SASL
810 #
911 # TODO: use with more clients, to verify the API can accommodate them.
1012 #
11- # An abstract base class for implementing a SASL authentication exchange.
12- # Different clients will each have their own adapter subclass, overridden
13- # to match their needs.
13+ # Represents the client to a SASL::AuthenticationExchange. By default,
14+ # most methods simply delegate to #client. Clients should subclass
15+ # SASL::ClientAdapter and override methods as needed to match the
16+ # semantics of this API to their API.
1417 #
15- # Although the default implementations _may_ be sufficient, subclasses
16- # will probably need to override some methods. Additionally, subclasses
17- # may need to include a protocol adapter mixin, if the default
18+ # Subclasses should also include a protocol adapter mixin when the default
1819 # ProtocolAdapters::Generic isn't sufficient.
20+ #
21+ # === Protocol Requirements
22+ #
23+ # {RFC4422 §4}[https://www.rfc-editor.org/rfc/rfc4422.html#section-4]
24+ # lists requirements for protocol specifications to offer SASL. Where
25+ # possible, ClientAdapter delegates the handling of these requirements to
26+ # SASL::ProtocolAdapters.
1927 class ClientAdapter
28+ extend Forwardable
29+
2030 include ProtocolAdapters ::Generic
2131
2232 # The client that handles communication with the protocol server.
33+ #
34+ # Most ClientAdapter methods are simply delegated to #client by default.
2335 attr_reader :client
2436
2537 # +command_proc+ can used to avoid exposing private methods on #client.
@@ -51,15 +63,17 @@ def initialize(client, &command_proc)
5163 # AuthenticationExchange.authenticate.
5264 def authenticate ( ...) AuthenticationExchange . authenticate ( self , ...) end
5365
66+ ##
67+ # method: sasl_ir_capable?
5468 # Do the protocol, server, and client all support an initial response?
55- #
56- # By default, this simply delegates to <tt>client.sasl_ir_capable?</tt>.
57- def sasl_ir_capable? ; client . sasl_ir_capable? end
69+ def_delegator :client , :sasl_ir_capable?
5870
59- # Does the server advertise support for the mechanism?
71+ ##
72+ # method: auth_capable?
73+ # call-seq: auth_capable?(mechanism)
6074 #
61- # By default, this simply delegates to <tt>client.auth_capable?</tt>.
62- def auth_capable? ( mechanism ) ; client . auth_capable? ( mechanism ) end
75+ # Does the server advertise support for the +mechanism+?
76+ def_delegator : client, : auth_capable?
6377
6478 # Calls command_proc with +command_name+ (see
6579 # SASL::ProtocolAdapters::Generic#command_name),
@@ -79,19 +93,30 @@ def run_command(mechanism, initial_response = nil, &continuations_handler)
7993 command_proc . call ( *args , &continuations_handler )
8094 end
8195
96+ ##
97+ # method: host
98+ # The hostname to which the client connected.
99+ def_delegator :client , :host
100+
101+ ##
102+ # method: port
103+ # The destination port to which the client connected.
104+ def_delegator :client , :port
105+
82106 # Returns an array of server responses errors raised by run_command.
83107 # Exceptions in this array won't drop the connection.
84108 def response_errors ; [ ] end
85109
86- # Drop the connection gracefully.
87- #
88- # By default, this simply delegates to <tt>client.drop_connection</tt>.
89- def drop_connection ; client . drop_connection end
110+ ##
111+ # method: drop_connection
112+ # Drop the connection gracefully, sending a "LOGOUT" command as needed.
113+ def_delegator :client , :drop_connection
114+
115+ ##
116+ # method: drop_connection!
117+ # Drop the connection abruptly, closing the socket without logging out.
118+ def_delegator :client , :drop_connection!
90119
91- # Drop the connection abruptly.
92- #
93- # By default, this simply delegates to <tt>client.drop_connection!</tt>.
94- def drop_connection! ; client . drop_connection! end
95120 end
96121 end
97122 end
0 commit comments