Serenity Operating System
at portability 179 lines 6.5 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#pragma once 28 29#include "IRCLogBuffer.h" 30#include "IRCWindow.h" 31#include <AK/CircularQueue.h> 32#include <AK/Function.h> 33#include <AK/HashMap.h> 34#include <AK/String.h> 35#include <LibCore/ConfigFile.h> 36#include <LibCore/TCPSocket.h> 37 38class IRCChannel; 39class IRCQuery; 40class IRCWindowListModel; 41 42class IRCClient final : public Core::Object { 43 C_OBJECT(IRCClient) 44 friend class IRCChannel; 45 friend class IRCQuery; 46 47public: 48 virtual ~IRCClient() override; 49 50 void set_server(const String& hostname, int port = 6667); 51 52 bool connect(); 53 54 String hostname() const { return m_hostname; } 55 int port() const { return m_port; } 56 57 String nickname() const { return m_nickname; } 58 59 void join_channel(const String&); 60 void part_channel(const String&); 61 void change_nick(const String&); 62 63 bool is_nick_prefix(char) const; 64 65 IRCWindow* current_window() { return aid_get_active_window(); } 66 const IRCWindow* current_window() const { return aid_get_active_window(); } 67 68 Function<void()> on_disconnect; 69 Function<void()> on_server_message; 70 Function<void(const String&)> on_nickname_changed; 71 Function<void(IRCChannel&)> on_part_from_channel; 72 73 Function<NonnullRefPtr<IRCWindow>(void*, IRCWindow::Type, const String&)> aid_create_window; 74 Function<IRCWindow*()> aid_get_active_window; 75 Function<void()> aid_update_window_list; 76 77 void register_subwindow(IRCWindow&); 78 void unregister_subwindow(IRCWindow&); 79 80 IRCWindowListModel* client_window_list_model() { return m_client_window_list_model.ptr(); } 81 const IRCWindowListModel* client_window_list_model() const { return m_client_window_list_model.ptr(); } 82 83 int window_count() const { return m_windows.size(); } 84 const IRCWindow& window_at(int index) const { return *m_windows.at(index); } 85 IRCWindow& window_at(int index) { return *m_windows.at(index); } 86 87 size_t window_index(const IRCWindow& window) const 88 { 89 for (size_t i = 0; i < m_windows.size(); ++i) { 90 if (m_windows[i] == &window) 91 return i; 92 } 93 ASSERT_NOT_REACHED(); 94 } 95 96 void did_part_from_channel(Badge<IRCChannel>, IRCChannel&); 97 98 void handle_user_input_in_channel(const String& channel_name, const String&); 99 void handle_user_input_in_query(const String& query_name, const String&); 100 void handle_user_input_in_server(const String&); 101 102 void handle_whois_action(const String&); 103 void handle_open_query_action(const String&); 104 void handle_close_query_action(const String&); 105 void handle_join_action(const String&); 106 void handle_part_action(const String&); 107 void handle_change_nick_action(const String&); 108 109 IRCQuery* query_with_name(const String&); 110 IRCQuery& ensure_query(const String& name); 111 IRCChannel& ensure_channel(const String& name); 112 113 void add_server_message(const String&, Color = Color::Black); 114 115private: 116 IRCClient(); 117 118 struct Message { 119 String prefix; 120 String command; 121 Vector<String> arguments; 122 }; 123 124 enum class PrivmsgOrNotice { 125 Privmsg, 126 Notice, 127 }; 128 129 void receive_from_server(); 130 void send(const String&); 131 void send_user(); 132 void send_nick(); 133 void send_pong(const String& server); 134 void send_privmsg(const String& target, const String&); 135 void send_notice(const String& target, const String&); 136 void send_whois(const String&); 137 void process_line(ByteBuffer&&); 138 void handle_join(const Message&); 139 void handle_part(const Message&); 140 void handle_ping(const Message&); 141 void handle_topic(const Message&); 142 void handle_rpl_topic(const Message&); 143 void handle_rpl_whoisuser(const Message&); 144 void handle_rpl_whoisserver(const Message&); 145 void handle_rpl_whoisoperator(const Message&); 146 void handle_rpl_whoisidle(const Message&); 147 void handle_rpl_endofwhois(const Message&); 148 void handle_rpl_whoischannels(const Message&); 149 void handle_rpl_topicwhotime(const Message&); 150 void handle_rpl_endofnames(const Message&); 151 void handle_rpl_namreply(const Message&); 152 void handle_privmsg_or_notice(const Message&, PrivmsgOrNotice); 153 void handle_nick(const Message&); 154 void handle(const Message&); 155 void handle_user_command(const String&); 156 void handle_ctcp_request(const StringView& peer, const StringView& payload); 157 void handle_ctcp_response(const StringView& peer, const StringView& payload); 158 void send_ctcp_response(const StringView& peer, const StringView& payload); 159 160 void on_socket_connected(); 161 162 String m_hostname; 163 int m_port { 6667 }; 164 165 RefPtr<Core::TCPSocket> m_socket; 166 167 String m_nickname; 168 RefPtr<Core::Notifier> m_notifier; 169 HashMap<String, RefPtr<IRCChannel>, CaseInsensitiveStringTraits> m_channels; 170 HashMap<String, RefPtr<IRCQuery>, CaseInsensitiveStringTraits> m_queries; 171 172 Vector<IRCWindow*> m_windows; 173 174 IRCWindow* m_server_subwindow { nullptr }; 175 176 NonnullRefPtr<IRCWindowListModel> m_client_window_list_model; 177 NonnullRefPtr<IRCLogBuffer> m_log; 178 NonnullRefPtr<Core::ConfigFile> m_config; 179};