Serenity Operating System
at master 198 lines 7.0 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#pragma once 8 9#include <AK/Error.h> 10#include <AK/Time.h> 11#include <Kernel/FileSystem/File.h> 12#include <Kernel/Library/LockRefPtr.h> 13#include <Kernel/Locking/Mutex.h> 14#include <Kernel/Net/NetworkAdapter.h> 15#include <Kernel/UnixTypes.h> 16 17namespace Kernel { 18 19class OpenFileDescription; 20 21class Socket : public File { 22public: 23 static ErrorOr<NonnullRefPtr<Socket>> create(int domain, int type, int protocol); 24 virtual ~Socket() override; 25 26 int domain() const { return m_domain; } 27 int type() const { return m_type; } 28 int protocol() const { return m_protocol; } 29 30 bool is_shut_down_for_writing() const { return m_shut_down_for_writing; } 31 bool is_shut_down_for_reading() const { return m_shut_down_for_reading; } 32 33 enum class SetupState { 34 Unstarted, // we haven't tried to set the socket up yet 35 InProgress, // we're in the process of setting things up - for TCP maybe we've sent a SYN packet 36 Completed, // the setup process is complete, but not necessarily successful 37 }; 38 39 enum class Role : u8 { 40 None, 41 Listener, 42 Accepted, 43 Connected, 44 Connecting 45 }; 46 47 static StringView to_string(SetupState setup_state) 48 { 49 switch (setup_state) { 50 case SetupState::Unstarted: 51 return "Unstarted"sv; 52 case SetupState::InProgress: 53 return "InProgress"sv; 54 case SetupState::Completed: 55 return "Completed"sv; 56 default: 57 return "None"sv; 58 } 59 } 60 61 SetupState setup_state() const { return m_setup_state; } 62 void set_setup_state(SetupState setup_state); 63 64 virtual Role role(OpenFileDescription const&) const { return m_role; } 65 66 bool is_connected() const { return m_connected; } 67 void set_connected(bool); 68 69 bool can_accept() const { return !m_pending.is_empty(); } 70 RefPtr<Socket> accept(); 71 72 ErrorOr<void> shutdown(int how); 73 74 virtual ErrorOr<void> bind(Credentials const&, Userspace<sockaddr const*>, socklen_t) = 0; 75 virtual ErrorOr<void> connect(Credentials const&, OpenFileDescription&, Userspace<sockaddr const*>, socklen_t) = 0; 76 virtual ErrorOr<void> listen(size_t) = 0; 77 virtual void get_local_address(sockaddr*, socklen_t*) = 0; 78 virtual void get_peer_address(sockaddr*, socklen_t*) = 0; 79 virtual bool is_local() const { return false; } 80 virtual bool is_ipv4() const { return false; } 81 virtual ErrorOr<size_t> sendto(OpenFileDescription&, UserOrKernelBuffer const&, size_t, int flags, Userspace<sockaddr const*>, socklen_t) = 0; 82 virtual ErrorOr<size_t> recvfrom(OpenFileDescription&, UserOrKernelBuffer&, size_t, int flags, Userspace<sockaddr*>, Userspace<socklen_t*>, Time&, bool blocking) = 0; 83 84 virtual ErrorOr<void> setsockopt(int level, int option, Userspace<void const*>, socklen_t); 85 virtual ErrorOr<void> getsockopt(OpenFileDescription&, int level, int option, Userspace<void*>, Userspace<socklen_t*>); 86 87 ProcessID origin_pid() const { return m_origin.pid; } 88 UserID origin_uid() const { return m_origin.uid; } 89 GroupID origin_gid() const { return m_origin.gid; } 90 ProcessID acceptor_pid() const { return m_acceptor.pid; } 91 UserID acceptor_uid() const { return m_acceptor.uid; } 92 GroupID acceptor_gid() const { return m_acceptor.gid; } 93 LockRefPtr<NetworkAdapter> const bound_interface() const { return m_bound_interface; } 94 95 Mutex& mutex() { return m_mutex; } 96 97 // ^File 98 virtual ErrorOr<size_t> read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t) override final; 99 virtual ErrorOr<size_t> write(OpenFileDescription&, u64, UserOrKernelBuffer const&, size_t) override final; 100 virtual ErrorOr<struct stat> stat() const override; 101 virtual ErrorOr<NonnullOwnPtr<KString>> pseudo_path(OpenFileDescription const&) const override = 0; 102 103 bool has_receive_timeout() const { return m_receive_timeout != Time::zero(); } 104 Time const& receive_timeout() const { return m_receive_timeout; } 105 106 bool has_send_timeout() const { return m_send_timeout != Time::zero(); } 107 Time const& send_timeout() const { return m_send_timeout; } 108 109 bool wants_timestamp() const { return m_timestamp; } 110 111protected: 112 Socket(int domain, int type, int protocol); 113 114 ErrorOr<void> queue_connection_from(NonnullRefPtr<Socket>); 115 116 size_t backlog() const { return m_backlog; } 117 void set_backlog(size_t backlog) { m_backlog = backlog; } 118 119 virtual StringView class_name() const override { return "Socket"sv; } 120 121 virtual void shut_down_for_reading() { } 122 virtual void shut_down_for_writing() { } 123 124 Role m_role { Role::None }; 125 126 Optional<ErrnoCode> const& so_error() const 127 { 128 VERIFY(m_mutex.is_exclusively_locked_by_current_thread()); 129 return m_so_error; 130 } 131 132 Error set_so_error(ErrnoCode error_code) 133 { 134 MutexLocker locker(mutex()); 135 m_so_error = error_code; 136 137 return Error::from_errno(error_code); 138 } 139 140 Error set_so_error(Error error) 141 { 142 MutexLocker locker(mutex()); 143 m_so_error = static_cast<ErrnoCode>(error.code()); 144 145 return error; 146 } 147 148 void clear_so_error() 149 { 150 m_so_error = {}; 151 } 152 153 void set_origin(Process const&); 154 void set_acceptor(Process const&); 155 156 void set_role(Role role) { m_role = role; } 157 158 ucred m_origin { 0, 0, 0 }; 159 ucred m_acceptor { 0, 0, 0 }; 160 bool m_routing_disabled { false }; 161 162private: 163 virtual bool is_socket() const final { return true; } 164 165 Mutex m_mutex { "Socket"sv }; 166 167 int m_domain { 0 }; 168 int m_type { 0 }; 169 int m_protocol { 0 }; 170 size_t m_backlog { 0 }; 171 SetupState m_setup_state { SetupState::Unstarted }; 172 bool m_connected { false }; 173 bool m_shut_down_for_reading { false }; 174 bool m_shut_down_for_writing { false }; 175 176 LockRefPtr<NetworkAdapter> m_bound_interface { nullptr }; 177 178 Time m_receive_timeout {}; 179 Time m_send_timeout {}; 180 int m_timestamp { 0 }; 181 182 Optional<ErrnoCode> m_so_error; 183 184 Vector<NonnullRefPtr<Socket>> m_pending; 185}; 186 187// This is a special variant of TRY() that also updates the socket's SO_ERROR field on error. 188#define SOCKET_TRY(expression) \ 189 ({ \ 190 auto&& result = (expression); \ 191 if (result.is_error()) \ 192 return set_so_error(result.release_error()); \ 193 static_assert(!::AK::Detail::IsLvalueReference<decltype(result.release_value())>, \ 194 "Do not return a reference from a fallible expression"); \ 195 result.release_value(); \ 196 }) 197 198}