mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 11:12:45 +00:00 
			
		
		
		
	LibCore: Move Stream-based sockets into the Core namespace
				
					
				
			This commit is contained in:
		
							parent
							
								
									d43a7eae54
								
							
						
					
					
						commit
						a96339b72b
					
				
					 123 changed files with 1157 additions and 1100 deletions
				
			
		|  | @ -94,7 +94,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) | |||
| 
 | ||||
|     auto webcontent_socket = TRY(Core::take_over_socket_from_system_server("WebContent"sv)); | ||||
|     auto webcontent_client = TRY(WebContent::ConnectionFromClient::try_create(move(webcontent_socket))); | ||||
|     webcontent_client->set_fd_passing_socket(TRY(Core::Stream::LocalSocket::adopt_fd(webcontent_fd_passing_socket))); | ||||
|     webcontent_client->set_fd_passing_socket(TRY(Core::LocalSocket::adopt_fd(webcontent_fd_passing_socket))); | ||||
| 
 | ||||
|     QSocketNotifier webcontent_notifier(QSocketNotifier::Type::Read); | ||||
|     proxy_socket_through_notifier(*webcontent_client, webcontent_notifier); | ||||
|  |  | |||
|  | @ -600,11 +600,11 @@ void WebContentView::create_client() | |||
|     MUST(Core::System::close(wc_fd_passing_fd)); | ||||
|     MUST(Core::System::close(wc_fd)); | ||||
| 
 | ||||
|     auto socket = MUST(Core::Stream::LocalSocket::adopt_fd(ui_fd)); | ||||
|     auto socket = MUST(Core::LocalSocket::adopt_fd(ui_fd)); | ||||
|     MUST(socket->set_blocking(true)); | ||||
| 
 | ||||
|     auto new_client = MUST(adopt_nonnull_ref_or_enomem(new (nothrow) WebView::WebContentClient(std::move(socket), *this))); | ||||
|     new_client->set_fd_passing_socket(MUST(Core::Stream::LocalSocket::adopt_fd(ui_fd_passing_fd))); | ||||
|     new_client->set_fd_passing_socket(MUST(Core::LocalSocket::adopt_fd(ui_fd_passing_fd))); | ||||
| 
 | ||||
|     m_web_content_notifier.setSocket(new_client->socket().fd().value()); | ||||
|     m_web_content_notifier.setEnabled(true); | ||||
|  |  | |||
|  | @ -125,7 +125,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) | |||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         auto maybe_buffered_socket = Core::Stream::BufferedTCPSocket::create(maybe_client_socket.release_value()); | ||||
|         auto maybe_buffered_socket = Core::BufferedTCPSocket::create(maybe_client_socket.release_value()); | ||||
|         if (maybe_buffered_socket.is_error()) { | ||||
|             warnln("Could not obtain a buffered socket for the client: {}", maybe_buffered_socket.error()); | ||||
|             return; | ||||
|  |  | |||
|  | @ -338,7 +338,7 @@ public:)~~~"); | |||
|     static i32 static_message_id() { return (int)MessageID::@message.pascal_name@; } | ||||
|     virtual const char* message_name() const override { return "@endpoint.name@::@message.pascal_name@"; } | ||||
| 
 | ||||
|     static ErrorOr<NonnullOwnPtr<@message.pascal_name@>> decode(AK::Stream& stream, Core::Stream::LocalSocket& socket) | ||||
|     static ErrorOr<NonnullOwnPtr<@message.pascal_name@>> decode(AK::Stream& stream, Core::LocalSocket& socket) | ||||
|     { | ||||
|         IPC::Decoder decoder { stream, socket };)~~~"); | ||||
| 
 | ||||
|  | @ -584,7 +584,7 @@ public: | |||
| 
 | ||||
|     static u32 static_magic() { return @endpoint.magic@; } | ||||
| 
 | ||||
|     static ErrorOr<NonnullOwnPtr<IPC::Message>> decode_message(ReadonlyBytes buffer, [[maybe_unused]] Core::Stream::LocalSocket& socket) | ||||
|     static ErrorOr<NonnullOwnPtr<IPC::Message>> decode_message(ReadonlyBytes buffer, [[maybe_unused]] Core::LocalSocket& socket) | ||||
|     { | ||||
|         FixedMemoryStream stream { buffer }; | ||||
|         auto message_endpoint_magic = TRY(stream.read_value<u32>());)~~~"); | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ | |||
| #include <AK/String.h> | ||||
| #include <LibCore/EventLoop.h> | ||||
| #include <LibCore/LocalServer.h> | ||||
| #include <LibCore/Socket.h> | ||||
| #include <LibCore/Stream.h> | ||||
| #include <LibCore/TCPServer.h> | ||||
| #include <LibCore/Timer.h> | ||||
|  | @ -151,11 +152,11 @@ TEST_CASE(file_truncate) | |||
| 
 | ||||
| TEST_CASE(should_error_when_connection_fails) | ||||
| { | ||||
|     // NOTE: This is required here because Core::Stream::TCPSocket requires
 | ||||
|     // NOTE: This is required here because Core::TCPSocket requires
 | ||||
|     //       Core::EventLoop through Core::Notifier.
 | ||||
|     Core::EventLoop event_loop; | ||||
| 
 | ||||
|     auto maybe_tcp_socket = Core::Stream::TCPSocket::connect({ { 127, 0, 0, 1 }, 1234 }); | ||||
|     auto maybe_tcp_socket = Core::TCPSocket::connect({ { 127, 0, 0, 1 }, 1234 }); | ||||
|     EXPECT(maybe_tcp_socket.is_error()); | ||||
|     EXPECT(maybe_tcp_socket.error().is_syscall()); | ||||
|     EXPECT(maybe_tcp_socket.error().code() == ECONNREFUSED); | ||||
|  | @ -175,7 +176,7 @@ TEST_CASE(tcp_socket_read) | |||
|     EXPECT(!tcp_server->listen({ 127, 0, 0, 1 }, 9090).is_error()); | ||||
|     EXPECT(!tcp_server->set_blocking(true).is_error()); | ||||
| 
 | ||||
|     auto maybe_client_socket = Core::Stream::TCPSocket::connect({ { 127, 0, 0, 1 }, 9090 }); | ||||
|     auto maybe_client_socket = Core::TCPSocket::connect({ { 127, 0, 0, 1 }, 9090 }); | ||||
|     EXPECT(!maybe_client_socket.is_error()); | ||||
|     auto client_socket = maybe_client_socket.release_value(); | ||||
| 
 | ||||
|  | @ -211,7 +212,7 @@ TEST_CASE(tcp_socket_write) | |||
|     EXPECT(!tcp_server->listen({ 127, 0, 0, 1 }, 9090).is_error()); | ||||
|     EXPECT(!tcp_server->set_blocking(true).is_error()); | ||||
| 
 | ||||
|     auto maybe_client_socket = Core::Stream::TCPSocket::connect({ { 127, 0, 0, 1 }, 9090 }); | ||||
|     auto maybe_client_socket = Core::TCPSocket::connect({ { 127, 0, 0, 1 }, 9090 }); | ||||
|     EXPECT(!maybe_client_socket.is_error()); | ||||
|     auto client_socket = maybe_client_socket.release_value(); | ||||
| 
 | ||||
|  | @ -244,7 +245,7 @@ TEST_CASE(tcp_socket_eof) | |||
|     EXPECT(!tcp_server->listen({ 127, 0, 0, 1 }, 9090).is_error()); | ||||
|     EXPECT(!tcp_server->set_blocking(true).is_error()); | ||||
| 
 | ||||
|     auto maybe_client_socket = Core::Stream::TCPSocket::connect({ { 127, 0, 0, 1 }, 9090 }); | ||||
|     auto maybe_client_socket = Core::TCPSocket::connect({ { 127, 0, 0, 1 }, 9090 }); | ||||
|     EXPECT(!maybe_client_socket.is_error()); | ||||
|     auto client_socket = maybe_client_socket.release_value(); | ||||
| 
 | ||||
|  | @ -279,7 +280,7 @@ TEST_CASE(udp_socket_read_write) | |||
|     auto udp_server = Core::UDPServer::construct(); | ||||
|     EXPECT(udp_server->bind({ 127, 0, 0, 1 }, 9090)); | ||||
| 
 | ||||
|     auto maybe_client_socket = Core::Stream::UDPSocket::connect({ { 127, 0, 0, 1 }, 9090 }); | ||||
|     auto maybe_client_socket = Core::UDPSocket::connect({ { 127, 0, 0, 1 }, 9090 }); | ||||
|     EXPECT(!maybe_client_socket.is_error()); | ||||
|     auto client_socket = maybe_client_socket.release_value(); | ||||
| 
 | ||||
|  | @ -328,7 +329,7 @@ TEST_CASE(local_socket_read) | |||
|     auto local_server = Core::LocalServer::construct(); | ||||
|     EXPECT(local_server->listen("/tmp/test-socket")); | ||||
| 
 | ||||
|     local_server->on_accept = [&](NonnullOwnPtr<Core::Stream::LocalSocket> server_socket) { | ||||
|     local_server->on_accept = [&](NonnullOwnPtr<Core::LocalSocket> server_socket) { | ||||
|         EXPECT(!server_socket->write(sent_data.bytes()).is_error()); | ||||
| 
 | ||||
|         event_loop.quit(0); | ||||
|  | @ -343,7 +344,7 @@ TEST_CASE(local_socket_read) | |||
|         [](auto&) { | ||||
|             Core::EventLoop event_loop; | ||||
| 
 | ||||
|             auto maybe_client_socket = Core::Stream::LocalSocket::connect("/tmp/test-socket"); | ||||
|             auto maybe_client_socket = Core::LocalSocket::connect("/tmp/test-socket"); | ||||
|             EXPECT(!maybe_client_socket.is_error()); | ||||
|             auto client_socket = maybe_client_socket.release_value(); | ||||
| 
 | ||||
|  | @ -377,7 +378,7 @@ TEST_CASE(local_socket_write) | |||
|     auto local_server = Core::LocalServer::construct(); | ||||
|     EXPECT(local_server->listen("/tmp/test-socket")); | ||||
| 
 | ||||
|     local_server->on_accept = [&](NonnullOwnPtr<Core::Stream::LocalSocket> server_socket) { | ||||
|     local_server->on_accept = [&](NonnullOwnPtr<Core::LocalSocket> server_socket) { | ||||
|         // NOTE: For some reason LocalServer gives us a nonblocking socket..?
 | ||||
|         MUST(server_socket->set_blocking(true)); | ||||
| 
 | ||||
|  | @ -400,7 +401,7 @@ TEST_CASE(local_socket_write) | |||
|     // NOTE: Same reason as in the local_socket_read test.
 | ||||
|     auto background_action = Threading::BackgroundAction<int>::construct( | ||||
|         [](auto&) { | ||||
|             auto maybe_client_socket = Core::Stream::LocalSocket::connect("/tmp/test-socket"); | ||||
|             auto maybe_client_socket = Core::LocalSocket::connect("/tmp/test-socket"); | ||||
|             EXPECT(!maybe_client_socket.is_error()); | ||||
|             auto client_socket = maybe_client_socket.release_value(); | ||||
| 
 | ||||
|  | @ -566,9 +567,9 @@ TEST_CASE(buffered_tcp_socket_read) | |||
|     EXPECT(!tcp_server->listen({ 127, 0, 0, 1 }, 9090).is_error()); | ||||
|     EXPECT(!tcp_server->set_blocking(true).is_error()); | ||||
| 
 | ||||
|     auto maybe_client_socket = Core::Stream::TCPSocket::connect({ { 127, 0, 0, 1 }, 9090 }); | ||||
|     auto maybe_client_socket = Core::TCPSocket::connect({ { 127, 0, 0, 1 }, 9090 }); | ||||
|     EXPECT(!maybe_client_socket.is_error()); | ||||
|     auto maybe_buffered_socket = Core::Stream::BufferedTCPSocket::create(maybe_client_socket.release_value()); | ||||
|     auto maybe_buffered_socket = Core::BufferedTCPSocket::create(maybe_client_socket.release_value()); | ||||
|     EXPECT(!maybe_buffered_socket.is_error()); | ||||
|     auto client_socket = maybe_buffered_socket.release_value(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -31,7 +31,7 @@ class ConnectionToServer | |||
|     friend class ConnectionToServerWrapper; | ||||
| 
 | ||||
| public: | ||||
|     ConnectionToServer(NonnullOwnPtr<Core::Stream::LocalSocket> socket, DeprecatedString const& project_path) | ||||
|     ConnectionToServer(NonnullOwnPtr<Core::LocalSocket> socket, DeprecatedString const& project_path) | ||||
|         : IPC::ConnectionToServer<LanguageClientEndpoint, LanguageServerEndpoint>(*this, move(socket)) | ||||
|     { | ||||
|         m_project_path = project_path; | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ | |||
|         }                                                                                                 \ | ||||
|                                                                                                           \ | ||||
|     private:                                                                                              \ | ||||
|         ConnectionToServer(NonnullOwnPtr<Core::Stream::LocalSocket> socket, DeprecatedString const& project_path) \ | ||||
|         ConnectionToServer(NonnullOwnPtr<Core::LocalSocket> socket, DeprecatedString const& project_path) \ | ||||
|             : HackStudio::ConnectionToServer(move(socket), project_path)                                  \ | ||||
|         {                                                                                                 \ | ||||
|         }                                                                                                 \ | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ namespace LanguageServers { | |||
| 
 | ||||
| static HashMap<int, RefPtr<ConnectionFromClient>> s_connections; | ||||
| 
 | ||||
| ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket> socket) | ||||
| ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket> socket) | ||||
|     : IPC::ConnectionFromClient<LanguageClientEndpoint, LanguageServerEndpoint>(*this, move(socket), 1) | ||||
| { | ||||
|     s_connections.set(1, *this); | ||||
|  |  | |||
|  | @ -21,7 +21,7 @@ namespace LanguageServers { | |||
| 
 | ||||
| class ConnectionFromClient : public IPC::ConnectionFromClient<LanguageClientEndpoint, LanguageServerEndpoint> { | ||||
| public: | ||||
|     explicit ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket>); | ||||
|     explicit ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket>); | ||||
|     ~ConnectionFromClient() override = default; | ||||
| 
 | ||||
|     virtual void die() override; | ||||
|  |  | |||
|  | @ -15,7 +15,7 @@ class ConnectionFromClient final : public LanguageServers::ConnectionFromClient | |||
|     C_OBJECT(ConnectionFromClient); | ||||
| 
 | ||||
| private: | ||||
|     ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket> socket) | ||||
|     ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket> socket) | ||||
|         : LanguageServers::ConnectionFromClient(move(socket)) | ||||
|     { | ||||
|         m_autocomplete_engine = adopt_own(*new CodeComprehension::Cpp::CppComprehensionEngine(m_filedb)); | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ class ConnectionFromClient final : public LanguageServers::ConnectionFromClient | |||
|     C_OBJECT(ConnectionFromClient); | ||||
| 
 | ||||
| private: | ||||
|     ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket> socket) | ||||
|     ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket> socket) | ||||
|         : LanguageServers::ConnectionFromClient(move(socket)) | ||||
|     { | ||||
|         m_autocomplete_engine = make<CodeComprehension::Shell::ShellComprehensionEngine>(m_filedb); | ||||
|  |  | |||
|  | @ -21,7 +21,7 @@ public: | |||
|     virtual ~InspectorServerClient() override = default; | ||||
| 
 | ||||
| private: | ||||
|     InspectorServerClient(NonnullOwnPtr<Core::Stream::LocalSocket> socket) | ||||
|     InspectorServerClient(NonnullOwnPtr<Core::LocalSocket> socket) | ||||
|         : IPC::ConnectionToServer<InspectorClientEndpoint, InspectorServerEndpoint>(*this, move(socket)) | ||||
|     { | ||||
|     } | ||||
|  |  | |||
|  | @ -20,7 +20,7 @@ | |||
| 
 | ||||
| namespace Audio { | ||||
| 
 | ||||
| ConnectionToServer::ConnectionToServer(NonnullOwnPtr<Core::Stream::LocalSocket> socket) | ||||
| ConnectionToServer::ConnectionToServer(NonnullOwnPtr<Core::LocalSocket> socket) | ||||
|     : IPC::ConnectionToServer<AudioClientEndpoint, AudioServerEndpoint>(*this, move(socket)) | ||||
|     , m_buffer(make<AudioQueue>(MUST(AudioQueue::create()))) | ||||
|     , m_user_queue(make<UserSampleQueue>()) | ||||
|  |  | |||
|  | @ -62,7 +62,7 @@ public: | |||
|     Function<void(double volume)> on_client_volume_change; | ||||
| 
 | ||||
| private: | ||||
|     ConnectionToServer(NonnullOwnPtr<Core::Stream::LocalSocket>); | ||||
|     ConnectionToServer(NonnullOwnPtr<Core::LocalSocket>); | ||||
| 
 | ||||
|     virtual void main_mix_muted_state_changed(bool) override; | ||||
|     virtual void main_mix_volume_changed(double) override; | ||||
|  |  | |||
|  | @ -15,7 +15,7 @@ class ConnectionFromClient final : public LanguageServers::ConnectionFromClient | |||
|     C_OBJECT(ConnectionFromClient); | ||||
| 
 | ||||
| private: | ||||
|     ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket> socket) | ||||
|     ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket> socket) | ||||
|         : LanguageServers::ConnectionFromClient(move(socket)) | ||||
|     { | ||||
|         m_autocomplete_engine = make<CodeComprehension::Cpp::CppComprehensionEngine>(m_filedb); | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ class ConnectionFromClient final : public LanguageServers::ConnectionFromClient | |||
|     C_OBJECT(ConnectionFromClient); | ||||
| 
 | ||||
| private: | ||||
|     ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket> socket) | ||||
|     ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket> socket) | ||||
|         : LanguageServers::ConnectionFromClient(move(socket)) | ||||
|     { | ||||
|         m_autocomplete_engine = make<CodeComprehension::Shell::ShellComprehensionEngine>(m_filedb); | ||||
|  |  | |||
|  | @ -42,7 +42,7 @@ public: | |||
|     static Client& the(); | ||||
| 
 | ||||
| private: | ||||
|     explicit Client(NonnullOwnPtr<Core::Stream::LocalSocket> socket) | ||||
|     explicit Client(NonnullOwnPtr<Core::LocalSocket> socket) | ||||
|         : IPC::ConnectionToServer<ConfigClientEndpoint, ConfigServerEndpoint>(*this, move(socket)) | ||||
|     { | ||||
|     } | ||||
|  |  | |||
|  | @ -22,6 +22,7 @@ set(SOURCES | |||
|     Property.cpp | ||||
|     SecretString.cpp | ||||
|     SessionManagement.cpp | ||||
|     Socket.cpp | ||||
|     SOCKSProxyClient.cpp | ||||
|     StandardPaths.cpp | ||||
|     Stream.cpp | ||||
|  |  | |||
|  | @ -23,6 +23,7 @@ | |||
| #include <LibCore/Notifier.h> | ||||
| #include <LibCore/Object.h> | ||||
| #include <LibCore/SessionManagement.h> | ||||
| #include <LibCore/Socket.h> | ||||
| #include <LibThreading/Mutex.h> | ||||
| #include <LibThreading/MutexProtected.h> | ||||
| #include <errno.h> | ||||
|  | @ -156,7 +157,7 @@ pid_t EventLoop::s_pid; | |||
| class InspectorServerConnection : public Object { | ||||
|     C_OBJECT(InspectorServerConnection) | ||||
| private: | ||||
|     explicit InspectorServerConnection(NonnullOwnPtr<Stream::LocalSocket> socket) | ||||
|     explicit InspectorServerConnection(NonnullOwnPtr<LocalSocket> socket) | ||||
|         : m_socket(move(socket)) | ||||
|         , m_client_id(s_id_allocator.with_locked([](auto& allocator) { | ||||
|             return allocator->allocate(); | ||||
|  | @ -305,7 +306,7 @@ public: | |||
|     } | ||||
| 
 | ||||
| private: | ||||
|     NonnullOwnPtr<Stream::LocalSocket> m_socket; | ||||
|     NonnullOwnPtr<LocalSocket> m_socket; | ||||
|     WeakPtr<Object> m_inspected_object; | ||||
|     int m_client_id { -1 }; | ||||
| }; | ||||
|  | @ -370,7 +371,7 @@ bool connect_to_inspector_server() | |||
|         return false; | ||||
|     } | ||||
|     auto inspector_server_path = maybe_path.value(); | ||||
|     auto maybe_socket = Stream::LocalSocket::connect(inspector_server_path, Stream::PreventSIGPIPE::Yes); | ||||
|     auto maybe_socket = LocalSocket::connect(inspector_server_path, Socket::PreventSIGPIPE::Yes); | ||||
|     if (maybe_socket.is_error()) { | ||||
|         dbgln("connect_to_inspector_server: Failed to connect: {}", maybe_socket.error()); | ||||
|         return false; | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ namespace Core { | |||
| 
 | ||||
| class AnonymousBuffer; | ||||
| class ArgsParser; | ||||
| class BufferedSocketBase; | ||||
| class ChildEvent; | ||||
| class ConfigFile; | ||||
| class CustomEvent; | ||||
|  | @ -22,6 +23,7 @@ class Event; | |||
| class EventLoop; | ||||
| class IODevice; | ||||
| class LocalServer; | ||||
| class LocalSocket; | ||||
| class MimeData; | ||||
| class NetworkJob; | ||||
| class NetworkResponse; | ||||
|  | @ -29,18 +31,19 @@ class Notifier; | |||
| class Object; | ||||
| class ObjectClassRegistration; | ||||
| class ProcessStatisticsReader; | ||||
| class Socket; | ||||
| class SocketAddress; | ||||
| class TCPServer; | ||||
| class TCPSocket; | ||||
| class Timer; | ||||
| class TimerEvent; | ||||
| class UDPServer; | ||||
| class UDPSocket; | ||||
| 
 | ||||
| enum class TimerShouldFireWhenNotVisible; | ||||
| 
 | ||||
| namespace Stream { | ||||
| class File; | ||||
| class Socket; | ||||
| class BufferedSocketBase; | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ | |||
| #include <LibCore/LocalServer.h> | ||||
| #include <LibCore/Notifier.h> | ||||
| #include <LibCore/SessionManagement.h> | ||||
| #include <LibCore/Socket.h> | ||||
| #include <LibCore/Stream.h> | ||||
| #include <LibCore/System.h> | ||||
| #include <LibCore/SystemServerTakeover.h> | ||||
|  | @ -113,7 +114,7 @@ bool LocalServer::listen(DeprecatedString const& address) | |||
|     return true; | ||||
| } | ||||
| 
 | ||||
| ErrorOr<NonnullOwnPtr<Stream::LocalSocket>> LocalServer::accept() | ||||
| ErrorOr<NonnullOwnPtr<LocalSocket>> LocalServer::accept() | ||||
| { | ||||
|     VERIFY(m_listening); | ||||
|     sockaddr_un un; | ||||
|  | @ -133,7 +134,7 @@ ErrorOr<NonnullOwnPtr<Stream::LocalSocket>> LocalServer::accept() | |||
|     (void)fcntl(accepted_fd, F_SETFD, FD_CLOEXEC); | ||||
| #endif | ||||
| 
 | ||||
|     return Stream::LocalSocket::adopt_fd(accepted_fd, Stream::PreventSIGPIPE::Yes); | ||||
|     return LocalSocket::adopt_fd(accepted_fd, Socket::PreventSIGPIPE::Yes); | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -21,9 +21,9 @@ public: | |||
|     bool is_listening() const { return m_listening; } | ||||
|     bool listen(DeprecatedString const& address); | ||||
| 
 | ||||
|     ErrorOr<NonnullOwnPtr<Stream::LocalSocket>> accept(); | ||||
|     ErrorOr<NonnullOwnPtr<LocalSocket>> accept(); | ||||
| 
 | ||||
|     Function<void(NonnullOwnPtr<Stream::LocalSocket>)> on_accept; | ||||
|     Function<void(NonnullOwnPtr<LocalSocket>)> on_accept; | ||||
|     Function<void(Error)> on_accept_error; | ||||
| 
 | ||||
| private: | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ NetworkJob::NetworkJob(AK::Stream& output_stream) | |||
| { | ||||
| } | ||||
| 
 | ||||
| void NetworkJob::start(Core::Stream::Socket&) | ||||
| void NetworkJob::start(Core::Socket&) | ||||
| { | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -41,7 +41,7 @@ public: | |||
|         DetachFromSocket, | ||||
|         CloseSocket, | ||||
|     }; | ||||
|     virtual void start(Core::Stream::Socket&) = 0; | ||||
|     virtual void start(Core::Socket&) = 0; | ||||
|     virtual void shutdown(ShutdownMode) = 0; | ||||
|     virtual void fail(Error error) { did_fail(error); } | ||||
| 
 | ||||
|  |  | |||
|  | @ -95,7 +95,7 @@ StringView reply_response_name(Reply reply) | |||
|     VERIFY_NOT_REACHED(); | ||||
| } | ||||
| 
 | ||||
| ErrorOr<void> send_version_identifier_and_method_selection_message(Core::Stream::Socket& socket, Core::SOCKSProxyClient::Version version, Method method) | ||||
| ErrorOr<void> send_version_identifier_and_method_selection_message(Core::Socket& socket, Core::SOCKSProxyClient::Version version, Method method) | ||||
| { | ||||
|     Socks5VersionIdentifierAndMethodSelectionMessage message { | ||||
|         .version_identifier = to_underlying(version), | ||||
|  | @ -120,7 +120,7 @@ ErrorOr<void> send_version_identifier_and_method_selection_message(Core::Stream: | |||
|     return {}; | ||||
| } | ||||
| 
 | ||||
| ErrorOr<Reply> send_connect_request_message(Core::Stream::Socket& socket, Core::SOCKSProxyClient::Version version, Core::SOCKSProxyClient::HostOrIPV4 target, int port, Core::SOCKSProxyClient::Command command) | ||||
| ErrorOr<Reply> send_connect_request_message(Core::Socket& socket, Core::SOCKSProxyClient::Version version, Core::SOCKSProxyClient::HostOrIPV4 target, int port, Core::SOCKSProxyClient::Command command) | ||||
| { | ||||
|     AllocatingMemoryStream stream; | ||||
| 
 | ||||
|  | @ -216,7 +216,7 @@ ErrorOr<Reply> send_connect_request_message(Core::Stream::Socket& socket, Core:: | |||
|     return Reply(response_header.status); | ||||
| } | ||||
| 
 | ||||
| ErrorOr<u8> send_username_password_authentication_message(Core::Stream::Socket& socket, Core::SOCKSProxyClient::UsernamePasswordAuthenticationData const& auth_data) | ||||
| ErrorOr<u8> send_username_password_authentication_message(Core::Socket& socket, Core::SOCKSProxyClient::UsernamePasswordAuthenticationData const& auth_data) | ||||
| { | ||||
|     AllocatingMemoryStream stream; | ||||
| 
 | ||||
|  | @ -314,10 +314,10 @@ ErrorOr<NonnullOwnPtr<SOCKSProxyClient>> SOCKSProxyClient::connect(HostOrIPV4 co | |||
| { | ||||
|     auto underlying = TRY(server.visit( | ||||
|         [&](u32 ipv4) { | ||||
|             return Core::Stream::TCPSocket::connect({ IPv4Address(ipv4), static_cast<u16>(server_port) }); | ||||
|             return Core::TCPSocket::connect({ IPv4Address(ipv4), static_cast<u16>(server_port) }); | ||||
|         }, | ||||
|         [&](DeprecatedString const& hostname) { | ||||
|             return Core::Stream::TCPSocket::connect(hostname, static_cast<u16>(server_port)); | ||||
|             return Core::TCPSocket::connect(hostname, static_cast<u16>(server_port)); | ||||
|         })); | ||||
| 
 | ||||
|     auto socket = TRY(connect(*underlying, version, target, target_port, auth_data, command)); | ||||
|  |  | |||
|  | @ -8,10 +8,11 @@ | |||
| 
 | ||||
| #include <AK/OwnPtr.h> | ||||
| #include <LibCore/Proxy.h> | ||||
| #include <LibCore/Socket.h> | ||||
| #include <LibCore/Stream.h> | ||||
| 
 | ||||
| namespace Core { | ||||
| class SOCKSProxyClient final : public Stream::Socket { | ||||
| class SOCKSProxyClient final : public Socket { | ||||
| public: | ||||
|     enum class Version : u8 { | ||||
|         V4 = 0x04, | ||||
|  |  | |||
							
								
								
									
										410
									
								
								Userland/Libraries/LibCore/Socket.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										410
									
								
								Userland/Libraries/LibCore/Socket.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,410 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> | ||||
|  * Copyright (c) 2021, sin-ack <sin-ack@protonmail.com> | ||||
|  * | ||||
|  * SPDX-License-Identifier: BSD-2-Clause | ||||
|  */ | ||||
| 
 | ||||
| #include <LibCore/Socket.h> | ||||
| #include <LibCore/System.h> | ||||
| 
 | ||||
| namespace Core { | ||||
| 
 | ||||
| ErrorOr<int> Socket::create_fd(SocketDomain domain, SocketType type) | ||||
| { | ||||
|     int socket_domain; | ||||
|     switch (domain) { | ||||
|     case SocketDomain::Inet: | ||||
|         socket_domain = AF_INET; | ||||
|         break; | ||||
|     case SocketDomain::Local: | ||||
|         socket_domain = AF_LOCAL; | ||||
|         break; | ||||
|     default: | ||||
|         VERIFY_NOT_REACHED(); | ||||
|     } | ||||
| 
 | ||||
|     int socket_type; | ||||
|     switch (type) { | ||||
|     case SocketType::Stream: | ||||
|         socket_type = SOCK_STREAM; | ||||
|         break; | ||||
|     case SocketType::Datagram: | ||||
|         socket_type = SOCK_DGRAM; | ||||
|         break; | ||||
|     default: | ||||
|         VERIFY_NOT_REACHED(); | ||||
|     } | ||||
| 
 | ||||
|     // Let's have a safe default of CLOEXEC. :^)
 | ||||
| #ifdef SOCK_CLOEXEC | ||||
|     return System::socket(socket_domain, socket_type | SOCK_CLOEXEC, 0); | ||||
| #else | ||||
|     auto fd = TRY(System::socket(socket_domain, socket_type, 0)); | ||||
|     TRY(System::fcntl(fd, F_SETFD, FD_CLOEXEC)); | ||||
|     return fd; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| ErrorOr<IPv4Address> Socket::resolve_host(DeprecatedString const& host, SocketType type) | ||||
| { | ||||
|     int socket_type; | ||||
|     switch (type) { | ||||
|     case SocketType::Stream: | ||||
|         socket_type = SOCK_STREAM; | ||||
|         break; | ||||
|     case SocketType::Datagram: | ||||
|         socket_type = SOCK_DGRAM; | ||||
|         break; | ||||
|     default: | ||||
|         VERIFY_NOT_REACHED(); | ||||
|     } | ||||
| 
 | ||||
|     struct addrinfo hints = {}; | ||||
|     hints.ai_family = AF_UNSPEC; | ||||
|     hints.ai_socktype = socket_type; | ||||
|     hints.ai_flags = 0; | ||||
|     hints.ai_protocol = 0; | ||||
| 
 | ||||
|     auto const results = TRY(Core::System::getaddrinfo(host.characters(), nullptr, hints)); | ||||
| 
 | ||||
|     for (auto const& result : results.addresses()) { | ||||
|         if (result.ai_family == AF_INET) { | ||||
|             auto* socket_address = bit_cast<struct sockaddr_in*>(result.ai_addr); | ||||
|             NetworkOrdered<u32> const network_ordered_address { socket_address->sin_addr.s_addr }; | ||||
|             return IPv4Address { network_ordered_address }; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return Error::from_string_literal("Could not resolve to IPv4 address"); | ||||
| } | ||||
| 
 | ||||
| ErrorOr<void> Socket::connect_local(int fd, DeprecatedString const& path) | ||||
| { | ||||
|     auto address = SocketAddress::local(path); | ||||
|     auto maybe_sockaddr = address.to_sockaddr_un(); | ||||
|     if (!maybe_sockaddr.has_value()) { | ||||
|         dbgln("Core::Socket::connect_local: Could not obtain a sockaddr_un"); | ||||
|         return Error::from_errno(EINVAL); | ||||
|     } | ||||
| 
 | ||||
|     auto addr = maybe_sockaddr.release_value(); | ||||
|     return System::connect(fd, bit_cast<struct sockaddr*>(&addr), sizeof(addr)); | ||||
| } | ||||
| 
 | ||||
| ErrorOr<void> Socket::connect_inet(int fd, SocketAddress const& address) | ||||
| { | ||||
|     auto addr = address.to_sockaddr_in(); | ||||
|     return System::connect(fd, bit_cast<struct sockaddr*>(&addr), sizeof(addr)); | ||||
| } | ||||
| 
 | ||||
| ErrorOr<Bytes> PosixSocketHelper::read(Bytes buffer, int flags) | ||||
| { | ||||
|     if (!is_open()) { | ||||
|         return Error::from_errno(ENOTCONN); | ||||
|     } | ||||
| 
 | ||||
|     ssize_t nread = TRY(System::recv(m_fd, buffer.data(), buffer.size(), flags)); | ||||
|     m_last_read_was_eof = nread == 0; | ||||
| 
 | ||||
|     // If a socket read is EOF, then no more data can be read from it because
 | ||||
|     // the protocol has disconnected. In this case, we can just disable the
 | ||||
|     // notifier if we have one.
 | ||||
|     if (m_last_read_was_eof && m_notifier) | ||||
|         m_notifier->set_enabled(false); | ||||
| 
 | ||||
|     return buffer.trim(nread); | ||||
| } | ||||
| 
 | ||||
| ErrorOr<size_t> PosixSocketHelper::write(ReadonlyBytes buffer, int flags) | ||||
| { | ||||
|     if (!is_open()) { | ||||
|         return Error::from_errno(ENOTCONN); | ||||
|     } | ||||
| 
 | ||||
|     return TRY(System::send(m_fd, buffer.data(), buffer.size(), flags)); | ||||
| } | ||||
| 
 | ||||
| void PosixSocketHelper::close() | ||||
| { | ||||
|     if (!is_open()) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (m_notifier) | ||||
|         m_notifier->set_enabled(false); | ||||
| 
 | ||||
|     ErrorOr<void> result; | ||||
|     do { | ||||
|         result = System::close(m_fd); | ||||
|     } while (result.is_error() && result.error().code() == EINTR); | ||||
| 
 | ||||
|     VERIFY(!result.is_error()); | ||||
|     m_fd = -1; | ||||
| } | ||||
| 
 | ||||
| ErrorOr<bool> PosixSocketHelper::can_read_without_blocking(int timeout) const | ||||
| { | ||||
|     struct pollfd the_fd = { .fd = m_fd, .events = POLLIN, .revents = 0 }; | ||||
| 
 | ||||
|     ErrorOr<int> result { 0 }; | ||||
|     do { | ||||
|         result = Core::System::poll({ &the_fd, 1 }, timeout); | ||||
|     } while (result.is_error() && result.error().code() == EINTR); | ||||
| 
 | ||||
|     if (result.is_error()) | ||||
|         return result.release_error(); | ||||
| 
 | ||||
|     return (the_fd.revents & POLLIN) > 0; | ||||
| } | ||||
| 
 | ||||
| ErrorOr<void> PosixSocketHelper::set_blocking(bool enabled) | ||||
| { | ||||
|     int value = enabled ? 0 : 1; | ||||
|     return System::ioctl(m_fd, FIONBIO, &value); | ||||
| } | ||||
| 
 | ||||
| ErrorOr<void> PosixSocketHelper::set_close_on_exec(bool enabled) | ||||
| { | ||||
|     int flags = TRY(System::fcntl(m_fd, F_GETFD)); | ||||
| 
 | ||||
|     if (enabled) | ||||
|         flags |= FD_CLOEXEC; | ||||
|     else | ||||
|         flags &= ~FD_CLOEXEC; | ||||
| 
 | ||||
|     TRY(System::fcntl(m_fd, F_SETFD, flags)); | ||||
|     return {}; | ||||
| } | ||||
| 
 | ||||
| ErrorOr<void> PosixSocketHelper::set_receive_timeout(Time timeout) | ||||
| { | ||||
|     auto timeout_spec = timeout.to_timespec(); | ||||
|     return System::setsockopt(m_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout_spec, sizeof(timeout_spec)); | ||||
| } | ||||
| 
 | ||||
| void PosixSocketHelper::setup_notifier() | ||||
| { | ||||
|     if (!m_notifier) | ||||
|         m_notifier = Core::Notifier::construct(m_fd, Core::Notifier::Read); | ||||
| } | ||||
| 
 | ||||
| ErrorOr<NonnullOwnPtr<TCPSocket>> TCPSocket::connect(DeprecatedString const& host, u16 port) | ||||
| { | ||||
|     auto ip_address = TRY(resolve_host(host, SocketType::Stream)); | ||||
|     return connect(SocketAddress { ip_address, port }); | ||||
| } | ||||
| 
 | ||||
| ErrorOr<NonnullOwnPtr<TCPSocket>> TCPSocket::connect(SocketAddress const& address) | ||||
| { | ||||
|     auto socket = TRY(adopt_nonnull_own_or_enomem(new (nothrow) TCPSocket())); | ||||
| 
 | ||||
|     auto fd = TRY(create_fd(SocketDomain::Inet, SocketType::Stream)); | ||||
|     socket->m_helper.set_fd(fd); | ||||
| 
 | ||||
|     TRY(connect_inet(fd, address)); | ||||
| 
 | ||||
|     socket->setup_notifier(); | ||||
|     return socket; | ||||
| } | ||||
| 
 | ||||
| ErrorOr<NonnullOwnPtr<TCPSocket>> TCPSocket::adopt_fd(int fd) | ||||
| { | ||||
|     if (fd < 0) { | ||||
|         return Error::from_errno(EBADF); | ||||
|     } | ||||
| 
 | ||||
|     auto socket = TRY(adopt_nonnull_own_or_enomem(new (nothrow) TCPSocket())); | ||||
|     socket->m_helper.set_fd(fd); | ||||
|     socket->setup_notifier(); | ||||
|     return socket; | ||||
| } | ||||
| 
 | ||||
| ErrorOr<size_t> PosixSocketHelper::pending_bytes() const | ||||
| { | ||||
|     if (!is_open()) { | ||||
|         return Error::from_errno(ENOTCONN); | ||||
|     } | ||||
| 
 | ||||
|     int value; | ||||
|     TRY(System::ioctl(m_fd, FIONREAD, &value)); | ||||
|     return static_cast<size_t>(value); | ||||
| } | ||||
| 
 | ||||
| ErrorOr<NonnullOwnPtr<UDPSocket>> UDPSocket::connect(DeprecatedString const& host, u16 port, Optional<Time> timeout) | ||||
| { | ||||
|     auto ip_address = TRY(resolve_host(host, SocketType::Datagram)); | ||||
|     return connect(SocketAddress { ip_address, port }, timeout); | ||||
| } | ||||
| 
 | ||||
| ErrorOr<NonnullOwnPtr<UDPSocket>> UDPSocket::connect(SocketAddress const& address, Optional<Time> timeout) | ||||
| { | ||||
|     auto socket = TRY(adopt_nonnull_own_or_enomem(new (nothrow) UDPSocket())); | ||||
| 
 | ||||
|     auto fd = TRY(create_fd(SocketDomain::Inet, SocketType::Datagram)); | ||||
|     socket->m_helper.set_fd(fd); | ||||
|     if (timeout.has_value()) { | ||||
|         TRY(socket->m_helper.set_receive_timeout(timeout.value())); | ||||
|     } | ||||
| 
 | ||||
|     TRY(connect_inet(fd, address)); | ||||
| 
 | ||||
|     socket->setup_notifier(); | ||||
|     return socket; | ||||
| } | ||||
| 
 | ||||
| ErrorOr<NonnullOwnPtr<LocalSocket>> LocalSocket::connect(DeprecatedString const& path, PreventSIGPIPE prevent_sigpipe) | ||||
| { | ||||
|     auto socket = TRY(adopt_nonnull_own_or_enomem(new (nothrow) LocalSocket(prevent_sigpipe))); | ||||
| 
 | ||||
|     auto fd = TRY(create_fd(SocketDomain::Local, SocketType::Stream)); | ||||
|     socket->m_helper.set_fd(fd); | ||||
| 
 | ||||
|     TRY(connect_local(fd, path)); | ||||
| 
 | ||||
|     socket->setup_notifier(); | ||||
|     return socket; | ||||
| } | ||||
| 
 | ||||
| ErrorOr<NonnullOwnPtr<LocalSocket>> LocalSocket::adopt_fd(int fd, PreventSIGPIPE prevent_sigpipe) | ||||
| { | ||||
|     if (fd < 0) { | ||||
|         return Error::from_errno(EBADF); | ||||
|     } | ||||
| 
 | ||||
|     auto socket = TRY(adopt_nonnull_own_or_enomem(new (nothrow) LocalSocket(prevent_sigpipe))); | ||||
|     socket->m_helper.set_fd(fd); | ||||
|     socket->setup_notifier(); | ||||
|     return socket; | ||||
| } | ||||
| 
 | ||||
| ErrorOr<int> LocalSocket::receive_fd(int flags) | ||||
| { | ||||
| #if defined(AK_OS_SERENITY) | ||||
|     return Core::System::recvfd(m_helper.fd(), flags); | ||||
| #elif defined(AK_OS_LINUX) || defined(AK_OS_MACOS) || defined(AK_OS_FREEBSD) || defined(AK_OS_OPENBSD) | ||||
|     union { | ||||
|         struct cmsghdr cmsghdr; | ||||
|         char control[CMSG_SPACE(sizeof(int))]; | ||||
|     } cmsgu {}; | ||||
|     char c = 0; | ||||
|     struct iovec iov { | ||||
|         .iov_base = &c, | ||||
|         .iov_len = 1, | ||||
|     }; | ||||
|     struct msghdr msg = {}; | ||||
|     msg.msg_iov = &iov; | ||||
|     msg.msg_iovlen = 1; | ||||
|     msg.msg_control = cmsgu.control; | ||||
|     msg.msg_controllen = sizeof(cmsgu.control); | ||||
|     TRY(Core::System::recvmsg(m_helper.fd(), &msg, 0)); | ||||
| 
 | ||||
|     struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); | ||||
|     if (!cmsg || cmsg->cmsg_len != CMSG_LEN(sizeof(int))) | ||||
|         return Error::from_string_literal("Malformed message when receiving file descriptor"); | ||||
| 
 | ||||
|     VERIFY(cmsg->cmsg_level == SOL_SOCKET); | ||||
|     VERIFY(cmsg->cmsg_type == SCM_RIGHTS); | ||||
|     int fd = *((int*)CMSG_DATA(cmsg)); | ||||
| 
 | ||||
|     if (flags & O_CLOEXEC) { | ||||
|         auto fd_flags = TRY(Core::System::fcntl(fd, F_GETFD)); | ||||
|         TRY(Core::System::fcntl(fd, F_SETFD, fd_flags | FD_CLOEXEC)); | ||||
|     } | ||||
| 
 | ||||
|     return fd; | ||||
| #else | ||||
|     (void)flags; | ||||
|     return Error::from_string_literal("File descriptor passing not supported on this platform"); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| ErrorOr<void> LocalSocket::send_fd(int fd) | ||||
| { | ||||
| #if defined(AK_OS_SERENITY) | ||||
|     return Core::System::sendfd(m_helper.fd(), fd); | ||||
| #elif defined(AK_OS_LINUX) || defined(AK_OS_MACOS) || defined(AK_OS_FREEBSD) || defined(AK_OS_OPENBSD) | ||||
|     char c = 'F'; | ||||
|     struct iovec iov { | ||||
|         .iov_base = &c, | ||||
|         .iov_len = sizeof(c) | ||||
|     }; | ||||
| 
 | ||||
|     union { | ||||
|         struct cmsghdr cmsghdr; | ||||
|         char control[CMSG_SPACE(sizeof(int))]; | ||||
|     } cmsgu {}; | ||||
| 
 | ||||
|     struct msghdr msg = {}; | ||||
|     msg.msg_iov = &iov; | ||||
|     msg.msg_iovlen = 1; | ||||
|     msg.msg_control = cmsgu.control; | ||||
|     msg.msg_controllen = sizeof(cmsgu.control); | ||||
| 
 | ||||
|     struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); | ||||
|     cmsg->cmsg_len = CMSG_LEN(sizeof(int)); | ||||
|     cmsg->cmsg_level = SOL_SOCKET; | ||||
|     cmsg->cmsg_type = SCM_RIGHTS; | ||||
| 
 | ||||
|     *((int*)CMSG_DATA(cmsg)) = fd; | ||||
| 
 | ||||
|     TRY(Core::System::sendmsg(m_helper.fd(), &msg, 0)); | ||||
|     return {}; | ||||
| #else | ||||
|     (void)fd; | ||||
|     return Error::from_string_literal("File descriptor passing not supported on this platform"); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| ErrorOr<pid_t> LocalSocket::peer_pid() const | ||||
| { | ||||
| #ifdef AK_OS_MACOS | ||||
|     pid_t pid; | ||||
|     socklen_t pid_size = sizeof(pid); | ||||
| #elif defined(AK_OS_FREEBSD) | ||||
|     struct xucred creds = {}; | ||||
|     socklen_t creds_size = sizeof(creds); | ||||
| #elif defined(AK_OS_OPENBSD) | ||||
|     struct sockpeercred creds = {}; | ||||
|     socklen_t creds_size = sizeof(creds); | ||||
| #else | ||||
|     struct ucred creds = {}; | ||||
|     socklen_t creds_size = sizeof(creds); | ||||
| #endif | ||||
| 
 | ||||
| #ifdef AK_OS_MACOS | ||||
|     TRY(System::getsockopt(m_helper.fd(), SOL_LOCAL, LOCAL_PEERPID, &pid, &pid_size)); | ||||
|     return pid; | ||||
| #elif defined(AK_OS_FREEBSD) | ||||
|     TRY(System::getsockopt(m_helper.fd(), SOL_LOCAL, LOCAL_PEERCRED, &creds, &creds_size)); | ||||
|     return creds.cr_pid; | ||||
| #else | ||||
|     TRY(System::getsockopt(m_helper.fd(), SOL_SOCKET, SO_PEERCRED, &creds, &creds_size)); | ||||
|     return creds.pid; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| ErrorOr<Bytes> LocalSocket::read_without_waiting(Bytes buffer) | ||||
| { | ||||
|     return m_helper.read(buffer, MSG_DONTWAIT); | ||||
| } | ||||
| 
 | ||||
| Optional<int> LocalSocket::fd() const | ||||
| { | ||||
|     if (!is_open()) | ||||
|         return {}; | ||||
|     return m_helper.fd(); | ||||
| } | ||||
| 
 | ||||
| ErrorOr<int> LocalSocket::release_fd() | ||||
| { | ||||
|     if (!is_open()) { | ||||
|         return Error::from_errno(ENOTCONN); | ||||
|     } | ||||
| 
 | ||||
|     auto fd = m_helper.fd(); | ||||
|     m_helper.set_fd(-1); | ||||
|     return fd; | ||||
| } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										508
									
								
								Userland/Libraries/LibCore/Socket.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										508
									
								
								Userland/Libraries/LibCore/Socket.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,508 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2021, sin-ack <sin-ack@protonmail.com> | ||||
|  * Copyright (c) 2022, the SerenityOS developers. | ||||
|  * | ||||
|  * SPDX-License-Identifier: BSD-2-Clause | ||||
|  */ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <AK/BufferedStream.h> | ||||
| #include <AK/Function.h> | ||||
| #include <AK/Stream.h> | ||||
| #include <AK/Time.h> | ||||
| #include <LibCore/Notifier.h> | ||||
| #include <LibCore/SocketAddress.h> | ||||
| 
 | ||||
| namespace Core { | ||||
| 
 | ||||
| /// The Socket class is the base class for all concrete BSD-style socket
 | ||||
| /// classes. Sockets are non-seekable streams which can be read byte-wise.
 | ||||
| class Socket : public AK::Stream { | ||||
| public: | ||||
|     Socket(Socket&&) = default; | ||||
|     Socket& operator=(Socket&&) = default; | ||||
| 
 | ||||
|     /// Checks how many bytes of data are currently available to read on the
 | ||||
|     /// socket. For datagram-based socket, this is the size of the first
 | ||||
|     /// datagram that can be read. Returns either the amount of bytes, or an
 | ||||
|     /// errno in the case of failure.
 | ||||
|     virtual ErrorOr<size_t> pending_bytes() const = 0; | ||||
|     /// Returns whether there's any data that can be immediately read, or an
 | ||||
|     /// errno on failure.
 | ||||
|     virtual ErrorOr<bool> can_read_without_blocking(int timeout = 0) const = 0; | ||||
|     // Sets the blocking mode of the socket. If blocking mode is disabled, reads
 | ||||
|     // will fail with EAGAIN when there's no data available to read, and writes
 | ||||
|     // will fail with EAGAIN when the data cannot be written without blocking
 | ||||
|     // (due to the send buffer being full, for example).
 | ||||
|     virtual ErrorOr<void> set_blocking(bool enabled) = 0; | ||||
|     // Sets the close-on-exec mode of the socket. If close-on-exec mode is
 | ||||
|     // enabled, then the socket will be automatically closed by the kernel when
 | ||||
|     // an exec call happens.
 | ||||
|     virtual ErrorOr<void> set_close_on_exec(bool enabled) = 0; | ||||
| 
 | ||||
|     /// Disables any listening mechanisms that this socket uses.
 | ||||
|     /// Can be called with 'false' when `on_ready_to_read` notifications are no longer needed.
 | ||||
|     /// Conversely, set_notifications_enabled(true) will re-enable notifications.
 | ||||
|     virtual void set_notifications_enabled(bool) { } | ||||
| 
 | ||||
|     Function<void()> on_ready_to_read; | ||||
| 
 | ||||
|     enum class PreventSIGPIPE { | ||||
|         No, | ||||
|         Yes, | ||||
|     }; | ||||
| 
 | ||||
| protected: | ||||
|     enum class SocketDomain { | ||||
|         Local, | ||||
|         Inet, | ||||
|     }; | ||||
| 
 | ||||
|     enum class SocketType { | ||||
|         Stream, | ||||
|         Datagram, | ||||
|     }; | ||||
| 
 | ||||
|     Socket(PreventSIGPIPE prevent_sigpipe = PreventSIGPIPE::No) | ||||
|         : m_prevent_sigpipe(prevent_sigpipe == PreventSIGPIPE::Yes) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     static ErrorOr<int> create_fd(SocketDomain, SocketType); | ||||
|     // FIXME: This will need to be updated when IPv6 socket arrives. Perhaps a
 | ||||
|     //        base class for all address types is appropriate.
 | ||||
|     static ErrorOr<IPv4Address> resolve_host(DeprecatedString const&, SocketType); | ||||
| 
 | ||||
|     static ErrorOr<void> connect_local(int fd, DeprecatedString const& path); | ||||
|     static ErrorOr<void> connect_inet(int fd, SocketAddress const&); | ||||
| 
 | ||||
|     int default_flags() const | ||||
|     { | ||||
|         int flags = 0; | ||||
|         if (m_prevent_sigpipe) | ||||
|             flags |= MSG_NOSIGNAL; | ||||
|         return flags; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     bool m_prevent_sigpipe { false }; | ||||
| }; | ||||
| 
 | ||||
| /// A reusable socket maintains state about being connected in addition to
 | ||||
| /// normal Socket capabilities, and can be reconnected once disconnected.
 | ||||
| class ReusableSocket : public Socket { | ||||
| public: | ||||
|     /// Returns whether the socket is currently connected.
 | ||||
|     virtual bool is_connected() = 0; | ||||
|     /// Reconnects the socket to the given host and port. Returns EALREADY if
 | ||||
|     /// is_connected() is true.
 | ||||
|     virtual ErrorOr<void> reconnect(DeprecatedString const& host, u16 port) = 0; | ||||
|     /// Connects the socket to the given socket address (IP address + port).
 | ||||
|     /// Returns EALREADY is_connected() is true.
 | ||||
|     virtual ErrorOr<void> reconnect(SocketAddress const&) = 0; | ||||
| }; | ||||
| 
 | ||||
| class PosixSocketHelper { | ||||
|     AK_MAKE_NONCOPYABLE(PosixSocketHelper); | ||||
| 
 | ||||
| public: | ||||
|     template<typename T> | ||||
|     PosixSocketHelper(Badge<T>) | ||||
|     requires(IsBaseOf<Socket, T>) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     PosixSocketHelper(PosixSocketHelper&& other) | ||||
|     { | ||||
|         operator=(move(other)); | ||||
|     } | ||||
| 
 | ||||
|     PosixSocketHelper& operator=(PosixSocketHelper&& other) | ||||
|     { | ||||
|         m_fd = exchange(other.m_fd, -1); | ||||
|         m_last_read_was_eof = exchange(other.m_last_read_was_eof, false); | ||||
|         m_notifier = move(other.m_notifier); | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
|     int fd() const { return m_fd; } | ||||
|     void set_fd(int fd) { m_fd = fd; } | ||||
| 
 | ||||
|     ErrorOr<Bytes> read(Bytes, int flags); | ||||
|     ErrorOr<size_t> write(ReadonlyBytes, int flags); | ||||
| 
 | ||||
|     bool is_eof() const { return !is_open() || m_last_read_was_eof; } | ||||
|     bool is_open() const { return m_fd != -1; } | ||||
|     void close(); | ||||
| 
 | ||||
|     ErrorOr<size_t> pending_bytes() const; | ||||
|     ErrorOr<bool> can_read_without_blocking(int timeout) const; | ||||
| 
 | ||||
|     ErrorOr<void> set_blocking(bool enabled); | ||||
|     ErrorOr<void> set_close_on_exec(bool enabled); | ||||
|     ErrorOr<void> set_receive_timeout(Time timeout); | ||||
| 
 | ||||
|     void setup_notifier(); | ||||
|     RefPtr<Core::Notifier> notifier() { return m_notifier; } | ||||
| 
 | ||||
| private: | ||||
|     int m_fd { -1 }; | ||||
|     bool m_last_read_was_eof { false }; | ||||
|     RefPtr<Core::Notifier> m_notifier; | ||||
| }; | ||||
| 
 | ||||
| class TCPSocket final : public Socket { | ||||
| public: | ||||
|     static ErrorOr<NonnullOwnPtr<TCPSocket>> connect(DeprecatedString const& host, u16 port); | ||||
|     static ErrorOr<NonnullOwnPtr<TCPSocket>> connect(SocketAddress const& address); | ||||
|     static ErrorOr<NonnullOwnPtr<TCPSocket>> adopt_fd(int fd); | ||||
| 
 | ||||
|     TCPSocket(TCPSocket&& other) | ||||
|         : Socket(static_cast<Socket&&>(other)) | ||||
|         , m_helper(move(other.m_helper)) | ||||
|     { | ||||
|         if (is_open()) | ||||
|             setup_notifier(); | ||||
|     } | ||||
| 
 | ||||
|     TCPSocket& operator=(TCPSocket&& other) | ||||
|     { | ||||
|         Socket::operator=(static_cast<Socket&&>(other)); | ||||
|         m_helper = move(other.m_helper); | ||||
|         if (is_open()) | ||||
|             setup_notifier(); | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
|     virtual ErrorOr<Bytes> read(Bytes buffer) override { return m_helper.read(buffer, default_flags()); } | ||||
|     virtual ErrorOr<size_t> write(ReadonlyBytes buffer) override { return m_helper.write(buffer, default_flags()); } | ||||
|     virtual bool is_eof() const override { return m_helper.is_eof(); } | ||||
|     virtual bool is_open() const override { return m_helper.is_open(); }; | ||||
|     virtual void close() override { m_helper.close(); }; | ||||
|     virtual ErrorOr<size_t> pending_bytes() const override { return m_helper.pending_bytes(); } | ||||
|     virtual ErrorOr<bool> can_read_without_blocking(int timeout = 0) const override { return m_helper.can_read_without_blocking(timeout); } | ||||
|     virtual void set_notifications_enabled(bool enabled) override | ||||
|     { | ||||
|         if (auto notifier = m_helper.notifier()) | ||||
|             notifier->set_enabled(enabled); | ||||
|     } | ||||
|     ErrorOr<void> set_blocking(bool enabled) override { return m_helper.set_blocking(enabled); } | ||||
|     ErrorOr<void> set_close_on_exec(bool enabled) override { return m_helper.set_close_on_exec(enabled); } | ||||
| 
 | ||||
|     virtual ~TCPSocket() override { close(); } | ||||
| 
 | ||||
| private: | ||||
|     TCPSocket(PreventSIGPIPE prevent_sigpipe = PreventSIGPIPE::No) | ||||
|         : Socket(prevent_sigpipe) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     void setup_notifier() | ||||
|     { | ||||
|         VERIFY(is_open()); | ||||
| 
 | ||||
|         m_helper.setup_notifier(); | ||||
|         m_helper.notifier()->on_ready_to_read = [this] { | ||||
|             if (on_ready_to_read) | ||||
|                 on_ready_to_read(); | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     PosixSocketHelper m_helper { Badge<TCPSocket> {} }; | ||||
| }; | ||||
| 
 | ||||
| class UDPSocket final : public Socket { | ||||
| public: | ||||
|     static ErrorOr<NonnullOwnPtr<UDPSocket>> connect(DeprecatedString const& host, u16 port, Optional<Time> timeout = {}); | ||||
|     static ErrorOr<NonnullOwnPtr<UDPSocket>> connect(SocketAddress const& address, Optional<Time> timeout = {}); | ||||
| 
 | ||||
|     UDPSocket(UDPSocket&& other) | ||||
|         : Socket(static_cast<Socket&&>(other)) | ||||
|         , m_helper(move(other.m_helper)) | ||||
|     { | ||||
|         if (is_open()) | ||||
|             setup_notifier(); | ||||
|     } | ||||
| 
 | ||||
|     UDPSocket& operator=(UDPSocket&& other) | ||||
|     { | ||||
|         Socket::operator=(static_cast<Socket&&>(other)); | ||||
|         m_helper = move(other.m_helper); | ||||
|         if (is_open()) | ||||
|             setup_notifier(); | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
|     virtual ErrorOr<Bytes> read(Bytes buffer) override | ||||
|     { | ||||
|         auto pending_bytes = TRY(this->pending_bytes()); | ||||
|         if (pending_bytes > buffer.size()) { | ||||
|             // With UDP datagrams, reading a datagram into a buffer that's
 | ||||
|             // smaller than the datagram's size will cause the rest of the
 | ||||
|             // datagram to be discarded. That's not very nice, so let's bail
 | ||||
|             // early, telling the caller that he should allocate a bigger
 | ||||
|             // buffer.
 | ||||
|             return Error::from_errno(EMSGSIZE); | ||||
|         } | ||||
| 
 | ||||
|         return m_helper.read(buffer, default_flags()); | ||||
|     } | ||||
| 
 | ||||
|     virtual ErrorOr<size_t> write(ReadonlyBytes buffer) override { return m_helper.write(buffer, default_flags()); } | ||||
|     virtual bool is_eof() const override { return m_helper.is_eof(); } | ||||
|     virtual bool is_open() const override { return m_helper.is_open(); } | ||||
|     virtual void close() override { m_helper.close(); } | ||||
|     virtual ErrorOr<size_t> pending_bytes() const override { return m_helper.pending_bytes(); } | ||||
|     virtual ErrorOr<bool> can_read_without_blocking(int timeout = 0) const override { return m_helper.can_read_without_blocking(timeout); } | ||||
|     virtual void set_notifications_enabled(bool enabled) override | ||||
|     { | ||||
|         if (auto notifier = m_helper.notifier()) | ||||
|             notifier->set_enabled(enabled); | ||||
|     } | ||||
|     ErrorOr<void> set_blocking(bool enabled) override { return m_helper.set_blocking(enabled); } | ||||
|     ErrorOr<void> set_close_on_exec(bool enabled) override { return m_helper.set_close_on_exec(enabled); } | ||||
| 
 | ||||
|     virtual ~UDPSocket() override { close(); } | ||||
| 
 | ||||
| private: | ||||
|     UDPSocket(PreventSIGPIPE prevent_sigpipe = PreventSIGPIPE::No) | ||||
|         : Socket(prevent_sigpipe) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     void setup_notifier() | ||||
|     { | ||||
|         VERIFY(is_open()); | ||||
| 
 | ||||
|         m_helper.setup_notifier(); | ||||
|         m_helper.notifier()->on_ready_to_read = [this] { | ||||
|             if (on_ready_to_read) | ||||
|                 on_ready_to_read(); | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     PosixSocketHelper m_helper { Badge<UDPSocket> {} }; | ||||
| }; | ||||
| 
 | ||||
| class LocalSocket final : public Socket { | ||||
| public: | ||||
|     static ErrorOr<NonnullOwnPtr<LocalSocket>> connect(DeprecatedString const& path, PreventSIGPIPE = PreventSIGPIPE::No); | ||||
|     static ErrorOr<NonnullOwnPtr<LocalSocket>> adopt_fd(int fd, PreventSIGPIPE = PreventSIGPIPE::No); | ||||
| 
 | ||||
|     LocalSocket(LocalSocket&& other) | ||||
|         : Socket(static_cast<Socket&&>(other)) | ||||
|         , m_helper(move(other.m_helper)) | ||||
|     { | ||||
|         if (is_open()) | ||||
|             setup_notifier(); | ||||
|     } | ||||
| 
 | ||||
|     LocalSocket& operator=(LocalSocket&& other) | ||||
|     { | ||||
|         Socket::operator=(static_cast<Socket&&>(other)); | ||||
|         m_helper = move(other.m_helper); | ||||
|         if (is_open()) | ||||
|             setup_notifier(); | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
|     virtual ErrorOr<Bytes> read(Bytes buffer) override { return m_helper.read(buffer, default_flags()); } | ||||
|     virtual ErrorOr<size_t> write(ReadonlyBytes buffer) override { return m_helper.write(buffer, default_flags()); } | ||||
|     virtual bool is_eof() const override { return m_helper.is_eof(); } | ||||
|     virtual bool is_open() const override { return m_helper.is_open(); } | ||||
|     virtual void close() override { m_helper.close(); } | ||||
|     virtual ErrorOr<size_t> pending_bytes() const override { return m_helper.pending_bytes(); } | ||||
|     virtual ErrorOr<bool> can_read_without_blocking(int timeout = 0) const override { return m_helper.can_read_without_blocking(timeout); } | ||||
|     virtual ErrorOr<void> set_blocking(bool enabled) override { return m_helper.set_blocking(enabled); } | ||||
|     virtual ErrorOr<void> set_close_on_exec(bool enabled) override { return m_helper.set_close_on_exec(enabled); } | ||||
|     virtual void set_notifications_enabled(bool enabled) override | ||||
|     { | ||||
|         if (auto notifier = m_helper.notifier()) | ||||
|             notifier->set_enabled(enabled); | ||||
|     } | ||||
| 
 | ||||
|     ErrorOr<int> receive_fd(int flags); | ||||
|     ErrorOr<void> send_fd(int fd); | ||||
|     ErrorOr<pid_t> peer_pid() const; | ||||
|     ErrorOr<Bytes> read_without_waiting(Bytes buffer); | ||||
| 
 | ||||
|     /// Release the fd associated with this LocalSocket. After the fd is
 | ||||
|     /// released, the socket will be considered "closed" and all operations done
 | ||||
|     /// on it will fail with ENOTCONN. Fails with ENOTCONN if the socket is
 | ||||
|     /// already closed.
 | ||||
|     ErrorOr<int> release_fd(); | ||||
| 
 | ||||
|     Optional<int> fd() const; | ||||
|     RefPtr<Core::Notifier> notifier() { return m_helper.notifier(); } | ||||
| 
 | ||||
|     virtual ~LocalSocket() { close(); } | ||||
| 
 | ||||
| private: | ||||
|     LocalSocket(PreventSIGPIPE prevent_sigpipe = PreventSIGPIPE::No) | ||||
|         : Socket(prevent_sigpipe) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     void setup_notifier() | ||||
|     { | ||||
|         VERIFY(is_open()); | ||||
| 
 | ||||
|         m_helper.setup_notifier(); | ||||
|         m_helper.notifier()->on_ready_to_read = [this] { | ||||
|             if (on_ready_to_read) | ||||
|                 on_ready_to_read(); | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     PosixSocketHelper m_helper { Badge<LocalSocket> {} }; | ||||
| }; | ||||
| 
 | ||||
| template<typename T> | ||||
| concept SocketLike = IsBaseOf<Socket, T>; | ||||
| 
 | ||||
| class BufferedSocketBase : public Socket { | ||||
| public: | ||||
|     virtual ErrorOr<StringView> read_line(Bytes buffer) = 0; | ||||
|     virtual ErrorOr<Bytes> read_until(Bytes buffer, StringView candidate) = 0; | ||||
|     virtual ErrorOr<bool> can_read_line() = 0; | ||||
|     virtual size_t buffer_size() const = 0; | ||||
| }; | ||||
| 
 | ||||
| template<SocketLike T> | ||||
| class BufferedSocket final : public BufferedSocketBase { | ||||
|     friend BufferedHelper<T>; | ||||
| 
 | ||||
| public: | ||||
|     static ErrorOr<NonnullOwnPtr<BufferedSocket<T>>> create(NonnullOwnPtr<T> stream, size_t buffer_size = 16384) | ||||
|     { | ||||
|         return BufferedHelper<T>::template create_buffered<BufferedSocket>(move(stream), buffer_size); | ||||
|     } | ||||
| 
 | ||||
|     BufferedSocket(BufferedSocket&& other) | ||||
|         : BufferedSocketBase(static_cast<BufferedSocketBase&&>(other)) | ||||
|         , m_helper(move(other.m_helper)) | ||||
|     { | ||||
|         setup_notifier(); | ||||
|     } | ||||
| 
 | ||||
|     BufferedSocket& operator=(BufferedSocket&& other) | ||||
|     { | ||||
|         Socket::operator=(static_cast<Socket&&>(other)); | ||||
|         m_helper = move(other.m_helper); | ||||
| 
 | ||||
|         setup_notifier(); | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
|     virtual ErrorOr<Bytes> read(Bytes buffer) override { return m_helper.read(move(buffer)); } | ||||
|     virtual ErrorOr<size_t> write(ReadonlyBytes buffer) override { return m_helper.stream().write(buffer); } | ||||
|     virtual bool is_eof() const override { return m_helper.is_eof(); } | ||||
|     virtual bool is_open() const override { return m_helper.stream().is_open(); } | ||||
|     virtual void close() override { m_helper.stream().close(); } | ||||
|     virtual ErrorOr<size_t> pending_bytes() const override | ||||
|     { | ||||
|         return TRY(m_helper.stream().pending_bytes()) + m_helper.buffered_data_size(); | ||||
|     } | ||||
|     virtual ErrorOr<bool> can_read_without_blocking(int timeout = 0) const override { return m_helper.buffered_data_size() > 0 || TRY(m_helper.stream().can_read_without_blocking(timeout)); } | ||||
|     virtual ErrorOr<void> set_blocking(bool enabled) override { return m_helper.stream().set_blocking(enabled); } | ||||
|     virtual ErrorOr<void> set_close_on_exec(bool enabled) override { return m_helper.stream().set_close_on_exec(enabled); } | ||||
|     virtual void set_notifications_enabled(bool enabled) override { m_helper.stream().set_notifications_enabled(enabled); } | ||||
| 
 | ||||
|     virtual ErrorOr<StringView> read_line(Bytes buffer) override { return m_helper.read_line(move(buffer)); } | ||||
|     virtual ErrorOr<Bytes> read_until(Bytes buffer, StringView candidate) override { return m_helper.read_until(move(buffer), move(candidate)); } | ||||
|     template<size_t N> | ||||
|     ErrorOr<Bytes> read_until_any_of(Bytes buffer, Array<StringView, N> candidates) { return m_helper.read_until_any_of(move(buffer), move(candidates)); } | ||||
|     virtual ErrorOr<bool> can_read_line() override { return m_helper.can_read_line(); } | ||||
| 
 | ||||
|     virtual size_t buffer_size() const override { return m_helper.buffer_size(); } | ||||
| 
 | ||||
|     virtual ~BufferedSocket() override = default; | ||||
| 
 | ||||
| private: | ||||
|     BufferedSocket(NonnullOwnPtr<T> stream, CircularBuffer buffer) | ||||
|         : m_helper(Badge<BufferedSocket<T>> {}, move(stream), move(buffer)) | ||||
|     { | ||||
|         setup_notifier(); | ||||
|     } | ||||
| 
 | ||||
|     void setup_notifier() | ||||
|     { | ||||
|         m_helper.stream().on_ready_to_read = [this] { | ||||
|             if (on_ready_to_read) | ||||
|                 on_ready_to_read(); | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     BufferedHelper<T> m_helper; | ||||
| }; | ||||
| 
 | ||||
| using BufferedTCPSocket = BufferedSocket<TCPSocket>; | ||||
| using BufferedUDPSocket = BufferedSocket<UDPSocket>; | ||||
| using BufferedLocalSocket = BufferedSocket<LocalSocket>; | ||||
| 
 | ||||
| /// A BasicReusableSocket allows one to use one of the base Core::Stream classes
 | ||||
| /// as a ReusableSocket. It does not preserve any connection state or options,
 | ||||
| /// and instead just recreates the stream when reconnecting.
 | ||||
| template<SocketLike T> | ||||
| class BasicReusableSocket final : public ReusableSocket { | ||||
| public: | ||||
|     static ErrorOr<NonnullOwnPtr<BasicReusableSocket<T>>> connect(DeprecatedString const& host, u16 port) | ||||
|     { | ||||
|         return make<BasicReusableSocket<T>>(TRY(T::connect(host, port))); | ||||
|     } | ||||
| 
 | ||||
|     static ErrorOr<NonnullOwnPtr<BasicReusableSocket<T>>> connect(SocketAddress const& address) | ||||
|     { | ||||
|         return make<BasicReusableSocket<T>>(TRY(T::connect(address))); | ||||
|     } | ||||
| 
 | ||||
|     virtual bool is_connected() override | ||||
|     { | ||||
|         return m_socket.is_open(); | ||||
|     } | ||||
| 
 | ||||
|     virtual ErrorOr<void> reconnect(DeprecatedString const& host, u16 port) override | ||||
|     { | ||||
|         if (is_connected()) | ||||
|             return Error::from_errno(EALREADY); | ||||
| 
 | ||||
|         m_socket = TRY(T::connect(host, port)); | ||||
|         return {}; | ||||
|     } | ||||
| 
 | ||||
|     virtual ErrorOr<void> reconnect(SocketAddress const& address) override | ||||
|     { | ||||
|         if (is_connected()) | ||||
|             return Error::from_errno(EALREADY); | ||||
| 
 | ||||
|         m_socket = TRY(T::connect(address)); | ||||
|         return {}; | ||||
|     } | ||||
| 
 | ||||
|     virtual ErrorOr<Bytes> read(Bytes buffer) override { return m_socket.read(move(buffer)); } | ||||
|     virtual ErrorOr<size_t> write(ReadonlyBytes buffer) override { return m_socket.write(buffer); } | ||||
|     virtual bool is_eof() const override { return m_socket.is_eof(); } | ||||
|     virtual bool is_open() const override { return m_socket.is_open(); } | ||||
|     virtual void close() override { m_socket.close(); } | ||||
|     virtual ErrorOr<size_t> pending_bytes() const override { return m_socket.pending_bytes(); } | ||||
|     virtual ErrorOr<bool> can_read_without_blocking(int timeout = 0) const override { return m_socket.can_read_without_blocking(timeout); } | ||||
|     virtual ErrorOr<void> set_blocking(bool enabled) override { return m_socket.set_blocking(enabled); } | ||||
|     virtual ErrorOr<void> set_close_on_exec(bool enabled) override { return m_socket.set_close_on_exec(enabled); } | ||||
| 
 | ||||
| private: | ||||
|     BasicReusableSocket(NonnullOwnPtr<T> socket) | ||||
|         : m_socket(move(socket)) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     NonnullOwnPtr<T> m_socket; | ||||
| }; | ||||
| 
 | ||||
| using ReusableTCPSocket = BasicReusableSocket<TCPSocket>; | ||||
| using ReusableUDPSocket = BasicReusableSocket<UDPSocket>; | ||||
| 
 | ||||
| } | ||||
|  | @ -192,401 +192,4 @@ ErrorOr<void> File::truncate(size_t length) | |||
|     return System::ftruncate(m_fd, length); | ||||
| } | ||||
| 
 | ||||
| ErrorOr<int> Socket::create_fd(SocketDomain domain, SocketType type) | ||||
| { | ||||
|     int socket_domain; | ||||
|     switch (domain) { | ||||
|     case SocketDomain::Inet: | ||||
|         socket_domain = AF_INET; | ||||
|         break; | ||||
|     case SocketDomain::Local: | ||||
|         socket_domain = AF_LOCAL; | ||||
|         break; | ||||
|     default: | ||||
|         VERIFY_NOT_REACHED(); | ||||
|     } | ||||
| 
 | ||||
|     int socket_type; | ||||
|     switch (type) { | ||||
|     case SocketType::Stream: | ||||
|         socket_type = SOCK_STREAM; | ||||
|         break; | ||||
|     case SocketType::Datagram: | ||||
|         socket_type = SOCK_DGRAM; | ||||
|         break; | ||||
|     default: | ||||
|         VERIFY_NOT_REACHED(); | ||||
|     } | ||||
| 
 | ||||
|     // Let's have a safe default of CLOEXEC. :^)
 | ||||
| #ifdef SOCK_CLOEXEC | ||||
|     return System::socket(socket_domain, socket_type | SOCK_CLOEXEC, 0); | ||||
| #else | ||||
|     auto fd = TRY(System::socket(socket_domain, socket_type, 0)); | ||||
|     TRY(System::fcntl(fd, F_SETFD, FD_CLOEXEC)); | ||||
|     return fd; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| ErrorOr<IPv4Address> Socket::resolve_host(DeprecatedString const& host, SocketType type) | ||||
| { | ||||
|     int socket_type; | ||||
|     switch (type) { | ||||
|     case SocketType::Stream: | ||||
|         socket_type = SOCK_STREAM; | ||||
|         break; | ||||
|     case SocketType::Datagram: | ||||
|         socket_type = SOCK_DGRAM; | ||||
|         break; | ||||
|     default: | ||||
|         VERIFY_NOT_REACHED(); | ||||
|     } | ||||
| 
 | ||||
|     struct addrinfo hints = {}; | ||||
|     hints.ai_family = AF_UNSPEC; | ||||
|     hints.ai_socktype = socket_type; | ||||
|     hints.ai_flags = 0; | ||||
|     hints.ai_protocol = 0; | ||||
| 
 | ||||
|     auto const results = TRY(Core::System::getaddrinfo(host.characters(), nullptr, hints)); | ||||
| 
 | ||||
|     for (auto const& result : results.addresses()) { | ||||
|         if (result.ai_family == AF_INET) { | ||||
|             auto* socket_address = bit_cast<struct sockaddr_in*>(result.ai_addr); | ||||
|             NetworkOrdered<u32> const network_ordered_address { socket_address->sin_addr.s_addr }; | ||||
|             return IPv4Address { network_ordered_address }; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return Error::from_string_literal("Could not resolve to IPv4 address"); | ||||
| } | ||||
| 
 | ||||
| ErrorOr<void> Socket::connect_local(int fd, DeprecatedString const& path) | ||||
| { | ||||
|     auto address = SocketAddress::local(path); | ||||
|     auto maybe_sockaddr = address.to_sockaddr_un(); | ||||
|     if (!maybe_sockaddr.has_value()) { | ||||
|         dbgln("Core::Stream::Socket::connect_local: Could not obtain a sockaddr_un"); | ||||
|         return Error::from_errno(EINVAL); | ||||
|     } | ||||
| 
 | ||||
|     auto addr = maybe_sockaddr.release_value(); | ||||
|     return System::connect(fd, bit_cast<struct sockaddr*>(&addr), sizeof(addr)); | ||||
| } | ||||
| 
 | ||||
| ErrorOr<void> Socket::connect_inet(int fd, SocketAddress const& address) | ||||
| { | ||||
|     auto addr = address.to_sockaddr_in(); | ||||
|     return System::connect(fd, bit_cast<struct sockaddr*>(&addr), sizeof(addr)); | ||||
| } | ||||
| 
 | ||||
| ErrorOr<Bytes> PosixSocketHelper::read(Bytes buffer, int flags) | ||||
| { | ||||
|     if (!is_open()) { | ||||
|         return Error::from_errno(ENOTCONN); | ||||
|     } | ||||
| 
 | ||||
|     ssize_t nread = TRY(System::recv(m_fd, buffer.data(), buffer.size(), flags)); | ||||
|     m_last_read_was_eof = nread == 0; | ||||
| 
 | ||||
|     // If a socket read is EOF, then no more data can be read from it because
 | ||||
|     // the protocol has disconnected. In this case, we can just disable the
 | ||||
|     // notifier if we have one.
 | ||||
|     if (m_last_read_was_eof && m_notifier) | ||||
|         m_notifier->set_enabled(false); | ||||
| 
 | ||||
|     return buffer.trim(nread); | ||||
| } | ||||
| 
 | ||||
| ErrorOr<size_t> PosixSocketHelper::write(ReadonlyBytes buffer, int flags) | ||||
| { | ||||
|     if (!is_open()) { | ||||
|         return Error::from_errno(ENOTCONN); | ||||
|     } | ||||
| 
 | ||||
|     return TRY(System::send(m_fd, buffer.data(), buffer.size(), flags)); | ||||
| } | ||||
| 
 | ||||
| void PosixSocketHelper::close() | ||||
| { | ||||
|     if (!is_open()) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (m_notifier) | ||||
|         m_notifier->set_enabled(false); | ||||
| 
 | ||||
|     ErrorOr<void> result; | ||||
|     do { | ||||
|         result = System::close(m_fd); | ||||
|     } while (result.is_error() && result.error().code() == EINTR); | ||||
| 
 | ||||
|     VERIFY(!result.is_error()); | ||||
|     m_fd = -1; | ||||
| } | ||||
| 
 | ||||
| ErrorOr<bool> PosixSocketHelper::can_read_without_blocking(int timeout) const | ||||
| { | ||||
|     struct pollfd the_fd = { .fd = m_fd, .events = POLLIN, .revents = 0 }; | ||||
| 
 | ||||
|     ErrorOr<int> result { 0 }; | ||||
|     do { | ||||
|         result = Core::System::poll({ &the_fd, 1 }, timeout); | ||||
|     } while (result.is_error() && result.error().code() == EINTR); | ||||
| 
 | ||||
|     if (result.is_error()) | ||||
|         return result.release_error(); | ||||
| 
 | ||||
|     return (the_fd.revents & POLLIN) > 0; | ||||
| } | ||||
| 
 | ||||
| ErrorOr<void> PosixSocketHelper::set_blocking(bool enabled) | ||||
| { | ||||
|     int value = enabled ? 0 : 1; | ||||
|     return System::ioctl(m_fd, FIONBIO, &value); | ||||
| } | ||||
| 
 | ||||
| ErrorOr<void> PosixSocketHelper::set_close_on_exec(bool enabled) | ||||
| { | ||||
|     int flags = TRY(System::fcntl(m_fd, F_GETFD)); | ||||
| 
 | ||||
|     if (enabled) | ||||
|         flags |= FD_CLOEXEC; | ||||
|     else | ||||
|         flags &= ~FD_CLOEXEC; | ||||
| 
 | ||||
|     TRY(System::fcntl(m_fd, F_SETFD, flags)); | ||||
|     return {}; | ||||
| } | ||||
| 
 | ||||
| ErrorOr<void> PosixSocketHelper::set_receive_timeout(Time timeout) | ||||
| { | ||||
|     auto timeout_spec = timeout.to_timespec(); | ||||
|     return System::setsockopt(m_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout_spec, sizeof(timeout_spec)); | ||||
| } | ||||
| 
 | ||||
| void PosixSocketHelper::setup_notifier() | ||||
| { | ||||
|     if (!m_notifier) | ||||
|         m_notifier = Core::Notifier::construct(m_fd, Core::Notifier::Read); | ||||
| } | ||||
| 
 | ||||
| ErrorOr<NonnullOwnPtr<TCPSocket>> TCPSocket::connect(DeprecatedString const& host, u16 port) | ||||
| { | ||||
|     auto ip_address = TRY(resolve_host(host, SocketType::Stream)); | ||||
|     return connect(SocketAddress { ip_address, port }); | ||||
| } | ||||
| 
 | ||||
| ErrorOr<NonnullOwnPtr<TCPSocket>> TCPSocket::connect(SocketAddress const& address) | ||||
| { | ||||
|     auto socket = TRY(adopt_nonnull_own_or_enomem(new (nothrow) TCPSocket())); | ||||
| 
 | ||||
|     auto fd = TRY(create_fd(SocketDomain::Inet, SocketType::Stream)); | ||||
|     socket->m_helper.set_fd(fd); | ||||
| 
 | ||||
|     TRY(connect_inet(fd, address)); | ||||
| 
 | ||||
|     socket->setup_notifier(); | ||||
|     return socket; | ||||
| } | ||||
| 
 | ||||
| ErrorOr<NonnullOwnPtr<TCPSocket>> TCPSocket::adopt_fd(int fd) | ||||
| { | ||||
|     if (fd < 0) { | ||||
|         return Error::from_errno(EBADF); | ||||
|     } | ||||
| 
 | ||||
|     auto socket = TRY(adopt_nonnull_own_or_enomem(new (nothrow) TCPSocket())); | ||||
|     socket->m_helper.set_fd(fd); | ||||
|     socket->setup_notifier(); | ||||
|     return socket; | ||||
| } | ||||
| 
 | ||||
| ErrorOr<size_t> PosixSocketHelper::pending_bytes() const | ||||
| { | ||||
|     if (!is_open()) { | ||||
|         return Error::from_errno(ENOTCONN); | ||||
|     } | ||||
| 
 | ||||
|     int value; | ||||
|     TRY(System::ioctl(m_fd, FIONREAD, &value)); | ||||
|     return static_cast<size_t>(value); | ||||
| } | ||||
| 
 | ||||
| ErrorOr<NonnullOwnPtr<UDPSocket>> UDPSocket::connect(DeprecatedString const& host, u16 port, Optional<Time> timeout) | ||||
| { | ||||
|     auto ip_address = TRY(resolve_host(host, SocketType::Datagram)); | ||||
|     return connect(SocketAddress { ip_address, port }, timeout); | ||||
| } | ||||
| 
 | ||||
| ErrorOr<NonnullOwnPtr<UDPSocket>> UDPSocket::connect(SocketAddress const& address, Optional<Time> timeout) | ||||
| { | ||||
|     auto socket = TRY(adopt_nonnull_own_or_enomem(new (nothrow) UDPSocket())); | ||||
| 
 | ||||
|     auto fd = TRY(create_fd(SocketDomain::Inet, SocketType::Datagram)); | ||||
|     socket->m_helper.set_fd(fd); | ||||
|     if (timeout.has_value()) { | ||||
|         TRY(socket->m_helper.set_receive_timeout(timeout.value())); | ||||
|     } | ||||
| 
 | ||||
|     TRY(connect_inet(fd, address)); | ||||
| 
 | ||||
|     socket->setup_notifier(); | ||||
|     return socket; | ||||
| } | ||||
| 
 | ||||
| ErrorOr<NonnullOwnPtr<LocalSocket>> LocalSocket::connect(DeprecatedString const& path, PreventSIGPIPE prevent_sigpipe) | ||||
| { | ||||
|     auto socket = TRY(adopt_nonnull_own_or_enomem(new (nothrow) LocalSocket(prevent_sigpipe))); | ||||
| 
 | ||||
|     auto fd = TRY(create_fd(SocketDomain::Local, SocketType::Stream)); | ||||
|     socket->m_helper.set_fd(fd); | ||||
| 
 | ||||
|     TRY(connect_local(fd, path)); | ||||
| 
 | ||||
|     socket->setup_notifier(); | ||||
|     return socket; | ||||
| } | ||||
| 
 | ||||
| ErrorOr<NonnullOwnPtr<LocalSocket>> LocalSocket::adopt_fd(int fd, PreventSIGPIPE prevent_sigpipe) | ||||
| { | ||||
|     if (fd < 0) { | ||||
|         return Error::from_errno(EBADF); | ||||
|     } | ||||
| 
 | ||||
|     auto socket = TRY(adopt_nonnull_own_or_enomem(new (nothrow) LocalSocket(prevent_sigpipe))); | ||||
|     socket->m_helper.set_fd(fd); | ||||
|     socket->setup_notifier(); | ||||
|     return socket; | ||||
| } | ||||
| 
 | ||||
| ErrorOr<int> LocalSocket::receive_fd(int flags) | ||||
| { | ||||
| #if defined(AK_OS_SERENITY) | ||||
|     return Core::System::recvfd(m_helper.fd(), flags); | ||||
| #elif defined(AK_OS_LINUX) || defined(AK_OS_MACOS) || defined(AK_OS_FREEBSD) || defined(AK_OS_OPENBSD) | ||||
|     union { | ||||
|         struct cmsghdr cmsghdr; | ||||
|         char control[CMSG_SPACE(sizeof(int))]; | ||||
|     } cmsgu {}; | ||||
|     char c = 0; | ||||
|     struct iovec iov { | ||||
|         .iov_base = &c, | ||||
|         .iov_len = 1, | ||||
|     }; | ||||
|     struct msghdr msg = {}; | ||||
|     msg.msg_iov = &iov; | ||||
|     msg.msg_iovlen = 1; | ||||
|     msg.msg_control = cmsgu.control; | ||||
|     msg.msg_controllen = sizeof(cmsgu.control); | ||||
|     TRY(Core::System::recvmsg(m_helper.fd(), &msg, 0)); | ||||
| 
 | ||||
|     struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); | ||||
|     if (!cmsg || cmsg->cmsg_len != CMSG_LEN(sizeof(int))) | ||||
|         return Error::from_string_literal("Malformed message when receiving file descriptor"); | ||||
| 
 | ||||
|     VERIFY(cmsg->cmsg_level == SOL_SOCKET); | ||||
|     VERIFY(cmsg->cmsg_type == SCM_RIGHTS); | ||||
|     int fd = *((int*)CMSG_DATA(cmsg)); | ||||
| 
 | ||||
|     if (flags & O_CLOEXEC) { | ||||
|         auto fd_flags = TRY(Core::System::fcntl(fd, F_GETFD)); | ||||
|         TRY(Core::System::fcntl(fd, F_SETFD, fd_flags | FD_CLOEXEC)); | ||||
|     } | ||||
| 
 | ||||
|     return fd; | ||||
| #else | ||||
|     (void)flags; | ||||
|     return Error::from_string_literal("File descriptor passing not supported on this platform"); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| ErrorOr<void> LocalSocket::send_fd(int fd) | ||||
| { | ||||
| #if defined(AK_OS_SERENITY) | ||||
|     return Core::System::sendfd(m_helper.fd(), fd); | ||||
| #elif defined(AK_OS_LINUX) || defined(AK_OS_MACOS) || defined(AK_OS_FREEBSD) || defined(AK_OS_OPENBSD) | ||||
|     char c = 'F'; | ||||
|     struct iovec iov { | ||||
|         .iov_base = &c, | ||||
|         .iov_len = sizeof(c) | ||||
|     }; | ||||
| 
 | ||||
|     union { | ||||
|         struct cmsghdr cmsghdr; | ||||
|         char control[CMSG_SPACE(sizeof(int))]; | ||||
|     } cmsgu {}; | ||||
| 
 | ||||
|     struct msghdr msg = {}; | ||||
|     msg.msg_iov = &iov; | ||||
|     msg.msg_iovlen = 1; | ||||
|     msg.msg_control = cmsgu.control; | ||||
|     msg.msg_controllen = sizeof(cmsgu.control); | ||||
| 
 | ||||
|     struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); | ||||
|     cmsg->cmsg_len = CMSG_LEN(sizeof(int)); | ||||
|     cmsg->cmsg_level = SOL_SOCKET; | ||||
|     cmsg->cmsg_type = SCM_RIGHTS; | ||||
| 
 | ||||
|     *((int*)CMSG_DATA(cmsg)) = fd; | ||||
| 
 | ||||
|     TRY(Core::System::sendmsg(m_helper.fd(), &msg, 0)); | ||||
|     return {}; | ||||
| #else | ||||
|     (void)fd; | ||||
|     return Error::from_string_literal("File descriptor passing not supported on this platform"); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| ErrorOr<pid_t> LocalSocket::peer_pid() const | ||||
| { | ||||
| #ifdef AK_OS_MACOS | ||||
|     pid_t pid; | ||||
|     socklen_t pid_size = sizeof(pid); | ||||
| #elif defined(AK_OS_FREEBSD) | ||||
|     struct xucred creds = {}; | ||||
|     socklen_t creds_size = sizeof(creds); | ||||
| #elif defined(AK_OS_OPENBSD) | ||||
|     struct sockpeercred creds = {}; | ||||
|     socklen_t creds_size = sizeof(creds); | ||||
| #else | ||||
|     struct ucred creds = {}; | ||||
|     socklen_t creds_size = sizeof(creds); | ||||
| #endif | ||||
| 
 | ||||
| #ifdef AK_OS_MACOS | ||||
|     TRY(System::getsockopt(m_helper.fd(), SOL_LOCAL, LOCAL_PEERPID, &pid, &pid_size)); | ||||
|     return pid; | ||||
| #elif defined(AK_OS_FREEBSD) | ||||
|     TRY(System::getsockopt(m_helper.fd(), SOL_LOCAL, LOCAL_PEERCRED, &creds, &creds_size)); | ||||
|     return creds.cr_pid; | ||||
| #else | ||||
|     TRY(System::getsockopt(m_helper.fd(), SOL_SOCKET, SO_PEERCRED, &creds, &creds_size)); | ||||
|     return creds.pid; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| ErrorOr<Bytes> LocalSocket::read_without_waiting(Bytes buffer) | ||||
| { | ||||
|     return m_helper.read(buffer, MSG_DONTWAIT); | ||||
| } | ||||
| 
 | ||||
| Optional<int> LocalSocket::fd() const | ||||
| { | ||||
|     if (!is_open()) | ||||
|         return {}; | ||||
|     return m_helper.fd(); | ||||
| } | ||||
| 
 | ||||
| ErrorOr<int> LocalSocket::release_fd() | ||||
| { | ||||
|     if (!is_open()) { | ||||
|         return Error::from_errno(ENOTCONN); | ||||
|     } | ||||
| 
 | ||||
|     auto fd = m_helper.fd(); | ||||
|     m_helper.set_fd(-1); | ||||
|     return fd; | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -28,93 +28,6 @@ | |||
| 
 | ||||
| namespace Core::Stream { | ||||
| 
 | ||||
| enum class PreventSIGPIPE { | ||||
|     No, | ||||
|     Yes, | ||||
| }; | ||||
| 
 | ||||
| /// The Socket class is the base class for all concrete BSD-style socket
 | ||||
| /// classes. Sockets are non-seekable streams which can be read byte-wise.
 | ||||
| class Socket : public AK::Stream { | ||||
| public: | ||||
|     Socket(Socket&&) = default; | ||||
|     Socket& operator=(Socket&&) = default; | ||||
| 
 | ||||
|     /// Checks how many bytes of data are currently available to read on the
 | ||||
|     /// socket. For datagram-based socket, this is the size of the first
 | ||||
|     /// datagram that can be read. Returns either the amount of bytes, or an
 | ||||
|     /// errno in the case of failure.
 | ||||
|     virtual ErrorOr<size_t> pending_bytes() const = 0; | ||||
|     /// Returns whether there's any data that can be immediately read, or an
 | ||||
|     /// errno on failure.
 | ||||
|     virtual ErrorOr<bool> can_read_without_blocking(int timeout = 0) const = 0; | ||||
|     // Sets the blocking mode of the socket. If blocking mode is disabled, reads
 | ||||
|     // will fail with EAGAIN when there's no data available to read, and writes
 | ||||
|     // will fail with EAGAIN when the data cannot be written without blocking
 | ||||
|     // (due to the send buffer being full, for example).
 | ||||
|     virtual ErrorOr<void> set_blocking(bool enabled) = 0; | ||||
|     // Sets the close-on-exec mode of the socket. If close-on-exec mode is
 | ||||
|     // enabled, then the socket will be automatically closed by the kernel when
 | ||||
|     // an exec call happens.
 | ||||
|     virtual ErrorOr<void> set_close_on_exec(bool enabled) = 0; | ||||
| 
 | ||||
|     /// Disables any listening mechanisms that this socket uses.
 | ||||
|     /// Can be called with 'false' when `on_ready_to_read` notifications are no longer needed.
 | ||||
|     /// Conversely, set_notifications_enabled(true) will re-enable notifications.
 | ||||
|     virtual void set_notifications_enabled(bool) { } | ||||
| 
 | ||||
|     Function<void()> on_ready_to_read; | ||||
| 
 | ||||
| protected: | ||||
|     enum class SocketDomain { | ||||
|         Local, | ||||
|         Inet, | ||||
|     }; | ||||
| 
 | ||||
|     enum class SocketType { | ||||
|         Stream, | ||||
|         Datagram, | ||||
|     }; | ||||
| 
 | ||||
|     Socket(PreventSIGPIPE prevent_sigpipe = PreventSIGPIPE::No) | ||||
|         : m_prevent_sigpipe(prevent_sigpipe == PreventSIGPIPE::Yes) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     static ErrorOr<int> create_fd(SocketDomain, SocketType); | ||||
|     // FIXME: This will need to be updated when IPv6 socket arrives. Perhaps a
 | ||||
|     //        base class for all address types is appropriate.
 | ||||
|     static ErrorOr<IPv4Address> resolve_host(DeprecatedString const&, SocketType); | ||||
| 
 | ||||
|     static ErrorOr<void> connect_local(int fd, DeprecatedString const& path); | ||||
|     static ErrorOr<void> connect_inet(int fd, SocketAddress const&); | ||||
| 
 | ||||
|     int default_flags() const | ||||
|     { | ||||
|         int flags = 0; | ||||
|         if (m_prevent_sigpipe) | ||||
|             flags |= MSG_NOSIGNAL; | ||||
|         return flags; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     bool m_prevent_sigpipe { false }; | ||||
| }; | ||||
| 
 | ||||
| /// A reusable socket maintains state about being connected in addition to
 | ||||
| /// normal Socket capabilities, and can be reconnected once disconnected.
 | ||||
| class ReusableSocket : public Socket { | ||||
| public: | ||||
|     /// Returns whether the socket is currently connected.
 | ||||
|     virtual bool is_connected() = 0; | ||||
|     /// Reconnects the socket to the given host and port. Returns EALREADY if
 | ||||
|     /// is_connected() is true.
 | ||||
|     virtual ErrorOr<void> reconnect(DeprecatedString const& host, u16 port) = 0; | ||||
|     /// Connects the socket to the given socket address (IP address + port).
 | ||||
|     /// Returns EALREADY is_connected() is true.
 | ||||
|     virtual ErrorOr<void> reconnect(SocketAddress const&) = 0; | ||||
| }; | ||||
| 
 | ||||
| // Concrete classes.
 | ||||
| 
 | ||||
| enum class OpenMode : unsigned { | ||||
|  | @ -204,407 +117,6 @@ private: | |||
|     ShouldCloseFileDescriptor m_should_close_file_descriptor { ShouldCloseFileDescriptor::Yes }; | ||||
| }; | ||||
| 
 | ||||
| class PosixSocketHelper { | ||||
|     AK_MAKE_NONCOPYABLE(PosixSocketHelper); | ||||
| 
 | ||||
| public: | ||||
|     template<typename T> | ||||
|     PosixSocketHelper(Badge<T>) | ||||
|     requires(IsBaseOf<Socket, T>) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     PosixSocketHelper(PosixSocketHelper&& other) | ||||
|     { | ||||
|         operator=(move(other)); | ||||
|     } | ||||
| 
 | ||||
|     PosixSocketHelper& operator=(PosixSocketHelper&& other) | ||||
|     { | ||||
|         m_fd = exchange(other.m_fd, -1); | ||||
|         m_last_read_was_eof = exchange(other.m_last_read_was_eof, false); | ||||
|         m_notifier = move(other.m_notifier); | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
|     int fd() const { return m_fd; } | ||||
|     void set_fd(int fd) { m_fd = fd; } | ||||
| 
 | ||||
|     ErrorOr<Bytes> read(Bytes, int flags); | ||||
|     ErrorOr<size_t> write(ReadonlyBytes, int flags); | ||||
| 
 | ||||
|     bool is_eof() const { return !is_open() || m_last_read_was_eof; } | ||||
|     bool is_open() const { return m_fd != -1; } | ||||
|     void close(); | ||||
| 
 | ||||
|     ErrorOr<size_t> pending_bytes() const; | ||||
|     ErrorOr<bool> can_read_without_blocking(int timeout) const; | ||||
| 
 | ||||
|     ErrorOr<void> set_blocking(bool enabled); | ||||
|     ErrorOr<void> set_close_on_exec(bool enabled); | ||||
|     ErrorOr<void> set_receive_timeout(Time timeout); | ||||
| 
 | ||||
|     void setup_notifier(); | ||||
|     RefPtr<Core::Notifier> notifier() { return m_notifier; } | ||||
| 
 | ||||
| private: | ||||
|     int m_fd { -1 }; | ||||
|     bool m_last_read_was_eof { false }; | ||||
|     RefPtr<Core::Notifier> m_notifier; | ||||
| }; | ||||
| 
 | ||||
| class TCPSocket final : public Socket { | ||||
| public: | ||||
|     static ErrorOr<NonnullOwnPtr<TCPSocket>> connect(DeprecatedString const& host, u16 port); | ||||
|     static ErrorOr<NonnullOwnPtr<TCPSocket>> connect(SocketAddress const& address); | ||||
|     static ErrorOr<NonnullOwnPtr<TCPSocket>> adopt_fd(int fd); | ||||
| 
 | ||||
|     TCPSocket(TCPSocket&& other) | ||||
|         : Socket(static_cast<Socket&&>(other)) | ||||
|         , m_helper(move(other.m_helper)) | ||||
|     { | ||||
|         if (is_open()) | ||||
|             setup_notifier(); | ||||
|     } | ||||
| 
 | ||||
|     TCPSocket& operator=(TCPSocket&& other) | ||||
|     { | ||||
|         Socket::operator=(static_cast<Socket&&>(other)); | ||||
|         m_helper = move(other.m_helper); | ||||
|         if (is_open()) | ||||
|             setup_notifier(); | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
|     virtual ErrorOr<Bytes> read(Bytes buffer) override { return m_helper.read(buffer, default_flags()); } | ||||
|     virtual ErrorOr<size_t> write(ReadonlyBytes buffer) override { return m_helper.write(buffer, default_flags()); } | ||||
|     virtual bool is_eof() const override { return m_helper.is_eof(); } | ||||
|     virtual bool is_open() const override { return m_helper.is_open(); }; | ||||
|     virtual void close() override { m_helper.close(); }; | ||||
|     virtual ErrorOr<size_t> pending_bytes() const override { return m_helper.pending_bytes(); } | ||||
|     virtual ErrorOr<bool> can_read_without_blocking(int timeout = 0) const override { return m_helper.can_read_without_blocking(timeout); } | ||||
|     virtual void set_notifications_enabled(bool enabled) override | ||||
|     { | ||||
|         if (auto notifier = m_helper.notifier()) | ||||
|             notifier->set_enabled(enabled); | ||||
|     } | ||||
|     ErrorOr<void> set_blocking(bool enabled) override { return m_helper.set_blocking(enabled); } | ||||
|     ErrorOr<void> set_close_on_exec(bool enabled) override { return m_helper.set_close_on_exec(enabled); } | ||||
| 
 | ||||
|     virtual ~TCPSocket() override { close(); } | ||||
| 
 | ||||
| private: | ||||
|     TCPSocket(PreventSIGPIPE prevent_sigpipe = PreventSIGPIPE::No) | ||||
|         : Socket(prevent_sigpipe) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     void setup_notifier() | ||||
|     { | ||||
|         VERIFY(is_open()); | ||||
| 
 | ||||
|         m_helper.setup_notifier(); | ||||
|         m_helper.notifier()->on_ready_to_read = [this] { | ||||
|             if (on_ready_to_read) | ||||
|                 on_ready_to_read(); | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     PosixSocketHelper m_helper { Badge<TCPSocket> {} }; | ||||
| }; | ||||
| 
 | ||||
| class UDPSocket final : public Socket { | ||||
| public: | ||||
|     static ErrorOr<NonnullOwnPtr<UDPSocket>> connect(DeprecatedString const& host, u16 port, Optional<Time> timeout = {}); | ||||
|     static ErrorOr<NonnullOwnPtr<UDPSocket>> connect(SocketAddress const& address, Optional<Time> timeout = {}); | ||||
| 
 | ||||
|     UDPSocket(UDPSocket&& other) | ||||
|         : Socket(static_cast<Socket&&>(other)) | ||||
|         , m_helper(move(other.m_helper)) | ||||
|     { | ||||
|         if (is_open()) | ||||
|             setup_notifier(); | ||||
|     } | ||||
| 
 | ||||
|     UDPSocket& operator=(UDPSocket&& other) | ||||
|     { | ||||
|         Socket::operator=(static_cast<Socket&&>(other)); | ||||
|         m_helper = move(other.m_helper); | ||||
|         if (is_open()) | ||||
|             setup_notifier(); | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
|     virtual ErrorOr<Bytes> read(Bytes buffer) override | ||||
|     { | ||||
|         auto pending_bytes = TRY(this->pending_bytes()); | ||||
|         if (pending_bytes > buffer.size()) { | ||||
|             // With UDP datagrams, reading a datagram into a buffer that's
 | ||||
|             // smaller than the datagram's size will cause the rest of the
 | ||||
|             // datagram to be discarded. That's not very nice, so let's bail
 | ||||
|             // early, telling the caller that he should allocate a bigger
 | ||||
|             // buffer.
 | ||||
|             return Error::from_errno(EMSGSIZE); | ||||
|         } | ||||
| 
 | ||||
|         return m_helper.read(buffer, default_flags()); | ||||
|     } | ||||
| 
 | ||||
|     virtual ErrorOr<size_t> write(ReadonlyBytes buffer) override { return m_helper.write(buffer, default_flags()); } | ||||
|     virtual bool is_eof() const override { return m_helper.is_eof(); } | ||||
|     virtual bool is_open() const override { return m_helper.is_open(); } | ||||
|     virtual void close() override { m_helper.close(); } | ||||
|     virtual ErrorOr<size_t> pending_bytes() const override { return m_helper.pending_bytes(); } | ||||
|     virtual ErrorOr<bool> can_read_without_blocking(int timeout = 0) const override { return m_helper.can_read_without_blocking(timeout); } | ||||
|     virtual void set_notifications_enabled(bool enabled) override | ||||
|     { | ||||
|         if (auto notifier = m_helper.notifier()) | ||||
|             notifier->set_enabled(enabled); | ||||
|     } | ||||
|     ErrorOr<void> set_blocking(bool enabled) override { return m_helper.set_blocking(enabled); } | ||||
|     ErrorOr<void> set_close_on_exec(bool enabled) override { return m_helper.set_close_on_exec(enabled); } | ||||
| 
 | ||||
|     virtual ~UDPSocket() override { close(); } | ||||
| 
 | ||||
| private: | ||||
|     UDPSocket(PreventSIGPIPE prevent_sigpipe = PreventSIGPIPE::No) | ||||
|         : Socket(prevent_sigpipe) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     void setup_notifier() | ||||
|     { | ||||
|         VERIFY(is_open()); | ||||
| 
 | ||||
|         m_helper.setup_notifier(); | ||||
|         m_helper.notifier()->on_ready_to_read = [this] { | ||||
|             if (on_ready_to_read) | ||||
|                 on_ready_to_read(); | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     PosixSocketHelper m_helper { Badge<UDPSocket> {} }; | ||||
| }; | ||||
| 
 | ||||
| class LocalSocket final : public Socket { | ||||
| public: | ||||
|     static ErrorOr<NonnullOwnPtr<LocalSocket>> connect(DeprecatedString const& path, PreventSIGPIPE = PreventSIGPIPE::No); | ||||
|     static ErrorOr<NonnullOwnPtr<LocalSocket>> adopt_fd(int fd, PreventSIGPIPE = PreventSIGPIPE::No); | ||||
| 
 | ||||
|     LocalSocket(LocalSocket&& other) | ||||
|         : Socket(static_cast<Socket&&>(other)) | ||||
|         , m_helper(move(other.m_helper)) | ||||
|     { | ||||
|         if (is_open()) | ||||
|             setup_notifier(); | ||||
|     } | ||||
| 
 | ||||
|     LocalSocket& operator=(LocalSocket&& other) | ||||
|     { | ||||
|         Socket::operator=(static_cast<Socket&&>(other)); | ||||
|         m_helper = move(other.m_helper); | ||||
|         if (is_open()) | ||||
|             setup_notifier(); | ||||
| 
 | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
|     virtual ErrorOr<Bytes> read(Bytes buffer) override { return m_helper.read(buffer, default_flags()); } | ||||
|     virtual ErrorOr<size_t> write(ReadonlyBytes buffer) override { return m_helper.write(buffer, default_flags()); } | ||||
|     virtual bool is_eof() const override { return m_helper.is_eof(); } | ||||
|     virtual bool is_open() const override { return m_helper.is_open(); } | ||||
|     virtual void close() override { m_helper.close(); } | ||||
|     virtual ErrorOr<size_t> pending_bytes() const override { return m_helper.pending_bytes(); } | ||||
|     virtual ErrorOr<bool> can_read_without_blocking(int timeout = 0) const override { return m_helper.can_read_without_blocking(timeout); } | ||||
|     virtual ErrorOr<void> set_blocking(bool enabled) override { return m_helper.set_blocking(enabled); } | ||||
|     virtual ErrorOr<void> set_close_on_exec(bool enabled) override { return m_helper.set_close_on_exec(enabled); } | ||||
|     virtual void set_notifications_enabled(bool enabled) override | ||||
|     { | ||||
|         if (auto notifier = m_helper.notifier()) | ||||
|             notifier->set_enabled(enabled); | ||||
|     } | ||||
| 
 | ||||
|     ErrorOr<int> receive_fd(int flags); | ||||
|     ErrorOr<void> send_fd(int fd); | ||||
|     ErrorOr<pid_t> peer_pid() const; | ||||
|     ErrorOr<Bytes> read_without_waiting(Bytes buffer); | ||||
| 
 | ||||
|     /// Release the fd associated with this LocalSocket. After the fd is
 | ||||
|     /// released, the socket will be considered "closed" and all operations done
 | ||||
|     /// on it will fail with ENOTCONN. Fails with ENOTCONN if the socket is
 | ||||
|     /// already closed.
 | ||||
|     ErrorOr<int> release_fd(); | ||||
| 
 | ||||
|     Optional<int> fd() const; | ||||
|     RefPtr<Core::Notifier> notifier() { return m_helper.notifier(); } | ||||
| 
 | ||||
|     virtual ~LocalSocket() { close(); } | ||||
| 
 | ||||
| private: | ||||
|     LocalSocket(PreventSIGPIPE prevent_sigpipe = PreventSIGPIPE::No) | ||||
|         : Socket(prevent_sigpipe) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     void setup_notifier() | ||||
|     { | ||||
|         VERIFY(is_open()); | ||||
| 
 | ||||
|         m_helper.setup_notifier(); | ||||
|         m_helper.notifier()->on_ready_to_read = [this] { | ||||
|             if (on_ready_to_read) | ||||
|                 on_ready_to_read(); | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     PosixSocketHelper m_helper { Badge<LocalSocket> {} }; | ||||
| }; | ||||
| 
 | ||||
| template<typename T> | ||||
| concept SocketLike = IsBaseOf<Socket, T>; | ||||
| 
 | ||||
| class BufferedSocketBase : public Socket { | ||||
| public: | ||||
|     virtual ErrorOr<StringView> read_line(Bytes buffer) = 0; | ||||
|     virtual ErrorOr<Bytes> read_until(Bytes buffer, StringView candidate) = 0; | ||||
|     virtual ErrorOr<bool> can_read_line() = 0; | ||||
|     virtual size_t buffer_size() const = 0; | ||||
| }; | ||||
| 
 | ||||
| template<SocketLike T> | ||||
| class BufferedSocket final : public BufferedSocketBase { | ||||
|     friend BufferedHelper<T>; | ||||
| 
 | ||||
| public: | ||||
|     static ErrorOr<NonnullOwnPtr<BufferedSocket<T>>> create(NonnullOwnPtr<T> stream, size_t buffer_size = 16384) | ||||
|     { | ||||
|         return BufferedHelper<T>::template create_buffered<BufferedSocket>(move(stream), buffer_size); | ||||
|     } | ||||
| 
 | ||||
|     BufferedSocket(BufferedSocket&& other) | ||||
|         : BufferedSocketBase(static_cast<BufferedSocketBase&&>(other)) | ||||
|         , m_helper(move(other.m_helper)) | ||||
|     { | ||||
|         setup_notifier(); | ||||
|     } | ||||
| 
 | ||||
|     BufferedSocket& operator=(BufferedSocket&& other) | ||||
|     { | ||||
|         Socket::operator=(static_cast<Socket&&>(other)); | ||||
|         m_helper = move(other.m_helper); | ||||
| 
 | ||||
|         setup_notifier(); | ||||
|         return *this; | ||||
|     } | ||||
| 
 | ||||
|     virtual ErrorOr<Bytes> read(Bytes buffer) override { return m_helper.read(move(buffer)); } | ||||
|     virtual ErrorOr<size_t> write(ReadonlyBytes buffer) override { return m_helper.stream().write(buffer); } | ||||
|     virtual bool is_eof() const override { return m_helper.is_eof(); } | ||||
|     virtual bool is_open() const override { return m_helper.stream().is_open(); } | ||||
|     virtual void close() override { m_helper.stream().close(); } | ||||
|     virtual ErrorOr<size_t> pending_bytes() const override | ||||
|     { | ||||
|         return TRY(m_helper.stream().pending_bytes()) + m_helper.buffered_data_size(); | ||||
|     } | ||||
|     virtual ErrorOr<bool> can_read_without_blocking(int timeout = 0) const override { return m_helper.buffered_data_size() > 0 || TRY(m_helper.stream().can_read_without_blocking(timeout)); } | ||||
|     virtual ErrorOr<void> set_blocking(bool enabled) override { return m_helper.stream().set_blocking(enabled); } | ||||
|     virtual ErrorOr<void> set_close_on_exec(bool enabled) override { return m_helper.stream().set_close_on_exec(enabled); } | ||||
|     virtual void set_notifications_enabled(bool enabled) override { m_helper.stream().set_notifications_enabled(enabled); } | ||||
| 
 | ||||
|     virtual ErrorOr<StringView> read_line(Bytes buffer) override { return m_helper.read_line(move(buffer)); } | ||||
|     virtual ErrorOr<Bytes> read_until(Bytes buffer, StringView candidate) override { return m_helper.read_until(move(buffer), move(candidate)); } | ||||
|     template<size_t N> | ||||
|     ErrorOr<Bytes> read_until_any_of(Bytes buffer, Array<StringView, N> candidates) { return m_helper.read_until_any_of(move(buffer), move(candidates)); } | ||||
|     virtual ErrorOr<bool> can_read_line() override { return m_helper.can_read_line(); } | ||||
| 
 | ||||
|     virtual size_t buffer_size() const override { return m_helper.buffer_size(); } | ||||
| 
 | ||||
|     virtual ~BufferedSocket() override = default; | ||||
| 
 | ||||
| private: | ||||
|     BufferedSocket(NonnullOwnPtr<T> stream, CircularBuffer buffer) | ||||
|         : m_helper(Badge<BufferedSocket<T>> {}, move(stream), move(buffer)) | ||||
|     { | ||||
|         setup_notifier(); | ||||
|     } | ||||
| 
 | ||||
|     void setup_notifier() | ||||
|     { | ||||
|         m_helper.stream().on_ready_to_read = [this] { | ||||
|             if (on_ready_to_read) | ||||
|                 on_ready_to_read(); | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     BufferedHelper<T> m_helper; | ||||
| }; | ||||
| 
 | ||||
| using BufferedFile = BufferedSeekable<File>; | ||||
| using BufferedTCPSocket = BufferedSocket<TCPSocket>; | ||||
| using BufferedUDPSocket = BufferedSocket<UDPSocket>; | ||||
| using BufferedLocalSocket = BufferedSocket<LocalSocket>; | ||||
| 
 | ||||
| /// A BasicReusableSocket allows one to use one of the base Core::Stream classes
 | ||||
| /// as a ReusableSocket. It does not preserve any connection state or options,
 | ||||
| /// and instead just recreates the stream when reconnecting.
 | ||||
| template<SocketLike T> | ||||
| class BasicReusableSocket final : public ReusableSocket { | ||||
| public: | ||||
|     static ErrorOr<NonnullOwnPtr<BasicReusableSocket<T>>> connect(DeprecatedString const& host, u16 port) | ||||
|     { | ||||
|         return make<BasicReusableSocket<T>>(TRY(T::connect(host, port))); | ||||
|     } | ||||
| 
 | ||||
|     static ErrorOr<NonnullOwnPtr<BasicReusableSocket<T>>> connect(SocketAddress const& address) | ||||
|     { | ||||
|         return make<BasicReusableSocket<T>>(TRY(T::connect(address))); | ||||
|     } | ||||
| 
 | ||||
|     virtual bool is_connected() override | ||||
|     { | ||||
|         return m_socket.is_open(); | ||||
|     } | ||||
| 
 | ||||
|     virtual ErrorOr<void> reconnect(DeprecatedString const& host, u16 port) override | ||||
|     { | ||||
|         if (is_connected()) | ||||
|             return Error::from_errno(EALREADY); | ||||
| 
 | ||||
|         m_socket = TRY(T::connect(host, port)); | ||||
|         return {}; | ||||
|     } | ||||
| 
 | ||||
|     virtual ErrorOr<void> reconnect(SocketAddress const& address) override | ||||
|     { | ||||
|         if (is_connected()) | ||||
|             return Error::from_errno(EALREADY); | ||||
| 
 | ||||
|         m_socket = TRY(T::connect(address)); | ||||
|         return {}; | ||||
|     } | ||||
| 
 | ||||
|     virtual ErrorOr<Bytes> read(Bytes buffer) override { return m_socket.read(move(buffer)); } | ||||
|     virtual ErrorOr<size_t> write(ReadonlyBytes buffer) override { return m_socket.write(buffer); } | ||||
|     virtual bool is_eof() const override { return m_socket.is_eof(); } | ||||
|     virtual bool is_open() const override { return m_socket.is_open(); } | ||||
|     virtual void close() override { m_socket.close(); } | ||||
|     virtual ErrorOr<size_t> pending_bytes() const override { return m_socket.pending_bytes(); } | ||||
|     virtual ErrorOr<bool> can_read_without_blocking(int timeout = 0) const override { return m_socket.can_read_without_blocking(timeout); } | ||||
|     virtual ErrorOr<void> set_blocking(bool enabled) override { return m_socket.set_blocking(enabled); } | ||||
|     virtual ErrorOr<void> set_close_on_exec(bool enabled) override { return m_socket.set_close_on_exec(enabled); } | ||||
| 
 | ||||
| private: | ||||
|     BasicReusableSocket(NonnullOwnPtr<T> socket) | ||||
|         : m_socket(move(socket)) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     NonnullOwnPtr<T> m_socket; | ||||
| }; | ||||
| 
 | ||||
| using ReusableTCPSocket = BasicReusableSocket<TCPSocket>; | ||||
| using ReusableUDPSocket = BasicReusableSocket<UDPSocket>; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ | |||
|  */ | ||||
| 
 | ||||
| #include "SystemServerTakeover.h" | ||||
| #include <LibCore/Socket.h> | ||||
| #include <LibCore/System.h> | ||||
| 
 | ||||
| namespace Core { | ||||
|  | @ -34,7 +35,7 @@ static void parse_sockets_from_system_server() | |||
|     unsetenv(socket_takeover); | ||||
| } | ||||
| 
 | ||||
| ErrorOr<NonnullOwnPtr<Core::Stream::LocalSocket>> take_over_socket_from_system_server(DeprecatedString const& socket_path) | ||||
| ErrorOr<NonnullOwnPtr<Core::LocalSocket>> take_over_socket_from_system_server(DeprecatedString const& socket_path) | ||||
| { | ||||
|     if (!s_overtaken_sockets_parsed) | ||||
|         parse_sockets_from_system_server(); | ||||
|  | @ -57,7 +58,7 @@ ErrorOr<NonnullOwnPtr<Core::Stream::LocalSocket>> take_over_socket_from_system_s | |||
|     if (!S_ISSOCK(stat.st_mode)) | ||||
|         return Error::from_string_literal("The fd we got from SystemServer is not a socket"); | ||||
| 
 | ||||
|     auto socket = TRY(Core::Stream::LocalSocket::adopt_fd(fd)); | ||||
|     auto socket = TRY(Core::LocalSocket::adopt_fd(fd)); | ||||
|     // It had to be !CLOEXEC for obvious reasons, but we
 | ||||
|     // don't need it to be !CLOEXEC anymore, so set the
 | ||||
|     // CLOEXEC flag now.
 | ||||
|  |  | |||
|  | @ -10,6 +10,6 @@ | |||
| 
 | ||||
| namespace Core { | ||||
| 
 | ||||
| ErrorOr<NonnullOwnPtr<Core::Stream::LocalSocket>> take_over_socket_from_system_server(DeprecatedString const& socket_path = {}); | ||||
| ErrorOr<NonnullOwnPtr<Core::LocalSocket>> take_over_socket_from_system_server(DeprecatedString const& socket_path = {}); | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ | |||
| #include <AK/IPv4Address.h> | ||||
| #include <AK/Types.h> | ||||
| #include <LibCore/Notifier.h> | ||||
| #include <LibCore/Socket.h> | ||||
| #include <LibCore/System.h> | ||||
| #include <LibCore/TCPServer.h> | ||||
| 
 | ||||
|  | @ -74,7 +75,7 @@ ErrorOr<void> TCPServer::set_blocking(bool blocking) | |||
|     return {}; | ||||
| } | ||||
| 
 | ||||
| ErrorOr<NonnullOwnPtr<Stream::TCPSocket>> TCPServer::accept() | ||||
| ErrorOr<NonnullOwnPtr<TCPSocket>> TCPServer::accept() | ||||
| { | ||||
|     VERIFY(m_listening); | ||||
|     sockaddr_in in; | ||||
|  | @ -85,7 +86,7 @@ ErrorOr<NonnullOwnPtr<Stream::TCPSocket>> TCPServer::accept() | |||
|     int accepted_fd = TRY(Core::System::accept(m_fd, (sockaddr*)&in, &in_size)); | ||||
| #endif | ||||
| 
 | ||||
|     auto socket = TRY(Stream::TCPSocket::adopt_fd(accepted_fd)); | ||||
|     auto socket = TRY(TCPSocket::adopt_fd(accepted_fd)); | ||||
| 
 | ||||
| #ifdef AK_OS_MACOS | ||||
|     // FIXME: Ideally, we should let the caller decide whether it wants the
 | ||||
|  |  | |||
|  | @ -29,7 +29,7 @@ public: | |||
|     ErrorOr<void> listen(IPv4Address const& address, u16 port, AllowAddressReuse = AllowAddressReuse::No); | ||||
|     ErrorOr<void> set_blocking(bool blocking); | ||||
| 
 | ||||
|     ErrorOr<NonnullOwnPtr<Stream::TCPSocket>> accept(); | ||||
|     ErrorOr<NonnullOwnPtr<TCPSocket>> accept(); | ||||
| 
 | ||||
|     Optional<IPv4Address> local_address() const; | ||||
|     Optional<u16> local_port() const; | ||||
|  |  | |||
|  | @ -37,7 +37,7 @@ class ConnectionToLaunchServer final | |||
|     , public LaunchClientEndpoint { | ||||
|     IPC_CLIENT_CONNECTION(ConnectionToLaunchServer, "/tmp/session/%sid/portal/launch"sv) | ||||
| private: | ||||
|     ConnectionToLaunchServer(NonnullOwnPtr<Core::Stream::LocalSocket> socket) | ||||
|     ConnectionToLaunchServer(NonnullOwnPtr<Core::LocalSocket> socket) | ||||
|         : IPC::ConnectionToServer<LaunchClientEndpoint, LaunchServerEndpoint>(*this, move(socket)) | ||||
|     { | ||||
|     } | ||||
|  |  | |||
|  | @ -62,7 +62,7 @@ protected: | |||
|     void die() override; | ||||
| 
 | ||||
| private: | ||||
|     explicit Client(NonnullOwnPtr<Core::Stream::LocalSocket> socket) | ||||
|     explicit Client(NonnullOwnPtr<Core::LocalSocket> socket) | ||||
|         : IPC::ConnectionToServer<FileSystemAccessClientEndpoint, FileSystemAccessServerEndpoint>(*this, move(socket)) | ||||
|     { | ||||
|     } | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ class ConnectionToClipboardServer final | |||
|     IPC_CLIENT_CONNECTION(ConnectionToClipboardServer, "/tmp/session/%sid/portal/clipboard"sv) | ||||
| 
 | ||||
| private: | ||||
|     ConnectionToClipboardServer(NonnullOwnPtr<Core::Stream::LocalSocket> socket) | ||||
|     ConnectionToClipboardServer(NonnullOwnPtr<Core::LocalSocket> socket) | ||||
|         : IPC::ConnectionToServer<ClipboardClientEndpoint, ClipboardServerEndpoint>(*this, move(socket)) | ||||
|     { | ||||
|     } | ||||
|  |  | |||
|  | @ -22,7 +22,7 @@ public: | |||
|     static ConnectionToWindowManagerServer& the(); | ||||
| 
 | ||||
| private: | ||||
|     ConnectionToWindowManagerServer(NonnullOwnPtr<Core::Stream::LocalSocket> socket) | ||||
|     ConnectionToWindowManagerServer(NonnullOwnPtr<Core::LocalSocket> socket) | ||||
|         : IPC::ConnectionToServer<WindowManagerClientEndpoint, WindowManagerServerEndpoint>(*this, move(socket)) | ||||
|     { | ||||
|     } | ||||
|  |  | |||
|  | @ -42,7 +42,7 @@ static void set_system_theme_from_anonymous_buffer(Core::AnonymousBuffer buffer) | |||
|     Application::the()->set_system_palette(buffer); | ||||
| } | ||||
| 
 | ||||
| ConnectionToWindowServer::ConnectionToWindowServer(NonnullOwnPtr<Core::Stream::LocalSocket> socket) | ||||
| ConnectionToWindowServer::ConnectionToWindowServer(NonnullOwnPtr<Core::LocalSocket> socket) | ||||
|     : IPC::ConnectionToServer<WindowClientEndpoint, WindowServerEndpoint>(*this, move(socket)) | ||||
| { | ||||
|     // NOTE: WindowServer automatically sends a "fast_greet" message to us when we connect.
 | ||||
|  |  | |||
|  | @ -22,7 +22,7 @@ public: | |||
|     i32 expose_client_id() { return m_client_id; } | ||||
| 
 | ||||
| private: | ||||
|     ConnectionToWindowServer(NonnullOwnPtr<Core::Stream::LocalSocket>); | ||||
|     ConnectionToWindowServer(NonnullOwnPtr<Core::LocalSocket>); | ||||
| 
 | ||||
|     virtual void fast_greet(Vector<Gfx::IntRect> const&, u32, u32, u32, Core::AnonymousBuffer const&, DeprecatedString const&, DeprecatedString const&, DeprecatedString const&, Vector<bool> const&, i32) override; | ||||
|     virtual void paint(i32, Gfx::IntSize, Vector<Gfx::IntRect> const&) override; | ||||
|  |  | |||
|  | @ -26,7 +26,7 @@ public: | |||
|     } | ||||
| 
 | ||||
| private: | ||||
|     explicit ConnectionToNotificationServer(NonnullOwnPtr<Core::Stream::LocalSocket> socket, Notification* notification) | ||||
|     explicit ConnectionToNotificationServer(NonnullOwnPtr<Core::LocalSocket> socket, Notification* notification) | ||||
|         : IPC::ConnectionToServer<NotificationClientEndpoint, NotificationServerEndpoint>(*this, move(socket)) | ||||
|         , m_notification(notification) | ||||
|     { | ||||
|  |  | |||
|  | @ -21,10 +21,10 @@ Job::Job(GeminiRequest const& request, AK::Stream& output_stream) | |||
| { | ||||
| } | ||||
| 
 | ||||
| void Job::start(Core::Stream::Socket& socket) | ||||
| void Job::start(Core::Socket& socket) | ||||
| { | ||||
|     VERIFY(!m_socket); | ||||
|     m_socket = verify_cast<Core::Stream::BufferedSocketBase>(&socket); | ||||
|     m_socket = verify_cast<Core::BufferedSocketBase>(&socket); | ||||
|     on_socket_connected(); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ | |||
| 
 | ||||
| #include <AK/Optional.h> | ||||
| #include <LibCore/NetworkJob.h> | ||||
| #include <LibCore/Socket.h> | ||||
| #include <LibGemini/GeminiRequest.h> | ||||
| #include <LibGemini/GeminiResponse.h> | ||||
| 
 | ||||
|  | @ -20,14 +21,14 @@ public: | |||
|     explicit Job(GeminiRequest const&, AK::Stream&); | ||||
|     virtual ~Job() override = default; | ||||
| 
 | ||||
|     virtual void start(Core::Stream::Socket&) override; | ||||
|     virtual void start(Core::Socket&) override; | ||||
|     virtual void shutdown(ShutdownMode) override; | ||||
| 
 | ||||
|     GeminiResponse* response() { return static_cast<GeminiResponse*>(Core::NetworkJob::response()); } | ||||
|     GeminiResponse const* response() const { return static_cast<GeminiResponse const*>(Core::NetworkJob::response()); } | ||||
| 
 | ||||
|     const URL& url() const { return m_request.url(); } | ||||
|     Core::Stream::Socket const* socket() const { return m_socket; } | ||||
|     Core::Socket const* socket() const { return m_socket; } | ||||
| 
 | ||||
|     ErrorOr<size_t> response_length() const; | ||||
| 
 | ||||
|  | @ -56,7 +57,7 @@ protected: | |||
|     Vector<ByteBuffer, 2> m_received_buffers; | ||||
|     size_t m_received_size { 0 }; | ||||
|     size_t m_buffered_size { 0 }; | ||||
|     Core::Stream::BufferedSocketBase* m_socket { nullptr }; | ||||
|     Core::BufferedSocketBase* m_socket { nullptr }; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -92,10 +92,10 @@ Job::Job(HttpRequest&& request, AK::Stream& output_stream) | |||
| { | ||||
| } | ||||
| 
 | ||||
| void Job::start(Core::Stream::Socket& socket) | ||||
| void Job::start(Core::Socket& socket) | ||||
| { | ||||
|     VERIFY(!m_socket); | ||||
|     m_socket = static_cast<Core::Stream::BufferedSocketBase*>(&socket); | ||||
|     m_socket = static_cast<Core::BufferedSocketBase*>(&socket); | ||||
|     dbgln_if(HTTPJOB_DEBUG, "Reusing previous connection for {}", url()); | ||||
|     deferred_invoke([this] { | ||||
|         dbgln_if(HTTPJOB_DEBUG, "HttpJob: on_connected callback"); | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ | |||
| #include <AK/NonnullOwnPtrVector.h> | ||||
| #include <AK/Optional.h> | ||||
| #include <LibCore/NetworkJob.h> | ||||
| #include <LibCore/Socket.h> | ||||
| #include <LibHTTP/HttpRequest.h> | ||||
| #include <LibHTTP/HttpResponse.h> | ||||
| 
 | ||||
|  | @ -22,10 +23,10 @@ public: | |||
|     explicit Job(HttpRequest&&, AK::Stream&); | ||||
|     virtual ~Job() override = default; | ||||
| 
 | ||||
|     virtual void start(Core::Stream::Socket&) override; | ||||
|     virtual void start(Core::Socket&) override; | ||||
|     virtual void shutdown(ShutdownMode) override; | ||||
| 
 | ||||
|     Core::Stream::Socket const* socket() const { return m_socket; } | ||||
|     Core::Socket const* socket() const { return m_socket; } | ||||
|     URL url() const { return m_request.url(); } | ||||
| 
 | ||||
|     HttpResponse* response() { return static_cast<HttpResponse*>(Core::NetworkJob::response()); } | ||||
|  | @ -50,7 +51,7 @@ protected: | |||
| 
 | ||||
|     HttpRequest m_request; | ||||
|     State m_state { State::InStatus }; | ||||
|     Core::Stream::BufferedSocketBase* m_socket { nullptr }; | ||||
|     Core::BufferedSocketBase* m_socket { nullptr }; | ||||
|     bool m_legacy_connection { false }; | ||||
|     int m_code { -1 }; | ||||
|     HashMap<DeprecatedString, DeprecatedString, CaseInsensitiveStringTraits> m_headers; | ||||
|  |  | |||
|  | @ -10,7 +10,7 @@ | |||
| 
 | ||||
| namespace IMAP { | ||||
| 
 | ||||
| Client::Client(StringView host, u16 port, NonnullOwnPtr<Core::Stream::Socket> socket) | ||||
| Client::Client(StringView host, u16 port, NonnullOwnPtr<Core::Socket> socket) | ||||
|     : m_host(host) | ||||
|     , m_port(port) | ||||
|     , m_socket(move(socket)) | ||||
|  | @ -49,7 +49,7 @@ ErrorOr<NonnullOwnPtr<Client>> Client::connect_tls(StringView host, u16 port) | |||
| 
 | ||||
| ErrorOr<NonnullOwnPtr<Client>> Client::connect_plaintext(StringView host, u16 port) | ||||
| { | ||||
|     auto socket = TRY(Core::Stream::TCPSocket::connect(host, port)); | ||||
|     auto socket = TRY(Core::TCPSocket::connect(host, port)); | ||||
|     dbgln("Connected to {}:{}", host, port); | ||||
|     return adopt_nonnull_own_or_enomem(new (nothrow) Client(host, port, move(socket))); | ||||
| } | ||||
|  |  | |||
|  | @ -60,7 +60,7 @@ public: | |||
|     Function<void(ResponseData&&)> unrequested_response_callback; | ||||
| 
 | ||||
| private: | ||||
|     Client(StringView host, u16 port, NonnullOwnPtr<Core::Stream::Socket>); | ||||
|     Client(StringView host, u16 port, NonnullOwnPtr<Core::Socket>); | ||||
|     void setup_callbacks(); | ||||
| 
 | ||||
|     ErrorOr<void> on_ready_to_receive(); | ||||
|  | @ -71,7 +71,7 @@ private: | |||
|     StringView m_host; | ||||
|     u16 m_port; | ||||
| 
 | ||||
|     NonnullOwnPtr<Core::Stream::Socket> m_socket; | ||||
|     NonnullOwnPtr<Core::Socket> m_socket; | ||||
|     RefPtr<Promise<Empty>> m_connect_pending {}; | ||||
| 
 | ||||
|     int m_current_command = 1; | ||||
|  |  | |||
|  | @ -21,7 +21,7 @@ struct CoreEventLoopDeferredInvoker final : public DeferredInvoker { | |||
|     } | ||||
| }; | ||||
| 
 | ||||
| ConnectionBase::ConnectionBase(IPC::Stub& local_stub, NonnullOwnPtr<Core::Stream::LocalSocket> socket, u32 local_endpoint_magic) | ||||
| ConnectionBase::ConnectionBase(IPC::Stub& local_stub, NonnullOwnPtr<Core::LocalSocket> socket, u32 local_endpoint_magic) | ||||
|     : m_local_stub(local_stub) | ||||
|     , m_socket(move(socket)) | ||||
|     , m_local_endpoint_magic(local_endpoint_magic) | ||||
|  | @ -35,12 +35,12 @@ void ConnectionBase::set_deferred_invoker(NonnullOwnPtr<DeferredInvoker> deferre | |||
|     m_deferred_invoker = move(deferred_invoker); | ||||
| } | ||||
| 
 | ||||
| void ConnectionBase::set_fd_passing_socket(NonnullOwnPtr<Core::Stream::LocalSocket> socket) | ||||
| void ConnectionBase::set_fd_passing_socket(NonnullOwnPtr<Core::LocalSocket> socket) | ||||
| { | ||||
|     m_fd_passing_socket = move(socket); | ||||
| } | ||||
| 
 | ||||
| Core::Stream::LocalSocket& ConnectionBase::fd_passing_socket() | ||||
| Core::LocalSocket& ConnectionBase::fd_passing_socket() | ||||
| { | ||||
|     if (m_fd_passing_socket) | ||||
|         return *m_fd_passing_socket; | ||||
|  |  | |||
|  | @ -13,6 +13,7 @@ | |||
| #include <LibCore/Event.h> | ||||
| #include <LibCore/EventLoop.h> | ||||
| #include <LibCore/Notifier.h> | ||||
| #include <LibCore/Socket.h> | ||||
| #include <LibCore/Stream.h> | ||||
| #include <LibCore/Timer.h> | ||||
| #include <LibIPC/Forward.h> | ||||
|  | @ -39,7 +40,7 @@ class ConnectionBase : public Core::Object { | |||
| public: | ||||
|     virtual ~ConnectionBase() override = default; | ||||
| 
 | ||||
|     void set_fd_passing_socket(NonnullOwnPtr<Core::Stream::LocalSocket>); | ||||
|     void set_fd_passing_socket(NonnullOwnPtr<Core::LocalSocket>); | ||||
|     void set_deferred_invoker(NonnullOwnPtr<DeferredInvoker>); | ||||
|     DeferredInvoker& deferred_invoker() { return *m_deferred_invoker; } | ||||
| 
 | ||||
|  | @ -49,11 +50,11 @@ public: | |||
|     void shutdown(); | ||||
|     virtual void die() { } | ||||
| 
 | ||||
|     Core::Stream::LocalSocket& socket() { return *m_socket; } | ||||
|     Core::Stream::LocalSocket& fd_passing_socket(); | ||||
|     Core::LocalSocket& socket() { return *m_socket; } | ||||
|     Core::LocalSocket& fd_passing_socket(); | ||||
| 
 | ||||
| protected: | ||||
|     explicit ConnectionBase(IPC::Stub&, NonnullOwnPtr<Core::Stream::LocalSocket>, u32 local_endpoint_magic); | ||||
|     explicit ConnectionBase(IPC::Stub&, NonnullOwnPtr<Core::LocalSocket>, u32 local_endpoint_magic); | ||||
| 
 | ||||
|     virtual void may_have_become_unresponsive() { } | ||||
|     virtual void did_become_responsive() { } | ||||
|  | @ -70,8 +71,8 @@ protected: | |||
| 
 | ||||
|     IPC::Stub& m_local_stub; | ||||
| 
 | ||||
|     NonnullOwnPtr<Core::Stream::LocalSocket> m_socket; | ||||
|     OwnPtr<Core::Stream::LocalSocket> m_fd_passing_socket; | ||||
|     NonnullOwnPtr<Core::LocalSocket> m_socket; | ||||
|     OwnPtr<Core::LocalSocket> m_fd_passing_socket; | ||||
| 
 | ||||
|     RefPtr<Core::Timer> m_responsiveness_timer; | ||||
| 
 | ||||
|  | @ -86,7 +87,7 @@ protected: | |||
| template<typename LocalEndpoint, typename PeerEndpoint> | ||||
| class Connection : public ConnectionBase { | ||||
| public: | ||||
|     Connection(IPC::Stub& local_stub, NonnullOwnPtr<Core::Stream::LocalSocket> socket) | ||||
|     Connection(IPC::Stub& local_stub, NonnullOwnPtr<Core::LocalSocket> socket) | ||||
|         : ConnectionBase(local_stub, move(socket), LocalEndpoint::static_magic()) | ||||
|     { | ||||
|         m_socket->on_ready_to_read = [this] { | ||||
|  |  | |||
|  | @ -26,7 +26,7 @@ public: | |||
|     using ServerStub = typename ServerEndpoint::Stub; | ||||
|     using IPCProxy = typename ClientEndpoint::template Proxy<ServerEndpoint>; | ||||
| 
 | ||||
|     ConnectionFromClient(ServerStub& stub, NonnullOwnPtr<Core::Stream::LocalSocket> socket, int client_id) | ||||
|     ConnectionFromClient(ServerStub& stub, NonnullOwnPtr<Core::LocalSocket> socket, int client_id) | ||||
|         : IPC::Connection<ServerEndpoint, ClientEndpoint>(stub, move(socket)) | ||||
|         , ClientEndpoint::template Proxy<ServerEndpoint>(*this, {}) | ||||
|         , m_client_id(client_id) | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ public: | |||
|     static ErrorOr<NonnullRefPtr<klass>> try_create(Args&&... args)                                    \ | ||||
|     {                                                                                                  \ | ||||
|         auto parsed_socket_path = TRY(Core::SessionManagement::parse_path_with_sid(socket_path));      \ | ||||
|         auto socket = TRY(Core::Stream::LocalSocket::connect(move(parsed_socket_path)));               \ | ||||
|         auto socket = TRY(Core::LocalSocket::connect(move(parsed_socket_path)));                       \ | ||||
|         /* We want to rate-limit our clients */                                                        \ | ||||
|         TRY(socket->set_blocking(true));                                                               \ | ||||
|                                                                                                        \ | ||||
|  | @ -34,7 +34,7 @@ public: | |||
|     using ClientStub = typename ClientEndpoint::Stub; | ||||
|     using IPCProxy = typename ServerEndpoint::template Proxy<ClientEndpoint>; | ||||
| 
 | ||||
|     ConnectionToServer(ClientStub& local_endpoint, NonnullOwnPtr<Core::Stream::LocalSocket> socket) | ||||
|     ConnectionToServer(ClientStub& local_endpoint, NonnullOwnPtr<Core::LocalSocket> socket) | ||||
|         : Connection<ClientEndpoint, ServerEndpoint>(local_endpoint, move(socket)) | ||||
|         , ServerEndpoint::template Proxy<ClientEndpoint>(*this, {}) | ||||
|     { | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ | |||
| #include <LibCore/AnonymousBuffer.h> | ||||
| #include <LibCore/DateTime.h> | ||||
| #include <LibCore/Proxy.h> | ||||
| #include <LibCore/Socket.h> | ||||
| #include <LibIPC/Decoder.h> | ||||
| #include <LibIPC/Dictionary.h> | ||||
| #include <LibIPC/File.h> | ||||
|  |  | |||
|  | @ -32,7 +32,7 @@ inline ErrorOr<T> decode(Decoder&) | |||
| 
 | ||||
| class Decoder { | ||||
| public: | ||||
|     Decoder(AK::Stream& stream, Core::Stream::LocalSocket& socket) | ||||
|     Decoder(AK::Stream& stream, Core::LocalSocket& socket) | ||||
|         : m_stream(stream) | ||||
|         , m_socket(socket) | ||||
|     { | ||||
|  | @ -56,11 +56,11 @@ public: | |||
| 
 | ||||
|     ErrorOr<size_t> decode_size(); | ||||
| 
 | ||||
|     Core::Stream::LocalSocket& socket() { return m_socket; } | ||||
|     Core::LocalSocket& socket() { return m_socket; } | ||||
| 
 | ||||
| private: | ||||
|     AK::Stream& m_stream; | ||||
|     Core::Stream::LocalSocket& m_socket; | ||||
|     Core::LocalSocket& m_socket; | ||||
| }; | ||||
| 
 | ||||
| template<Arithmetic T> | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ | |||
| 
 | ||||
| namespace ImageDecoderClient { | ||||
| 
 | ||||
| Client::Client(NonnullOwnPtr<Core::Stream::LocalSocket> socket) | ||||
| Client::Client(NonnullOwnPtr<Core::LocalSocket> socket) | ||||
|     : IPC::ConnectionToServer<ImageDecoderClientEndpoint, ImageDecoderServerEndpoint>(*this, move(socket)) | ||||
| { | ||||
| } | ||||
|  |  | |||
|  | @ -35,7 +35,7 @@ public: | |||
|     Function<void()> on_death; | ||||
| 
 | ||||
| private: | ||||
|     Client(NonnullOwnPtr<Core::Stream::LocalSocket>); | ||||
|     Client(NonnullOwnPtr<Core::LocalSocket>); | ||||
| 
 | ||||
|     virtual void die() override; | ||||
| }; | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ | |||
| 
 | ||||
| namespace Protocol { | ||||
| 
 | ||||
| RequestClient::RequestClient(NonnullOwnPtr<Core::Stream::LocalSocket> socket) | ||||
| RequestClient::RequestClient(NonnullOwnPtr<Core::LocalSocket> socket) | ||||
|     : IPC::ConnectionToServer<RequestClientEndpoint, RequestServerEndpoint>(*this, move(socket)) | ||||
| { | ||||
| } | ||||
|  |  | |||
|  | @ -30,7 +30,7 @@ public: | |||
|     bool set_certificate(Badge<Request>, Request&, DeprecatedString, DeprecatedString); | ||||
| 
 | ||||
| private: | ||||
|     RequestClient(NonnullOwnPtr<Core::Stream::LocalSocket>); | ||||
|     RequestClient(NonnullOwnPtr<Core::LocalSocket>); | ||||
| 
 | ||||
|     virtual void request_progress(i32, Optional<u32> const&, u32) override; | ||||
|     virtual void request_finished(i32, bool, u32) override; | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ | |||
| 
 | ||||
| namespace Protocol { | ||||
| 
 | ||||
| WebSocketClient::WebSocketClient(NonnullOwnPtr<Core::Stream::LocalSocket> socket) | ||||
| WebSocketClient::WebSocketClient(NonnullOwnPtr<Core::LocalSocket> socket) | ||||
|     : IPC::ConnectionToServer<WebSocketClientEndpoint, WebSocketServerEndpoint>(*this, move(socket)) | ||||
| { | ||||
| } | ||||
|  |  | |||
|  | @ -30,7 +30,7 @@ public: | |||
|     bool set_certificate(Badge<WebSocket>, WebSocket&, DeprecatedString, DeprecatedString); | ||||
| 
 | ||||
| private: | ||||
|     WebSocketClient(NonnullOwnPtr<Core::Stream::LocalSocket>); | ||||
|     WebSocketClient(NonnullOwnPtr<Core::LocalSocket>); | ||||
| 
 | ||||
|     virtual void connected(i32) override; | ||||
|     virtual void received(i32, bool, ByteBuffer const&) override; | ||||
|  |  | |||
|  | @ -146,7 +146,7 @@ ErrorOr<NonnullRefPtr<SQLClient>> SQLClient::launch_server_and_create_client(Vec | |||
|     if (TRY(should_launch_server(pid_path))) | ||||
|         TRY(launch_server(socket_path, pid_path, move(candidate_server_paths))); | ||||
| 
 | ||||
|     auto socket = TRY(Core::Stream::LocalSocket::connect(move(socket_path))); | ||||
|     auto socket = TRY(Core::LocalSocket::connect(move(socket_path))); | ||||
|     TRY(socket->set_blocking(true)); | ||||
| 
 | ||||
|     return adopt_nonnull_ref_or_enomem(new (nothrow) SQLClient(move(socket))); | ||||
|  |  | |||
|  | @ -66,7 +66,7 @@ public: | |||
|     Function<void(ExecutionComplete)> on_results_exhausted; | ||||
| 
 | ||||
| private: | ||||
|     explicit SQLClient(NonnullOwnPtr<Core::Stream::LocalSocket> socket) | ||||
|     explicit SQLClient(NonnullOwnPtr<Core::LocalSocket> socket) | ||||
|         : IPC::ConnectionToServer<SQLClientEndpoint, SQLServerEndpoint>(*this, move(socket)) | ||||
|     { | ||||
|     } | ||||
|  |  | |||
|  | @ -75,7 +75,7 @@ ErrorOr<size_t> TLSv12::write(ReadonlyBytes bytes) | |||
| ErrorOr<NonnullOwnPtr<TLSv12>> TLSv12::connect(DeprecatedString const& host, u16 port, Options options) | ||||
| { | ||||
|     Core::EventLoop loop; | ||||
|     OwnPtr<Core::Stream::Socket> tcp_socket = TRY(Core::Stream::TCPSocket::connect(host, port)); | ||||
|     OwnPtr<Core::Socket> tcp_socket = TRY(Core::TCPSocket::connect(host, port)); | ||||
|     TRY(tcp_socket->set_blocking(false)); | ||||
|     auto tls_socket = make<TLSv12>(move(tcp_socket), move(options)); | ||||
|     tls_socket->set_sni(host); | ||||
|  | @ -94,7 +94,7 @@ ErrorOr<NonnullOwnPtr<TLSv12>> TLSv12::connect(DeprecatedString const& host, u16 | |||
|     return AK::Error::from_string_view(alert_name(static_cast<AlertDescription>(256 - result))); | ||||
| } | ||||
| 
 | ||||
| ErrorOr<NonnullOwnPtr<TLSv12>> TLSv12::connect(DeprecatedString const& host, Core::Stream::Socket& underlying_stream, Options options) | ||||
| ErrorOr<NonnullOwnPtr<TLSv12>> TLSv12::connect(DeprecatedString const& host, Core::Socket& underlying_stream, Options options) | ||||
| { | ||||
|     TRY(underlying_stream.set_blocking(false)); | ||||
|     auto tls_socket = make<TLSv12>(&underlying_stream, move(options)); | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ | |||
| #include <AK/IPv4Address.h> | ||||
| #include <AK/WeakPtr.h> | ||||
| #include <LibCore/Notifier.h> | ||||
| #include <LibCore/Socket.h> | ||||
| #include <LibCore/Stream.h> | ||||
| #include <LibCore/Timer.h> | ||||
| #include <LibCrypto/Authentication/HMAC.h> | ||||
|  | @ -344,15 +345,15 @@ struct Context { | |||
|     OwnPtr<Crypto::Curves::EllipticCurve> server_key_exchange_curve; | ||||
| }; | ||||
| 
 | ||||
| class TLSv12 final : public Core::Stream::Socket { | ||||
| class TLSv12 final : public Core::Socket { | ||||
| private: | ||||
|     Core::Stream::Socket& underlying_stream() | ||||
|     Core::Socket& underlying_stream() | ||||
|     { | ||||
|         return *m_stream.visit([&](auto& stream) -> Core::Stream::Socket* { return stream; }); | ||||
|         return *m_stream.visit([&](auto& stream) -> Core::Socket* { return stream; }); | ||||
|     } | ||||
|     Core::Stream::Socket const& underlying_stream() const | ||||
|     Core::Socket const& underlying_stream() const | ||||
|     { | ||||
|         return *m_stream.visit([&](auto& stream) -> Core::Stream::Socket const* { return stream; }); | ||||
|         return *m_stream.visit([&](auto& stream) -> Core::Socket const* { return stream; }); | ||||
|     } | ||||
| 
 | ||||
| public: | ||||
|  | @ -384,9 +385,9 @@ public: | |||
|     virtual void set_notifications_enabled(bool enabled) override { underlying_stream().set_notifications_enabled(enabled); } | ||||
| 
 | ||||
|     static ErrorOr<NonnullOwnPtr<TLSv12>> connect(DeprecatedString const& host, u16 port, Options = {}); | ||||
|     static ErrorOr<NonnullOwnPtr<TLSv12>> connect(DeprecatedString const& host, Core::Stream::Socket& underlying_stream, Options = {}); | ||||
|     static ErrorOr<NonnullOwnPtr<TLSv12>> connect(DeprecatedString const& host, Core::Socket& underlying_stream, Options = {}); | ||||
| 
 | ||||
|     using StreamVariantType = Variant<OwnPtr<Core::Stream::Socket>, Core::Stream::Socket*>; | ||||
|     using StreamVariantType = Variant<OwnPtr<Core::Socket>, Core::Socket*>; | ||||
|     explicit TLSv12(StreamVariantType, Options); | ||||
| 
 | ||||
|     bool is_established() const { return m_context.connection_status == ConnectionStatus::Established; } | ||||
|  |  | |||
|  | @ -170,7 +170,7 @@ static JsonValue make_success_response(JsonValue value) | |||
|     return result; | ||||
| } | ||||
| 
 | ||||
| Client::Client(NonnullOwnPtr<Core::Stream::BufferedTCPSocket> socket, Core::Object* parent) | ||||
| Client::Client(NonnullOwnPtr<Core::BufferedTCPSocket> socket, Core::Object* parent) | ||||
|     : Core::Object(parent) | ||||
|     , m_socket(move(socket)) | ||||
| { | ||||
|  |  | |||
|  | @ -13,6 +13,7 @@ | |||
| #include <AK/NonnullOwnPtrVector.h> | ||||
| #include <AK/Variant.h> | ||||
| #include <LibCore/Object.h> | ||||
| #include <LibCore/Socket.h> | ||||
| #include <LibCore/Stream.h> | ||||
| #include <LibHTTP/Forward.h> | ||||
| #include <LibHTTP/HttpRequest.h> | ||||
|  | @ -103,7 +104,7 @@ public: | |||
|     virtual Response print_page(Parameters parameters, JsonValue payload) = 0; | ||||
| 
 | ||||
| protected: | ||||
|     Client(NonnullOwnPtr<Core::Stream::BufferedTCPSocket>, Core::Object* parent); | ||||
|     Client(NonnullOwnPtr<Core::BufferedTCPSocket>, Core::Object* parent); | ||||
| 
 | ||||
| private: | ||||
|     using WrappedError = Variant<AK::Error, WebDriver::Error>; | ||||
|  | @ -116,7 +117,7 @@ private: | |||
|     ErrorOr<void, WrappedError> send_error_response(Error const& error); | ||||
|     void log_response(unsigned code); | ||||
| 
 | ||||
|     NonnullOwnPtr<Core::Stream::BufferedTCPSocket> m_socket; | ||||
|     NonnullOwnPtr<Core::BufferedTCPSocket> m_socket; | ||||
|     Optional<HTTP::HttpRequest> m_request; | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ | |||
|  */ | ||||
| 
 | ||||
| #include <LibCore/EventLoop.h> | ||||
| #include <LibCore/Socket.h> | ||||
| #include <LibWebSocket/Impl/WebSocketImplSerenity.h> | ||||
| 
 | ||||
| namespace WebSocket { | ||||
|  | @ -40,18 +41,18 @@ void WebSocketImplSerenity::connect(ConnectionInfo const& connection_info) | |||
|     VERIFY(on_connected); | ||||
|     VERIFY(on_connection_error); | ||||
|     VERIFY(on_ready_to_read); | ||||
|     auto socket_result = [&]() -> ErrorOr<NonnullOwnPtr<Core::Stream::BufferedSocketBase>> { | ||||
|     auto socket_result = [&]() -> ErrorOr<NonnullOwnPtr<Core::BufferedSocketBase>> { | ||||
|         if (connection_info.is_secure()) { | ||||
|             TLS::Options options; | ||||
|             options.set_alert_handler([this](auto) { | ||||
|                 on_connection_error(); | ||||
|             }); | ||||
|             return TRY(Core::Stream::BufferedSocket<TLS::TLSv12>::create( | ||||
|             return TRY(Core::BufferedSocket<TLS::TLSv12>::create( | ||||
|                 TRY(TLS::TLSv12::connect(connection_info.url().host(), connection_info.url().port_or_default(), move(options))))); | ||||
|         } | ||||
| 
 | ||||
|         return TRY(Core::Stream::BufferedTCPSocket::create( | ||||
|             TRY(Core::Stream::TCPSocket::connect(connection_info.url().host(), connection_info.url().port_or_default())))); | ||||
|         return TRY(Core::BufferedTCPSocket::create( | ||||
|             TRY(Core::TCPSocket::connect(connection_info.url().host(), connection_info.url().port_or_default())))); | ||||
|     }(); | ||||
| 
 | ||||
|     if (socket_result.is_error()) { | ||||
|  |  | |||
|  | @ -26,7 +26,7 @@ public: | |||
|     virtual void discard_connection() override; | ||||
| 
 | ||||
| private: | ||||
|     OwnPtr<Core::Stream::BufferedSocketBase> m_socket; | ||||
|     OwnPtr<Core::BufferedSocketBase> m_socket; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -11,7 +11,7 @@ | |||
| 
 | ||||
| namespace WebView { | ||||
| 
 | ||||
| WebContentClient::WebContentClient(NonnullOwnPtr<Core::Stream::LocalSocket> socket, ViewImplementation& view) | ||||
| WebContentClient::WebContentClient(NonnullOwnPtr<Core::LocalSocket> socket, ViewImplementation& view) | ||||
|     : IPC::ConnectionToServer<WebContentClientEndpoint, WebContentServerEndpoint>(*this, move(socket)) | ||||
|     , m_view(view) | ||||
| { | ||||
|  |  | |||
|  | @ -21,7 +21,7 @@ class WebContentClient final | |||
|     IPC_CLIENT_CONNECTION(WebContentClient, "/tmp/session/%sid/portal/webcontent"sv); | ||||
| 
 | ||||
| public: | ||||
|     WebContentClient(NonnullOwnPtr<Core::Stream::LocalSocket>, ViewImplementation&); | ||||
|     WebContentClient(NonnullOwnPtr<Core::LocalSocket>, ViewImplementation&); | ||||
| 
 | ||||
|     Function<void()> on_web_content_process_crash; | ||||
| 
 | ||||
|  |  | |||
|  | @ -22,7 +22,7 @@ void ConnectionFromClient::for_each(Function<void(ConnectionFromClient&)> callba | |||
|         callback(connection); | ||||
| } | ||||
| 
 | ||||
| ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket> client_socket, int client_id, Mixer& mixer) | ||||
| ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket> client_socket, int client_id, Mixer& mixer) | ||||
|     : IPC::ConnectionFromClient<AudioClientEndpoint, AudioServerEndpoint>(*this, move(client_socket), client_id) | ||||
|     , m_mixer(mixer) | ||||
| { | ||||
|  |  | |||
|  | @ -32,7 +32,7 @@ public: | |||
|     static void for_each(Function<void(ConnectionFromClient&)>); | ||||
| 
 | ||||
| private: | ||||
|     explicit ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket>, int client_id, Mixer& mixer); | ||||
|     explicit ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket>, int client_id, Mixer& mixer); | ||||
| 
 | ||||
|     virtual Messages::AudioServer::GetMainMixVolumeResponse get_main_mix_volume() override; | ||||
|     virtual void set_main_mix_volume(double) override; | ||||
|  |  | |||
|  | @ -25,7 +25,7 @@ ErrorOr<int> serenity_main(Main::Arguments) | |||
|     auto server = TRY(Core::LocalServer::try_create()); | ||||
|     TRY(server->take_over_from_system_server()); | ||||
| 
 | ||||
|     server->on_accept = [&](NonnullOwnPtr<Core::Stream::LocalSocket> client_socket) { | ||||
|     server->on_accept = [&](NonnullOwnPtr<Core::LocalSocket> client_socket) { | ||||
|         static int s_next_client_id = 0; | ||||
|         int client_id = ++s_next_client_id; | ||||
|         (void)IPC::new_client_connection<AudioServer::ConnectionFromClient>(move(client_socket), client_id, *mixer); | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ void ConnectionFromClient::for_each_client(Function<void(ConnectionFromClient&)> | |||
|     } | ||||
| } | ||||
| 
 | ||||
| ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket> socket, int client_id) | ||||
| ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket> socket, int client_id) | ||||
|     : IPC::ConnectionFromClient<ClipboardClientEndpoint, ClipboardServerEndpoint>(*this, move(socket), client_id) | ||||
| { | ||||
|     s_connections.set(client_id, *this); | ||||
|  |  | |||
|  | @ -27,7 +27,7 @@ public: | |||
|     void notify_about_clipboard_change(); | ||||
| 
 | ||||
| private: | ||||
|     explicit ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket>, int client_id); | ||||
|     explicit ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket>, int client_id); | ||||
| 
 | ||||
|     virtual Messages::ClipboardServer::GetClipboardDataResponse get_clipboard_data() override; | ||||
|     virtual void set_clipboard_data(Core::AnonymousBuffer const&, DeprecatedString const&, IPC::Dictionary const&) override; | ||||
|  |  | |||
|  | @ -74,7 +74,7 @@ static Core::ConfigFile& ensure_domain_config(DeprecatedString const& domain) | |||
|     return *config; | ||||
| } | ||||
| 
 | ||||
| ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket> client_socket, int client_id) | ||||
| ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket> client_socket, int client_id) | ||||
|     : IPC::ConnectionFromClient<ConfigClientEndpoint, ConfigServerEndpoint>(*this, move(client_socket), client_id) | ||||
|     , m_sync_timer(Core::Timer::create_single_shot(s_disk_sync_delay_ms, [this]() { sync_dirty_domains_to_disk(); }).release_value_but_fixme_should_propagate_errors()) | ||||
| { | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ public: | |||
|     bool is_monitoring_domain(DeprecatedString const& domain) const { return m_monitored_domains.contains(domain); } | ||||
| 
 | ||||
| private: | ||||
|     explicit ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket>, int client_id); | ||||
|     explicit ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket>, int client_id); | ||||
| 
 | ||||
|     virtual void pledge_domains(Vector<DeprecatedString> const&) override; | ||||
|     virtual void monitor_domain(DeprecatedString const&) override; | ||||
|  |  | |||
|  | @ -6,8 +6,9 @@ | |||
| 
 | ||||
| #include "Client.h" | ||||
| #include <LibCore/EventLoop.h> | ||||
| #include <LibCore/Socket.h> | ||||
| 
 | ||||
| Client::Client(int id, NonnullOwnPtr<Core::Stream::TCPSocket> socket) | ||||
| Client::Client(int id, NonnullOwnPtr<Core::TCPSocket> socket) | ||||
|     : m_id(id) | ||||
|     , m_socket(move(socket)) | ||||
| { | ||||
|  |  | |||
|  | @ -6,11 +6,12 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <LibCore/Socket.h> | ||||
| #include <LibCore/Stream.h> | ||||
| 
 | ||||
| class Client : public RefCounted<Client> { | ||||
| public: | ||||
|     static NonnullRefPtr<Client> create(int id, NonnullOwnPtr<Core::Stream::TCPSocket> socket) | ||||
|     static NonnullRefPtr<Client> create(int id, NonnullOwnPtr<Core::TCPSocket> socket) | ||||
|     { | ||||
|         return adopt_ref(*new Client(id, move(socket))); | ||||
|     } | ||||
|  | @ -18,12 +19,12 @@ public: | |||
|     Function<void()> on_exit; | ||||
| 
 | ||||
| protected: | ||||
|     Client(int id, NonnullOwnPtr<Core::Stream::TCPSocket> socket); | ||||
|     Client(int id, NonnullOwnPtr<Core::TCPSocket> socket); | ||||
| 
 | ||||
|     ErrorOr<void> drain_socket(); | ||||
|     void quit(); | ||||
| 
 | ||||
| private: | ||||
|     int m_id { 0 }; | ||||
|     NonnullOwnPtr<Core::Stream::TCPSocket> m_socket; | ||||
|     NonnullOwnPtr<Core::TCPSocket> m_socket; | ||||
| }; | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ namespace FileSystemAccessServer { | |||
| 
 | ||||
| static HashMap<int, NonnullRefPtr<ConnectionFromClient>> s_connections; | ||||
| 
 | ||||
| ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket> socket) | ||||
| ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket> socket) | ||||
|     : IPC::ConnectionFromClient<FileSystemAccessClientEndpoint, FileSystemAccessServerEndpoint>(*this, move(socket), 1) | ||||
| { | ||||
|     s_connections.set(1, *this); | ||||
|  |  | |||
|  | @ -25,7 +25,7 @@ public: | |||
|     virtual void die() override; | ||||
| 
 | ||||
| private: | ||||
|     explicit ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket>); | ||||
|     explicit ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket>); | ||||
| 
 | ||||
|     virtual void request_file_read_only_approved(i32, i32, i32, DeprecatedString const&) override; | ||||
|     virtual void request_file(i32, i32, i32, DeprecatedString const&, Core::Stream::OpenMode) override; | ||||
|  |  | |||
|  | @ -12,7 +12,7 @@ | |||
| 
 | ||||
| namespace ImageDecoder { | ||||
| 
 | ||||
| ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket> socket) | ||||
| ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket> socket) | ||||
|     : IPC::ConnectionFromClient<ImageDecoderClientEndpoint, ImageDecoderServerEndpoint>(*this, move(socket), 1) | ||||
| { | ||||
| } | ||||
|  |  | |||
|  | @ -24,7 +24,7 @@ public: | |||
|     virtual void die() override; | ||||
| 
 | ||||
| private: | ||||
|     explicit ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket>); | ||||
|     explicit ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket>); | ||||
| 
 | ||||
|     virtual Messages::ImageDecoderServer::DecodeImageResponse decode_image(Core::AnonymousBuffer const&, Optional<DeprecatedString> const& mime_type) override; | ||||
| }; | ||||
|  |  | |||
|  | @ -12,7 +12,7 @@ namespace InspectorServer { | |||
| 
 | ||||
| static HashMap<int, RefPtr<ConnectionFromClient>> s_connections; | ||||
| 
 | ||||
| ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket> socket, int client_id) | ||||
| ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket> socket, int client_id) | ||||
|     : IPC::ConnectionFromClient<InspectorClientEndpoint, InspectorServerEndpoint>(*this, move(socket), client_id) | ||||
| { | ||||
|     s_connections.set(client_id, *this); | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ public: | |||
|     virtual void die() override; | ||||
| 
 | ||||
| private: | ||||
|     explicit ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket>, int client_id); | ||||
|     explicit ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket>, int client_id); | ||||
| 
 | ||||
|     virtual Messages::InspectorServer::GetAllObjectsResponse get_all_objects(pid_t) override; | ||||
|     virtual Messages::InspectorServer::SetInspectedObjectResponse set_inspected_object(pid_t, u64 object_id) override; | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ | |||
| #include "InspectableProcess.h" | ||||
| #include <AK/JsonObject.h> | ||||
| #include <LibCore/EventLoop.h> | ||||
| #include <LibCore/Socket.h> | ||||
| 
 | ||||
| namespace InspectorServer { | ||||
| 
 | ||||
|  | @ -17,7 +18,7 @@ InspectableProcess* InspectableProcess::from_pid(pid_t pid) | |||
|     return g_processes.get(pid).value_or(nullptr); | ||||
| } | ||||
| 
 | ||||
| InspectableProcess::InspectableProcess(pid_t pid, NonnullOwnPtr<Core::Stream::LocalSocket> socket) | ||||
| InspectableProcess::InspectableProcess(pid_t pid, NonnullOwnPtr<Core::LocalSocket> socket) | ||||
|     : m_pid(pid) | ||||
|     , m_socket(move(socket)) | ||||
| { | ||||
|  |  | |||
|  | @ -12,7 +12,7 @@ namespace InspectorServer { | |||
| 
 | ||||
| class InspectableProcess { | ||||
| public: | ||||
|     InspectableProcess(pid_t, NonnullOwnPtr<Core::Stream::LocalSocket>); | ||||
|     InspectableProcess(pid_t, NonnullOwnPtr<Core::LocalSocket>); | ||||
|     ~InspectableProcess() = default; | ||||
| 
 | ||||
|     void send_request(JsonObject const& request); | ||||
|  | @ -22,7 +22,7 @@ public: | |||
| 
 | ||||
| private: | ||||
|     pid_t m_pid { 0 }; | ||||
|     NonnullOwnPtr<Core::Stream::LocalSocket> m_socket; | ||||
|     NonnullOwnPtr<Core::LocalSocket> m_socket; | ||||
| }; | ||||
| 
 | ||||
| extern HashMap<pid_t, NonnullOwnPtr<InspectorServer::InspectableProcess>> g_processes; | ||||
|  |  | |||
|  | @ -13,7 +13,7 @@ | |||
| namespace LaunchServer { | ||||
| 
 | ||||
| static HashMap<int, RefPtr<ConnectionFromClient>> s_connections; | ||||
| ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket> client_socket, int client_id) | ||||
| ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket> client_socket, int client_id) | ||||
|     : IPC::ConnectionFromClient<LaunchClientEndpoint, LaunchServerEndpoint>(*this, move(client_socket), client_id) | ||||
| { | ||||
|     s_connections.set(client_id, *this); | ||||
|  |  | |||
|  | @ -20,7 +20,7 @@ public: | |||
|     virtual void die() override; | ||||
| 
 | ||||
| private: | ||||
|     explicit ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket>, int client_id); | ||||
|     explicit ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket>, int client_id); | ||||
| 
 | ||||
|     virtual Messages::LaunchServer::OpenUrlResponse open_url(URL const&, DeprecatedString const&) override; | ||||
|     virtual Messages::LaunchServer::GetHandlersForUrlResponse get_handlers_for_url(URL const&) override; | ||||
|  |  | |||
|  | @ -15,7 +15,7 @@ using namespace DNS; | |||
| 
 | ||||
| static HashMap<int, RefPtr<ConnectionFromClient>> s_connections; | ||||
| 
 | ||||
| ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket> socket, int client_id) | ||||
| ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket> socket, int client_id) | ||||
|     : IPC::ConnectionFromClient<LookupClientEndpoint, LookupServerEndpoint>(*this, move(socket), client_id) | ||||
| { | ||||
|     s_connections.set(client_id, *this); | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ public: | |||
|     virtual void die() override; | ||||
| 
 | ||||
| private: | ||||
|     explicit ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket>, int client_id); | ||||
|     explicit ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket>, int client_id); | ||||
| 
 | ||||
|     virtual Messages::LookupServer::LookupNameResponse lookup_name(DeprecatedString const&) override; | ||||
|     virtual Messages::LookupServer::LookupAddressResponse lookup_address(DeprecatedString const&) override; | ||||
|  |  | |||
|  | @ -237,7 +237,7 @@ ErrorOr<Vector<Answer>> LookupServer::lookup(Name const& name, DeprecatedString | |||
| 
 | ||||
|     auto buffer = TRY(request.to_byte_buffer()); | ||||
| 
 | ||||
|     auto udp_socket = TRY(Core::Stream::UDPSocket::connect(nameserver, 53, Time::from_seconds(1))); | ||||
|     auto udp_socket = TRY(Core::UDPSocket::connect(nameserver, 53, Time::from_seconds(1))); | ||||
|     TRY(udp_socket->set_blocking(true)); | ||||
| 
 | ||||
|     TRY(udp_socket->write(buffer)); | ||||
|  |  | |||
|  | @ -13,7 +13,7 @@ namespace NotificationServer { | |||
| 
 | ||||
| static HashMap<int, RefPtr<ConnectionFromClient>> s_connections; | ||||
| 
 | ||||
| ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket> client_socket, int client_id) | ||||
| ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket> client_socket, int client_id) | ||||
|     : IPC::ConnectionFromClient<NotificationClientEndpoint, NotificationServerEndpoint>(*this, move(client_socket), client_id) | ||||
| { | ||||
|     s_connections.set(client_id, *this); | ||||
|  |  | |||
|  | @ -21,7 +21,7 @@ public: | |||
|     virtual void die() override; | ||||
| 
 | ||||
| private: | ||||
|     explicit ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket>, int client_id); | ||||
|     explicit ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket>, int client_id); | ||||
| 
 | ||||
|     virtual void show_notification(DeprecatedString const&, DeprecatedString const&, Gfx::ShareableBitmap const&) override; | ||||
|     virtual void close_notification() override; | ||||
|  |  | |||
|  | @ -11,10 +11,10 @@ | |||
| 
 | ||||
| namespace RequestServer::ConnectionCache { | ||||
| 
 | ||||
| HashMap<ConnectionKey, NonnullOwnPtr<NonnullOwnPtrVector<Connection<Core::Stream::TCPSocket, Core::Stream::Socket>>>> g_tcp_connection_cache {}; | ||||
| HashMap<ConnectionKey, NonnullOwnPtr<NonnullOwnPtrVector<Connection<Core::TCPSocket, Core::Socket>>>> g_tcp_connection_cache {}; | ||||
| HashMap<ConnectionKey, NonnullOwnPtr<NonnullOwnPtrVector<Connection<TLS::TLSv12>>>> g_tls_connection_cache {}; | ||||
| 
 | ||||
| void request_did_finish(URL const& url, Core::Stream::Socket const* socket) | ||||
| void request_did_finish(URL const& url, Core::Socket const* socket) | ||||
| { | ||||
|     if (!socket) { | ||||
|         dbgln("Request with a null socket finished for URL {}", url); | ||||
|  | @ -71,9 +71,9 @@ void request_did_finish(URL const& url, Core::Stream::Socket const* socket) | |||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     if (is<Core::Stream::BufferedSocket<TLS::TLSv12>>(socket)) | ||||
|     if (is<Core::BufferedSocket<TLS::TLSv12>>(socket)) | ||||
|         fire_off_next_job(g_tls_connection_cache); | ||||
|     else if (is<Core::Stream::BufferedSocket<Core::Stream::Socket>>(socket)) | ||||
|     else if (is<Core::BufferedSocket<Core::Socket>>(socket)) | ||||
|         fire_off_next_job(g_tcp_connection_cache); | ||||
|     else | ||||
|         dbgln("Unknown socket {} finished for URL {}", socket, url); | ||||
|  |  | |||
|  | @ -44,7 +44,7 @@ struct Proxy { | |||
|             if constexpr (requires { SocketType::connect(declval<DeprecatedString>(), *proxy_client_storage, forward<Args>(args)...); }) { | ||||
|                 proxy_client_storage = TRY(Core::SOCKSProxyClient::connect(data.host_ipv4, data.port, Core::SOCKSProxyClient::Version::V5, url.host(), url.port_or_default())); | ||||
|                 return TRY(SocketType::connect(url.host(), *proxy_client_storage, forward<Args>(args)...)); | ||||
|             } else if constexpr (IsSame<SocketType, Core::Stream::TCPSocket>) { | ||||
|             } else if constexpr (IsSame<SocketType, Core::TCPSocket>) { | ||||
|                 return TRY(Core::SOCKSProxyClient::connect(data.host_ipv4, data.port, Core::SOCKSProxyClient::Version::V5, url.host(), url.port_or_default())); | ||||
|             } else { | ||||
|                 return Error::from_string_literal("SOCKS5 not supported for this socket type"); | ||||
|  | @ -57,7 +57,7 @@ struct Proxy { | |||
| template<typename Socket, typename SocketStorageType = Socket> | ||||
| struct Connection { | ||||
|     struct JobData { | ||||
|         Function<void(Core::Stream::Socket&)> start {}; | ||||
|         Function<void(Core::Socket&)> start {}; | ||||
|         Function<void(Core::NetworkJob::Error)> fail {}; | ||||
|         Function<Vector<TLS::Certificate>()> provide_client_certificates {}; | ||||
| 
 | ||||
|  | @ -91,7 +91,7 @@ struct Connection { | |||
|     using SocketType = Socket; | ||||
|     using StorageType = SocketStorageType; | ||||
| 
 | ||||
|     NonnullOwnPtr<Core::Stream::BufferedSocket<SocketStorageType>> socket; | ||||
|     NonnullOwnPtr<Core::BufferedSocket<SocketStorageType>> socket; | ||||
|     QueueType request_queue; | ||||
|     NonnullRefPtr<Core::Timer> removal_timer; | ||||
|     bool has_started { false }; | ||||
|  | @ -121,10 +121,10 @@ struct AK::Traits<RequestServer::ConnectionCache::ConnectionKey> : public AK::Ge | |||
| 
 | ||||
| namespace RequestServer::ConnectionCache { | ||||
| 
 | ||||
| extern HashMap<ConnectionKey, NonnullOwnPtr<NonnullOwnPtrVector<Connection<Core::Stream::TCPSocket, Core::Stream::Socket>>>> g_tcp_connection_cache; | ||||
| extern HashMap<ConnectionKey, NonnullOwnPtr<NonnullOwnPtrVector<Connection<Core::TCPSocket, Core::Socket>>>> g_tcp_connection_cache; | ||||
| extern HashMap<ConnectionKey, NonnullOwnPtr<NonnullOwnPtrVector<Connection<TLS::TLSv12>>>> g_tls_connection_cache; | ||||
| 
 | ||||
| void request_did_finish(URL const&, Core::Stream::Socket const*); | ||||
| void request_did_finish(URL const&, Core::Socket const*); | ||||
| void dump_jobs(); | ||||
| 
 | ||||
| constexpr static size_t MaxConcurrentConnectionsPerURL = 4; | ||||
|  | @ -139,7 +139,7 @@ ErrorOr<void> recreate_socket_if_needed(T& connection, URL const& url) | |||
|     if (!connection.socket->is_open() || connection.socket->is_eof()) { | ||||
|         // Create another socket for the connection.
 | ||||
|         auto set_socket = [&](auto socket) -> ErrorOr<void> { | ||||
|             connection.socket = TRY(Core::Stream::BufferedSocket<SocketStorageType>::create(move(socket))); | ||||
|             connection.socket = TRY(Core::BufferedSocket<SocketStorageType>::create(move(socket))); | ||||
|             return {}; | ||||
|         }; | ||||
| 
 | ||||
|  | @ -192,7 +192,7 @@ decltype(auto) get_or_create_connection(auto& cache, URL const& url, auto& job, | |||
|             }); | ||||
|             return ReturnType { nullptr }; | ||||
|         } | ||||
|         auto socket_result = Core::Stream::BufferedSocket<typename ConnectionType::StorageType>::create(connection_result.release_value()); | ||||
|         auto socket_result = Core::BufferedSocket<typename ConnectionType::StorageType>::create(connection_result.release_value()); | ||||
|         if (socket_result.is_error()) { | ||||
|             dbgln("ConnectionCache: Failed to make a buffered socket for {}: {}", url, socket_result.error()); | ||||
|             Core::deferred_invoke([&job] { | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ namespace RequestServer { | |||
| 
 | ||||
| static HashMap<int, RefPtr<ConnectionFromClient>> s_connections; | ||||
| 
 | ||||
| ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket> socket) | ||||
| ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket> socket) | ||||
|     : IPC::ConnectionFromClient<RequestClientEndpoint, RequestServerEndpoint>(*this, move(socket), 1) | ||||
| { | ||||
|     s_connections.set(1, *this); | ||||
|  | @ -123,7 +123,7 @@ struct Job { | |||
|         return *s_jobs.find(url)->value; | ||||
|     } | ||||
| 
 | ||||
|     void start(Core::Stream::Socket& socket) | ||||
|     void start(Core::Socket& socket) | ||||
|     { | ||||
|         auto is_connected = socket.is_open(); | ||||
|         VERIFY(is_connected); | ||||
|  |  | |||
|  | @ -29,7 +29,7 @@ public: | |||
|     void did_request_certificates(Badge<Request>, Request&); | ||||
| 
 | ||||
| private: | ||||
|     explicit ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket>); | ||||
|     explicit ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket>); | ||||
| 
 | ||||
|     virtual Messages::RequestServer::IsSupportedProtocolResponse is_supported_protocol(DeprecatedString const&) override; | ||||
|     virtual Messages::RequestServer::StartRequestResponse start_request(DeprecatedString const&, URL const&, IPC::Dictionary const&, ByteBuffer const&, Core::ProxyData const&) override; | ||||
|  |  | |||
|  | @ -28,7 +28,7 @@ void ConnectionFromClient::set_database_path(DeprecatedString database_path) | |||
|     m_database_path = move(database_path); | ||||
| } | ||||
| 
 | ||||
| ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket> socket, int client_id) | ||||
| ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket> socket, int client_id) | ||||
|     : IPC::ConnectionFromClient<SQLClientEndpoint, SQLServerEndpoint>(*this, move(socket), client_id) | ||||
|     , m_database_path(DeprecatedString::formatted("{}/sql", Core::StandardPaths::data_directory())) | ||||
| { | ||||
|  |  | |||
|  | @ -32,7 +32,7 @@ public: | |||
|     Function<void()> on_disconnect; | ||||
| 
 | ||||
| private: | ||||
|     explicit ConnectionFromClient(NonnullOwnPtr<Core::Stream::LocalSocket>, int client_id); | ||||
|     explicit ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket>, int client_id); | ||||
| 
 | ||||
|     virtual Messages::SQLServer::ConnectResponse connect(DeprecatedString const&) override; | ||||
|     virtual Messages::SQLServer::PrepareStatementResponse prepare_statement(SQL::ConnectionID, DeprecatedString const&) override; | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ public: | |||
|     void set_bitmap(Gfx::Bitmap const& bitmap); | ||||
| 
 | ||||
| private: | ||||
|     ConnectionToClipboardServer(NonnullOwnPtr<Core::Stream::LocalSocket> socket) | ||||
|     ConnectionToClipboardServer(NonnullOwnPtr<Core::LocalSocket> socket) | ||||
|         : IPC::ConnectionToServer<ClipboardClientEndpoint, ClipboardServerEndpoint>(*this, move(socket)) | ||||
|     { | ||||
|     } | ||||
|  |  | |||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Tim Schumacher
						Tim Schumacher