/* * Copyright (c) 2021, Kyle Pereira * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include namespace IMAP { template using Promise = Core::Promise; class Client { AK_MAKE_NONCOPYABLE(Client); friend class Parser; public: static ErrorOr> connect_tls(StringView host, u16 port); static ErrorOr> connect_plaintext(StringView host, u16 port); Client(Client&&); RefPtr> connection_promise() { return m_connect_pending; } NonnullRefPtr> send_command(Command&&); NonnullRefPtr> send_simple_command(CommandType); ErrorOr send_raw(StringView data); NonnullRefPtr> login(StringView username, StringView password); NonnullRefPtr> list(StringView reference_name, StringView mailbox_name); NonnullRefPtr> lsub(StringView reference_name, StringView mailbox_name); NonnullRefPtr> select(StringView string); NonnullRefPtr> examine(StringView string); NonnullRefPtr> search(Optional charset, Vector&& search_keys, bool uid); NonnullRefPtr> fetch(FetchCommand request, bool uid); NonnullRefPtr> store(StoreMethod, Sequence, bool silent, Vector const& flags, bool uid); NonnullRefPtr> copy(Sequence sequence_set, StringView name, bool uid); NonnullRefPtr> create_mailbox(StringView name); NonnullRefPtr> delete_mailbox(StringView name); NonnullRefPtr> subscribe(StringView mailbox); NonnullRefPtr> unsubscribe(StringView mailbox); NonnullRefPtr> rename(StringView from, StringView to); NonnullRefPtr> authenticate(StringView method); NonnullRefPtr> idle(); NonnullRefPtr> finish_idle(); NonnullRefPtr> status(StringView mailbox, Vector const& types); NonnullRefPtr> append(StringView mailbox, Message&& message, Optional> flags = {}, Optional date_time = {}); bool is_open(); void close(); Function unrequested_response_callback; private: Client(StringView host, u16 port, NonnullOwnPtr); void setup_callbacks(); ErrorOr on_ready_to_receive(); bool verify_response_is_complete(); ErrorOr handle_parsed_response(ParseStatus&& parse_status); ErrorOr send_next_command(); StringView m_host; u16 m_port; NonnullOwnPtr m_socket; RefPtr> m_connect_pending {}; int m_current_command = 1; // Sent but response not received Vector>> m_pending_promises; // Not yet sent Vector m_command_queue {}; ByteBuffer m_buffer; Parser m_parser {}; bool m_expecting_response { false }; }; }