forked from ruby/net-imap
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclient_adapter.rb
More file actions
98 lines (86 loc) · 4.25 KB
/
Copy pathclient_adapter.rb
File metadata and controls
98 lines (86 loc) · 4.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# frozen_string_literal: true
module Net
class IMAP
module SASL
# This API is *experimental*, and may change.
#
# TODO: use with more clients, to verify the API can accommodate them.
#
# An abstract base class for implementing a SASL authentication exchange.
# Different clients will each have their own adapter subclass, overridden
# to match their needs.
#
# Although the default implementations _may_ be sufficient, subclasses
# will probably need to override some methods. Additionally, subclasses
# may need to include a protocol adapter mixin, if the default
# ProtocolAdapters::Generic isn't sufficient.
class ClientAdapter
include ProtocolAdapters::Generic
# The client that handles communication with the protocol server.
attr_reader :client
# +command_proc+ can used to avoid exposing private methods on #client.
# It's value is set by the block that is passed to ::new, and it is used
# by the default implementation of #run_command. Subclasses that
# override #run_command may use #command_proc for any other purpose they
# find useful.
#
# In the default implementation of #run_command, command_proc is called
# with the protocols authenticate +command+ name, the +mechanism+ name,
# an _optional_ +initial_response+ argument, and a +continuations+
# block. command_proc must run the protocol command with the arguments
# sent to it, _yield_ the payload of each continuation, respond to the
# continuation with the result of each _yield_, and _return_ the
# command's successful result. Non-successful results *MUST* raise
# an exception.
attr_reader :command_proc
# By default, this simply sets the #client and #command_proc attributes.
# Subclasses may override it, for example: to set the appropriate
# command_proc automatically.
def initialize(client, &command_proc)
@client, @command_proc = client, command_proc
end
# Attempt to authenticate #client to the server.
#
# By default, this simply delegates to
# AuthenticationExchange.authenticate.
def authenticate(...) AuthenticationExchange.authenticate(self, ...) end
# Do the protocol, server, and client all support an initial response?
#
# By default, this simply delegates to <tt>client.sasl_ir_capable?</tt>.
def sasl_ir_capable?; client.sasl_ir_capable? end
# Does the server advertise support for the mechanism?
#
# By default, this simply delegates to <tt>client.auth_capable?</tt>.
def auth_capable?(mechanism); client.auth_capable?(mechanism) end
# Calls command_proc with +command_name+ (see
# SASL::ProtocolAdapters::Generic#command_name),
# +mechanism+, +initial_response+, and a +continuations_handler+ block.
# The +initial_response+ is optional; when it's nil, it won't be sent to
# command_proc.
#
# Yields each continuation payload, responds to the server with the
# result of each yield, and returns the result. Non-successful results
# *MUST* raise an exception. Exceptions in the block *MUST* cause the
# command to fail.
#
# Subclasses that override this may use #command_proc differently.
def run_command(mechanism, initial_response = nil, &continuations_handler)
command_proc or raise Error, "initialize with block or override"
args = [command_name, mechanism, initial_response].compact
command_proc.call(*args, &continuations_handler)
end
# Returns an array of server responses errors raised by run_command.
# Exceptions in this array won't drop the connection.
def response_errors; [] end
# Drop the connection gracefully.
#
# By default, this simply delegates to <tt>client.drop_connection</tt>.
def drop_connection; client.drop_connection end
# Drop the connection abruptly.
#
# By default, this simply delegates to <tt>client.drop_connection!</tt>.
def drop_connection!; client.drop_connection! end
end
end
end
end