Module: EventMachine::IMAP::CommandSender
- Includes:
- LineBuffer, ContinuationSynchronisation
- Included in:
- Connection
- Defined in:
- lib/em-imap/command_sender.rb
Overview
Used to send commands, and various other pieces of data, to the IMAP server as they are needed. Plugs in the ContinuationSynchronisation module so that the outgoing channel is free of racey-behaviour.
Defined Under Namespace
Modules: LineBuffer
Instance Method Summary collapse
-
#prepare_idle_continuation(command) ⇒ Object
Register a stopback on the IDLE command that sends the DONE continuation that the server is waiting for.
-
#send_authentication_data(auth_handler, command) ⇒ Object
Pass a challenge/response between the server and the auth_handler.
-
#send_command_object(command) ⇒ Object
Send a command to the IMAP server.
-
#send_literal(literal, command) ⇒ Object
Send an IMAP literal to the server.
-
#send_string(str, command) ⇒ Object
Send some normal (binary/string) data to the server.
Methods included from ContinuationSynchronisation
#await_continuations, #awaiting_continuation?, #listen_for_continuation, #post_init, #when_not_awaiting_continuation
Methods included from LineBuffer
#post_init, #send_line_buffered
Instance Method Details
#prepare_idle_continuation(command) ⇒ Object
Register a stopback on the IDLE command that sends the DONE continuation that the server is waiting for.
This blocks the outgoing connection until the IDLE command is stopped, as required by RFC 2177.
117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/em-imap/command_sender.rb', line 117 def prepare_idle_continuation(command) when_not_awaiting_continuation do waiter = await_continuations command.stopback do waiter.stop begin send_data "DONE\r\n" rescue => e command.fail e end end end end |
#send_authentication_data(auth_handler, command) ⇒ Object
Pass a challenge/response between the server and the auth_handler.
This can be called several times in one authorization handshake depending on how many messages the server wishes to see from the auth_handler.
If the auth_handler raises an exception, or the network connection dies for some reason, the command will be failed.
94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/em-imap/command_sender.rb', line 94 def send_authentication_data(auth_handler, command) when_not_awaiting_continuation do waiter = await_continuations do |response| begin data = auth_handler.process(response.data.text.unpack("m")[0]) s = [data].pack("m").gsub(/\n/, "") send_data(s + CRLF) rescue => e command.fail e end end command.bothback{ |*args| waiter.stop } end end |
#send_command_object(command) ⇒ Object
Send a command to the IMAP server.
This method has two phases, the first of which is to convert your command into tokens for sending over the network, and the second is to actually send those fragments.
If the conversion fails, a Net::IMAP::DataFormatError will be raised which you should handle synchronously. If the sending fails, then the command will be failed asynchronously.
19 20 21 22 23 24 25 26 27 |
# File 'lib/em-imap/command_sender.rb', line 19 def send_command_object(command) Formatter.format(command) do |to_send| if to_send.is_a? Formatter::Literal send_literal to_send.str, command else send_string to_send, command end end end |
#send_literal(literal, command) ⇒ Object
Send an IMAP literal to the server.
Sending literals is a somewhat complicated process:
Step 1. Client tells the server how big the literal will be.
(and at the same time shows the server the contents of the command so
far)
Step 2. The server either accepts (with a ContinuationResponse) or
rejects (with a BadResponse) the continuation based on the size of the
literal, and the validity of the line so far.
Step 3. The client sends the literal, followed by a linefeed, and then continues with sending the rest of the command.
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/em-imap/command_sender.rb', line 63 def send_literal(literal, command) when_not_awaiting_continuation do begin send_line_buffered "{" + literal.size.to_s + "}" + CRLF rescue => e command.fail e end waiter = await_continuations do begin send_data literal rescue => e command.fail e end waiter.stop end command.errback{ waiter.stop } end end |
#send_string(str, command) ⇒ Object
Send some normal (binary/string) data to the server.
This uses the LineBuffer, and fails the command if the network connection has died for some reason.
37 38 39 40 41 42 43 44 45 |
# File 'lib/em-imap/command_sender.rb', line 37 def send_string(str, command) when_not_awaiting_continuation do begin send_line_buffered str rescue => e command.fail e end end end |