mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-11-28 06:16:23 -05:00
183 lines
5.6 KiB
C++
183 lines
5.6 KiB
C++
// Copyright 2018 yuzu emulator team
|
|
// Licensed under GPLv2 or any later version
|
|
// Refer to the license.txt file included.
|
|
|
|
#pragma once
|
|
|
|
#include <memory>
|
|
#include <string_view>
|
|
#include <vector>
|
|
|
|
#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<BSD> {
|
|
public:
|
|
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<Network::Socket> 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<u8> read_buffer;
|
|
std::vector<u8> write_buffer;
|
|
s32 ret{};
|
|
Errno bsd_errno{};
|
|
};
|
|
|
|
struct AcceptWork {
|
|
void Execute(BSD* bsd);
|
|
void Response(Kernel::HLERequestContext& ctx);
|
|
|
|
s32 fd;
|
|
std::vector<u8> write_buffer;
|
|
s32 ret{};
|
|
Errno bsd_errno{};
|
|
};
|
|
|
|
struct ConnectWork {
|
|
void Execute(BSD* bsd);
|
|
void Response(Kernel::HLERequestContext& ctx);
|
|
|
|
s32 fd;
|
|
std::vector<u8> addr;
|
|
Errno bsd_errno{};
|
|
};
|
|
|
|
struct RecvWork {
|
|
void Execute(BSD* bsd);
|
|
void Response(Kernel::HLERequestContext& ctx);
|
|
|
|
s32 fd;
|
|
u32 flags;
|
|
std::vector<u8> message;
|
|
s32 ret{};
|
|
Errno bsd_errno{};
|
|
};
|
|
|
|
struct RecvFromWork {
|
|
void Execute(BSD* bsd);
|
|
void Response(Kernel::HLERequestContext& ctx);
|
|
|
|
s32 fd;
|
|
u32 flags;
|
|
std::vector<u8> message;
|
|
std::vector<u8> addr;
|
|
s32 ret{};
|
|
Errno bsd_errno{};
|
|
};
|
|
|
|
struct SendWork {
|
|
void Execute(BSD* bsd);
|
|
void Response(Kernel::HLERequestContext& ctx);
|
|
|
|
s32 fd;
|
|
u32 flags;
|
|
std::vector<u8> message;
|
|
s32 ret{};
|
|
Errno bsd_errno{};
|
|
};
|
|
|
|
struct SendToWork {
|
|
void Execute(BSD* bsd);
|
|
void Response(Kernel::HLERequestContext& ctx);
|
|
|
|
s32 fd;
|
|
u32 flags;
|
|
std::vector<u8> message;
|
|
std::vector<u8> 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);
|
|
|
|
template <typename Work>
|
|
void ExecuteWork(Kernel::HLERequestContext& ctx, std::string_view sleep_reason,
|
|
bool is_blocking, Work work);
|
|
|
|
std::pair<s32, Errno> SocketImpl(Domain domain, Type type, Protocol protocol);
|
|
std::pair<s32, Errno> PollImpl(std::vector<u8>& write_buffer, std::vector<u8> read_buffer,
|
|
s32 nfds, s32 timeout);
|
|
std::pair<s32, Errno> AcceptImpl(s32 fd, std::vector<u8>& write_buffer);
|
|
Errno BindImpl(s32 fd, const std::vector<u8>& addr);
|
|
Errno ConnectImpl(s32 fd, const std::vector<u8>& addr);
|
|
Errno GetPeerNameImpl(s32 fd, std::vector<u8>& write_buffer);
|
|
Errno GetSockNameImpl(s32 fd, std::vector<u8>& write_buffer);
|
|
Errno ListenImpl(s32 fd, s32 backlog);
|
|
std::pair<s32, Errno> 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<s32, Errno> RecvImpl(s32 fd, u32 flags, std::vector<u8>& message);
|
|
std::pair<s32, Errno> RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& message,
|
|
std::vector<u8>& addr);
|
|
std::pair<s32, Errno> SendImpl(s32 fd, u32 flags, const std::vector<u8>& message);
|
|
std::pair<s32, Errno> SendToImpl(s32 fd, u32 flags, const std::vector<u8>& message,
|
|
const std::vector<u8>& 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<std::optional<FileDescriptor>, MAX_FD> file_descriptors;
|
|
|
|
BlockingWorkerPool<BSD, PollWork, AcceptWork, ConnectWork, RecvWork, RecvFromWork, SendWork,
|
|
SendToWork>
|
|
worker_pool;
|
|
};
|
|
|
|
class BSDCFG final : public ServiceFramework<BSDCFG> {
|
|
public:
|
|
explicit BSDCFG();
|
|
~BSDCFG() override;
|
|
};
|
|
|
|
} // namespace Service::Sockets
|