From f7d59f3e0e63a33e758b92a857ca4add0a8ee524 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sat, 11 Jul 2020 22:37:47 -0300 Subject: services/bsd: Implement most of bsd:s This implements: Socket, Poll, Accept, Bind, Connect, GetPeerName, GetSockName, Listen, Fcntl, SetSockOpt, Shutdown, Recv, RecvFrom, Send, SendTo, Write, and Close The implementation was done referencing: SwIPC, switchbrew, testing with libnx and inspecting its code, general information about bsd sockets online, and analysing official software. Not everything from these service calls is implemented, but everything that is not implemented will be logged in some way. --- src/core/hle/service/sockets/bsd.h | 148 ++++++++++++++++++++++++++++++++++++- 1 file changed, 145 insertions(+), 3 deletions(-) (limited to 'src/core/hle/service/sockets/bsd.h') diff --git a/src/core/hle/service/sockets/bsd.h b/src/core/hle/service/sockets/bsd.h index 7e1a64015..357531951 100644 --- a/src/core/hle/service/sockets/bsd.h +++ b/src/core/hle/service/sockets/bsd.h @@ -4,32 +4,174 @@ #pragma once +#include +#include +#include + #include "common/common_types.h" #include "core/hle/kernel/hle_ipc.h" #include "core/hle/service/service.h" +#include "core/hle/service/sockets/blocking_worker.h" #include "core/hle/service/sockets/sockets.h" +namespace Core { +class System; +} + +namespace Network { +class Socket; +} + namespace Service::Sockets { class BSD final : public ServiceFramework { public: - explicit BSD(const char* name); + explicit BSD(Core::System& system, const char* name); ~BSD() override; private: + /// Maximum number of file descriptors + static constexpr size_t MAX_FD = 128; + + struct FileDescriptor { + std::unique_ptr socket; + s32 flags = 0; + bool is_connection_based = false; + }; + + struct PollWork { + void Execute(BSD* bsd); + void Response(Kernel::HLERequestContext& ctx); + + s32 nfds; + s32 timeout; + std::vector read_buffer; + std::vector write_buffer; + s32 ret{}; + Errno bsd_errno{}; + }; + + struct AcceptWork { + void Execute(BSD* bsd); + void Response(Kernel::HLERequestContext& ctx); + + s32 fd; + std::vector write_buffer; + s32 ret{}; + Errno bsd_errno{}; + }; + + struct ConnectWork { + void Execute(BSD* bsd); + void Response(Kernel::HLERequestContext& ctx); + + s32 fd; + std::vector addr; + Errno bsd_errno{}; + }; + + struct RecvWork { + void Execute(BSD* bsd); + void Response(Kernel::HLERequestContext& ctx); + + s32 fd; + u32 flags; + std::vector message; + s32 ret{}; + Errno bsd_errno{}; + }; + + struct RecvFromWork { + void Execute(BSD* bsd); + void Response(Kernel::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(Kernel::HLERequestContext& ctx); + + s32 fd; + u32 flags; + std::vector message; + s32 ret{}; + Errno bsd_errno{}; + }; + + struct SendToWork { + void Execute(BSD* bsd); + void Response(Kernel::HLERequestContext& ctx); + + s32 fd; + u32 flags; + std::vector message; + std::vector addr; + s32 ret{}; + Errno bsd_errno{}; + }; + void RegisterClient(Kernel::HLERequestContext& ctx); void StartMonitoring(Kernel::HLERequestContext& ctx); void Socket(Kernel::HLERequestContext& ctx); void Select(Kernel::HLERequestContext& ctx); + void Poll(Kernel::HLERequestContext& ctx); + void Accept(Kernel::HLERequestContext& ctx); void Bind(Kernel::HLERequestContext& ctx); void Connect(Kernel::HLERequestContext& ctx); + void GetPeerName(Kernel::HLERequestContext& ctx); + void GetSockName(Kernel::HLERequestContext& ctx); void Listen(Kernel::HLERequestContext& ctx); + void Fcntl(Kernel::HLERequestContext& ctx); void SetSockOpt(Kernel::HLERequestContext& ctx); + void Shutdown(Kernel::HLERequestContext& ctx); + void Recv(Kernel::HLERequestContext& ctx); + void RecvFrom(Kernel::HLERequestContext& ctx); + void Send(Kernel::HLERequestContext& ctx); void SendTo(Kernel::HLERequestContext& ctx); + void Write(Kernel::HLERequestContext& ctx); void Close(Kernel::HLERequestContext& ctx); - /// Id to use for the next open file descriptor. - u32 next_fd = 1; + template + void ExecuteWork(Kernel::HLERequestContext& ctx, std::string_view sleep_reason, + bool is_blocking, Work work); + + std::pair SocketImpl(Domain domain, Type type, Protocol protocol); + std::pair PollImpl(std::vector& write_buffer, std::vector read_buffer, + s32 nfds, s32 timeout); + std::pair AcceptImpl(s32 fd, std::vector& write_buffer); + Errno BindImpl(s32 fd, const std::vector& addr); + Errno ConnectImpl(s32 fd, const std::vector& 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 SetSockOptImpl(s32 fd, u32 level, OptName optname, size_t optlen, const void* 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, const std::vector& message); + std::pair SendToImpl(s32 fd, u32 flags, const std::vector& message, + const std::vector& addr); + Errno CloseImpl(s32 fd); + + s32 FindFreeFileDescriptorHandle() noexcept; + bool IsFileDescriptorValid(s32 fd) const noexcept; + bool IsBlockingSocket(s32 fd) const noexcept; + + void BuildErrnoResponse(Kernel::HLERequestContext& ctx, Errno bsd_errno) const noexcept; + + std::array, MAX_FD> file_descriptors; + + BlockingWorkerPool + worker_pool; }; class BSDCFG final : public ServiceFramework { -- cgit v1.2.3