// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include #include #include #include "common/common_types.h" #include "common/expected.h" #include "common/socket_types.h" #include "core/hle/service/service.h" #include "core/hle/service/sockets/sockets.h" #include "network/network.h" namespace Core { class System; } namespace Network { class SocketBase; class Socket; } // namespace Network namespace Service::Sockets { class BSD final : public ServiceFramework { public: explicit BSD(Core::System& system_, const char* name); ~BSD() override; // These methods are called from SSL; the first two are also called from // this class for the corresponding IPC methods. // On the real device, the SSL service makes IPC calls to this service. Common::Expected DuplicateSocketImpl(s32 fd); Errno CloseImpl(s32 fd); std::optional> GetSocket(s32 fd); private: /// Maximum number of file descriptors static constexpr size_t MAX_FD = 128; struct FileDescriptor { std::shared_ptr socket; s32 flags = 0; bool is_connection_based = false; }; struct PollWork { void Execute(BSD* bsd); void Response(HLERequestContext& ctx); s32 nfds; s32 timeout; std::span read_buffer; std::vector write_buffer; s32 ret{}; Errno bsd_errno{}; }; struct AcceptWork { void Execute(BSD* bsd); void Response(HLERequestContext& ctx); s32 fd; std::vector write_buffer; s32 ret{}; Errno bsd_errno{}; }; struct ConnectWork { void Execute(BSD* bsd); void Response(HLERequestContext& ctx); s32 fd; std::span addr; Errno bsd_errno{}; }; struct RecvWork { void Execute(BSD* bsd); void Response(HLERequestContext& ctx); s32 fd; u32 flags; std::vector message; s32 ret{}; Errno bsd_errno{}; }; struct RecvFromWork { void Execute(BSD* bsd); void Response(HLERequestContext& ctx); s32 fd; u32 flags; std::vector message; std::vector addr; s32 ret{}; Errno bsd_errno{}; }; struct SendWork { void Execute(BSD* bsd); void Response(HLERequestContext& ctx); s32 fd; u32 flags; std::span message; s32 ret{}; Errno bsd_errno{}; }; struct SendToWork { void Execute(BSD* bsd); void Response(HLERequestContext& ctx); s32 fd; u32 flags; std::span message; std::span addr; s32 ret{}; Errno bsd_errno{}; }; void RegisterClient(HLERequestContext& ctx); void StartMonitoring(HLERequestContext& ctx); void Socket(HLERequestContext& ctx); void Select(HLERequestContext& ctx); void Poll(HLERequestContext& ctx); void Accept(HLERequestContext& ctx); void Bind(HLERequestContext& ctx); void Connect(HLERequestContext& ctx); void GetPeerName(HLERequestContext& ctx); void GetSockName(HLERequestContext& ctx); void GetSockOpt(HLERequestContext& ctx); void Listen(HLERequestContext& ctx); void Fcntl(HLERequestContext& ctx); void SetSockOpt(HLERequestContext& ctx); void Shutdown(HLERequestContext& ctx); void Recv(HLERequestContext& ctx); void RecvFrom(HLERequestContext& ctx); void Send(HLERequestContext& ctx); void SendTo(HLERequestContext& ctx); void Write(HLERequestContext& ctx); void Read(HLERequestContext& ctx); void Close(HLERequestContext& ctx); void DuplicateSocket(HLERequestContext& ctx); void EventFd(HLERequestContext& ctx); template void ExecuteWork(HLERequestContext& ctx, Work work); std::pair SocketImpl(Domain domain, Type type, Protocol protocol); std::pair PollImpl(std::vector& write_buffer, std::span read_buffer, s32 nfds, s32 timeout); std::pair AcceptImpl(s32 fd, std::vector& write_buffer); Errno BindImpl(s32 fd, std::span addr); Errno ConnectImpl(s32 fd, std::span addr); Errno GetPeerNameImpl(s32 fd, std::vector& write_buffer); Errno GetSockNameImpl(s32 fd, std::vector& write_buffer); Errno ListenImpl(s32 fd, s32 backlog); std::pair FcntlImpl(s32 fd, FcntlCmd cmd, s32 arg); Errno GetSockOptImpl(s32 fd, u32 level, OptName optname, std::vector& optval); Errno SetSockOptImpl(s32 fd, u32 level, OptName optname, std::span optval); Errno ShutdownImpl(s32 fd, s32 how); std::pair RecvImpl(s32 fd, u32 flags, std::vector& message); std::pair RecvFromImpl(s32 fd, u32 flags, std::vector& message, std::vector& addr); std::pair SendImpl(s32 fd, u32 flags, std::span message); std::pair SendToImpl(s32 fd, u32 flags, std::span message, std::span addr); s32 FindFreeFileDescriptorHandle() noexcept; bool IsFileDescriptorValid(s32 fd) const noexcept; void BuildErrnoResponse(HLERequestContext& ctx, Errno bsd_errno) const noexcept; std::array, MAX_FD> file_descriptors; Network::RoomNetwork& room_network; /// Callback to parse and handle a received wifi packet. void OnProxyPacketReceived(const Network::ProxyPacket& packet); // Callback identifier for the OnProxyPacketReceived event. Network::RoomMember::CallbackHandle proxy_packet_received; protected: virtual std::unique_lock LockService() override; }; class BSDCFG final : public ServiceFramework { public: explicit BSDCFG(Core::System& system_); ~BSDCFG() override; }; } // namespace Service::Sockets