1use std::fmt::{Debug, Formatter};
2
3use imap_codec::{
4 imap_types::{
5 auth::AuthenticateData,
6 command::{Command, CommandBody},
7 core::{LiteralMode, Tag, Text},
8 extensions::idle::IdleDone,
9 response::{
10 CommandContinuationRequest, CommandContinuationRequestBasic, Data, Greeting, Response,
11 Status,
12 },
13 secret::Secret,
14 ToStatic,
15 },
16 AuthenticateDataCodec, CommandCodec, GreetingCodec, IdleDoneCodec, ResponseCodec,
17};
18use thiserror::Error;
19
20use crate::{
21 handle::{Handle, HandleGenerator, HandleGeneratorGenerator, RawHandle},
22 receive::{ReceiveError, ReceiveEvent, ReceiveState},
23 server_send::{ServerSendEvent, ServerSendState},
24 types::CommandAuthenticate,
25 Interrupt, State,
26};
27
28static HANDLE_GENERATOR_GENERATOR: HandleGeneratorGenerator<ResponseHandle> =
29 HandleGeneratorGenerator::new();
30
31#[derive(Clone, Debug, PartialEq)]
32#[non_exhaustive]
33pub struct Options {
34 pub crlf_relaxed: bool,
35 pub max_literal_size: u32,
43 pub max_command_size: u32,
47 literal_accept_ccr: CommandContinuationRequest<'static>,
48 literal_reject_ccr: CommandContinuationRequest<'static>,
49}
50
51impl Default for Options {
52 fn default() -> Self {
53 Self {
54 crlf_relaxed: false,
56 max_literal_size: 25 * 1024 * 1024,
58 max_command_size: (25 * 1024 * 1024) + (64 * 1024),
61 literal_accept_ccr: CommandContinuationRequest::basic(None, Text::unvalidated("..."))
63 .unwrap(),
64 literal_reject_ccr: CommandContinuationRequest::basic(None, Text::unvalidated("..."))
66 .unwrap(),
67 }
68 }
69}
70
71impl Options {
72 pub fn literal_accept_text(&self) -> &Text {
73 match self.literal_accept_ccr {
74 CommandContinuationRequest::Basic(ref basic) => basic.text(),
75 CommandContinuationRequest::Base64(_) => unreachable!(),
76 }
77 }
78
79 pub fn set_literal_accept_text(&mut self, text: String) -> Result<(), String> {
80 if CommandContinuationRequestBasic::new(None, text.as_str()).is_ok() {
83 self.literal_accept_ccr = CommandContinuationRequest::basic(None, text).unwrap();
85 Ok(())
86 } else {
87 Err(text)
88 }
89 }
90
91 pub fn literal_reject_text(&self) -> &Text {
92 match self.literal_reject_ccr {
93 CommandContinuationRequest::Basic(ref basic) => basic.text(),
94 CommandContinuationRequest::Base64(_) => unreachable!(),
95 }
96 }
97
98 pub fn set_literal_reject_text(&mut self, text: String) -> Result<(), String> {
99 if CommandContinuationRequestBasic::new(None, text.as_str()).is_ok() {
102 self.literal_reject_ccr = CommandContinuationRequest::basic(None, text).unwrap();
104 Ok(())
105 } else {
106 Err(text)
107 }
108 }
109}
110
111pub struct Server {
112 options: Options,
113 handle_generator: HandleGenerator<ResponseHandle>,
114 send_state: ServerSendState,
115 receive_state: ReceiveState,
116 next_expected_message: NextExpectedMessage,
117}
118
119impl Server {
120 pub fn new(options: Options, greeting: Greeting<'static>) -> Self {
121 let mut send_state =
122 ServerSendState::new(GreetingCodec::default(), ResponseCodec::default());
123 send_state.enqueue_greeting(greeting);
124
125 let receive_state = ReceiveState::new(options.crlf_relaxed, Some(options.max_command_size));
126 let next_expected_message = NextExpectedMessage::Command(CommandCodec::default());
127
128 Self {
129 options,
130 handle_generator: HANDLE_GENERATOR_GENERATOR.generate(),
131 send_state,
132 receive_state,
133 next_expected_message,
134 }
135 }
136
137 pub fn enqueue_data(&mut self, data: Data<'static>) -> ResponseHandle {
143 let handle = self.handle_generator.generate();
144 self.send_state
145 .enqueue_response(Some(handle), Response::Data(data));
146 handle
147 }
148
149 pub fn enqueue_status(&mut self, status: Status<'static>) -> ResponseHandle {
155 let handle = self.handle_generator.generate();
156 self.send_state
157 .enqueue_response(Some(handle), Response::Status(status));
158 handle
159 }
160
161 pub fn enqueue_continuation_request(
167 &mut self,
168 continuation_request: CommandContinuationRequest<'static>,
169 ) -> ResponseHandle {
170 let handle = self.handle_generator.generate();
171 self.send_state.enqueue_response(
172 Some(handle),
173 Response::CommandContinuationRequest(continuation_request),
174 );
175 handle
176 }
177
178 fn progress_send(&mut self) -> Result<Option<Event>, Interrupt<Error>> {
179 match self.send_state.next() {
180 Ok(Some(ServerSendEvent::Greeting { greeting })) => {
181 Ok(Some(Event::GreetingSent { greeting }))
183 }
184 Ok(Some(ServerSendEvent::Response {
185 handle: Some(handle),
186 response,
187 })) => {
188 Ok(Some(Event::ResponseSent { handle, response }))
190 }
191 Ok(Some(ServerSendEvent::Response { handle: None, .. })) => {
192 Ok(None)
194 }
195 Ok(_) => {
196 Ok(None)
198 }
199 Err(Interrupt::Io(io)) => Err(Interrupt::Io(io)),
200 Err(Interrupt::Error(_)) => unreachable!(),
201 }
202 }
203
204 fn progress_receive(&mut self) -> Result<Option<Event>, Interrupt<Error>> {
205 match &self.next_expected_message {
206 NextExpectedMessage::Command(codec) => match self
207 .receive_state
208 .next::<CommandCodec>(codec)
209 {
210 Ok(ReceiveEvent::DecodingSuccess(command)) => match command.body {
211 CommandBody::Authenticate {
212 mechanism,
213 initial_response,
214 } => {
215 self.next_expected_message =
216 NextExpectedMessage::AuthenticateData(AuthenticateDataCodec::default());
217
218 Ok(Some(Event::CommandAuthenticateReceived {
219 command_authenticate: CommandAuthenticate {
220 tag: command.tag,
221 mechanism,
222 initial_response,
223 },
224 }))
225 }
226 CommandBody::Idle => {
227 self.next_expected_message = NextExpectedMessage::IdleAccept;
228
229 Ok(Some(Event::IdleCommandReceived { tag: command.tag }))
230 }
231 body => Ok(Some(Event::CommandReceived {
232 command: Command {
233 tag: command.tag,
234 body,
235 },
236 })),
237 },
238 Ok(ReceiveEvent::LiteralAnnouncement { mode, length }) => {
239 if length > self.options.max_literal_size {
240 match mode {
241 LiteralMode::Sync => {
242 if let Some(tag) = self.receive_state.message_tag() {
244 let status = Status::bad(
247 Some(tag),
248 None,
249 self.options.literal_reject_text().to_static(),
250 )
251 .unwrap();
252 self.send_state
253 .enqueue_response(None, Response::Status(status));
254
255 let discarded_bytes = self.receive_state.discard_message();
256
257 Err(Interrupt::Error(Error::LiteralTooLong { discarded_bytes }))
258 } else {
259 self.receive_state.poison_message();
271
272 Ok(None)
273 }
274 }
275 LiteralMode::NonSync => {
276 self.receive_state.poison_message();
284
285 Ok(None)
286 }
287 }
288 } else {
289 match mode {
290 LiteralMode::Sync => {
291 let cont = CommandContinuationRequest::basic(
295 None,
296 self.options.literal_accept_text().to_static(),
297 )
298 .unwrap();
299 self.send_state.enqueue_response(
300 None,
301 Response::CommandContinuationRequest(cont),
302 );
303 }
304 LiteralMode::NonSync => {
305 }
308 }
309
310 Ok(None)
311 }
312 }
313 Err(interrupt) => Err(handle_receive_interrupt(interrupt)),
314 },
315 NextExpectedMessage::AuthenticateData(codec) => {
316 match self.receive_state.next::<AuthenticateDataCodec>(codec) {
317 Ok(ReceiveEvent::DecodingSuccess(authenticate_data)) => {
318 Ok(Some(Event::AuthenticateDataReceived { authenticate_data }))
319 }
320 Ok(ReceiveEvent::LiteralAnnouncement { .. }) => {
321 Ok(None)
323 }
324 Err(interrupt) => Err(handle_receive_interrupt(interrupt)),
325 }
326 }
327 NextExpectedMessage::IdleAccept => {
328 Err(Interrupt::Io(crate::Io::NeedMoreInput))
332 }
333 NextExpectedMessage::IdleDone(codec) => {
334 match self.receive_state.next::<IdleDoneCodec>(codec) {
335 Ok(ReceiveEvent::DecodingSuccess(IdleDone)) => {
336 self.next_expected_message =
337 NextExpectedMessage::Command(CommandCodec::default());
338
339 Ok(Some(Event::IdleDoneReceived))
340 }
341 Ok(ReceiveEvent::LiteralAnnouncement { .. }) => {
342 Ok(None)
344 }
345 Err(interrupt) => Err(handle_receive_interrupt(interrupt)),
346 }
347 }
348 }
349 }
350
351 pub fn authenticate_continue(
352 &mut self,
353 continuation_request: CommandContinuationRequest<'static>,
354 ) -> Result<ResponseHandle, CommandContinuationRequest<'static>> {
355 if let NextExpectedMessage::AuthenticateData { .. } = self.next_expected_message {
356 let handle = self.enqueue_continuation_request(continuation_request);
357 Ok(handle)
358 } else {
359 Err(continuation_request)
360 }
361 }
362
363 pub fn authenticate_finish(
364 &mut self,
365 status: Status<'static>,
366 ) -> Result<ResponseHandle, Status<'static>> {
367 if let NextExpectedMessage::AuthenticateData(_) = &mut self.next_expected_message {
368 let handle = self.enqueue_status(status);
369
370 self.next_expected_message = NextExpectedMessage::Command(CommandCodec::default());
371
372 Ok(handle)
373 } else {
374 Err(status)
375 }
376 }
377
378 pub fn idle_accept(
379 &mut self,
380 continuation_request: CommandContinuationRequest<'static>,
381 ) -> Result<ResponseHandle, CommandContinuationRequest<'static>> {
382 if let NextExpectedMessage::IdleAccept = &mut self.next_expected_message {
383 let handle = self.enqueue_continuation_request(continuation_request);
384
385 self.next_expected_message = NextExpectedMessage::IdleDone(IdleDoneCodec::default());
386
387 Ok(handle)
388 } else {
389 Err(continuation_request)
390 }
391 }
392
393 pub fn idle_reject(
394 &mut self,
395 status: Status<'static>,
396 ) -> Result<ResponseHandle, Status<'static>> {
397 if let NextExpectedMessage::IdleAccept = &mut self.next_expected_message {
398 let handle = self.enqueue_status(status);
399
400 self.next_expected_message = NextExpectedMessage::Command(CommandCodec::default());
401
402 Ok(handle)
403 } else {
404 Err(status)
405 }
406 }
407}
408
409impl Debug for Server {
410 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
411 f.debug_struct("Server")
412 .field("options", &self.options)
413 .field("handle_generator", &self.handle_generator)
414 .finish_non_exhaustive()
415 }
416}
417
418impl State for Server {
419 type Event = Event;
420 type Error = Error;
421
422 fn enqueue_input(&mut self, bytes: &[u8]) {
423 self.receive_state.enqueue_input(bytes);
424 }
425
426 fn next(&mut self) -> Result<Self::Event, Interrupt<Self::Error>> {
427 loop {
428 if let Some(event) = self.progress_send()? {
429 return Ok(event);
430 }
431
432 if let Some(event) = self.progress_receive()? {
433 return Ok(event);
434 }
435 }
436 }
437}
438
439fn handle_receive_interrupt(receive_interrupt: Interrupt<ReceiveError>) -> Interrupt<Error> {
440 match receive_interrupt {
441 Interrupt::Io(io) => Interrupt::Io(io),
442 Interrupt::Error(ReceiveError::DecodingFailure { discarded_bytes }) => {
443 Interrupt::Error(Error::MalformedMessage { discarded_bytes })
444 }
445 Interrupt::Error(ReceiveError::ExpectedCrlfGotLf { discarded_bytes }) => {
446 Interrupt::Error(Error::ExpectedCrlfGotLf { discarded_bytes })
447 }
448 Interrupt::Error(ReceiveError::MessageIsPoisoned { discarded_bytes }) => {
449 Interrupt::Error(Error::MalformedMessage { discarded_bytes })
450 }
451 Interrupt::Error(ReceiveError::MessageTooLong { discarded_bytes }) => {
452 Interrupt::Error(Error::CommandTooLong { discarded_bytes })
453 }
454 }
455}
456
457#[derive(Clone, Copy, Eq, PartialEq, Hash)]
464pub struct ResponseHandle(RawHandle);
465
466impl Debug for ResponseHandle {
468 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
469 f.debug_tuple("ResponseHandle")
470 .field(&self.0.generator_id())
471 .field(&self.0.handle_id())
472 .finish()
473 }
474}
475
476impl Handle for ResponseHandle {
477 fn from_raw(raw_handle: RawHandle) -> Self {
478 Self(raw_handle)
479 }
480}
481
482#[derive(Debug)]
483pub enum Event {
484 GreetingSent {
486 greeting: Greeting<'static>,
487 },
488 ResponseSent {
490 handle: ResponseHandle,
492 response: Response<'static>,
494 },
495 CommandReceived {
497 command: Command<'static>,
498 },
499 CommandAuthenticateReceived {
506 command_authenticate: CommandAuthenticate,
507 },
508 AuthenticateDataReceived {
519 authenticate_data: AuthenticateData<'static>,
520 },
521 IdleCommandReceived {
522 tag: Tag<'static>,
523 },
524 IdleDoneReceived,
525}
526
527#[derive(Debug, Error)]
528pub enum Error {
529 #[error("Expected `\\r\\n`, got `\\n`")]
530 ExpectedCrlfGotLf { discarded_bytes: Secret<Box<[u8]>> },
531 #[error("Received malformed message")]
532 MalformedMessage { discarded_bytes: Secret<Box<[u8]>> },
533 #[error("Literal was rejected because it was too long")]
534 LiteralTooLong { discarded_bytes: Secret<Box<[u8]>> },
535 #[error("Command is too long")]
536 CommandTooLong { discarded_bytes: Secret<Box<[u8]>> },
537}
538
539#[derive(Clone, Debug)]
540enum NextExpectedMessage {
541 Command(CommandCodec),
542 AuthenticateData(AuthenticateDataCodec),
543 IdleAccept,
544 IdleDone(IdleDoneCodec),
545}