[Net] Convert sockets to asio

Makes the socket layer cross-platform while retaining mostly BSD socket
style API.
This commit is contained in:
Herman S.
2026-01-31 00:46:51 +09:00
parent 2bbd9c4687
commit 31c3dfd2fa
7 changed files with 483 additions and 192 deletions
+5 -1
View File
@@ -81,9 +81,13 @@
#endif
#if XE_PLATFORM_WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX // Don't want windows.h including min/max macros.
#endif // XE_PLATFORM_WIN32
#endif
#endif // XE_PLATFORM_WIN32
#if XE_PLATFORM_WIN32
#include <intrin.h>
+2
View File
@@ -19,7 +19,9 @@
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <ObjBase.h>
#include <SDKDDKVer.h>
#include <bcrypt.h>
+13
View File
@@ -6,6 +6,19 @@ project("xenia-kernel")
uuid("ae185c4a-1c4f-4503-9892-328e549e871a")
kind("StaticLib")
language("C++")
includedirs({
project_root.."/third_party/asio/include",
})
defines({
"ASIO_STANDALONE",
"ASIO_NO_DEPRECATED",
})
filter("platforms:Windows")
defines({
"_WIN32_WINNT=0x0A00", -- Windows 10+ for Asio
"_WINSOCK_DEPRECATED_NO_WARNINGS", -- Suppress deprecated Winsock API warnings
})
filter({})
links({
"aes_128",
"fmt",
+1 -7
View File
@@ -11,13 +11,7 @@
#include "xenia/base/logging.h"
#ifdef XE_PLATFORM_WIN32
// NOTE: must be included last as it expects windows.h to already be included.
#define _WINSOCK_DEPRECATED_NO_WARNINGS // inet_addr
#include <winsock2.h> // NOLINT(build/include_order)
#elif XE_PLATFORM_LINUX
#include <netinet/in.h>
#endif
#include <asio.hpp>
struct XONLINE_SERVICE_INFO {
xe::be<uint32_t> id;
+4 -4
View File
@@ -21,8 +21,10 @@
#ifdef XE_PLATFORM_WIN32
// NOTE: must be included last as it expects windows.h to already be included.
#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS // inet_addr
#include <winsock2.h> // NOLINT(build/include_order)
#endif
#include <winsock2.h> // NOLINT(build/include_order)
#elif XE_PLATFORM_LINUX
#include <arpa/inet.h>
#include <netinet/in.h>
@@ -323,9 +325,7 @@ DECLARE_XAM_EXPORT1(NetDll_WSACleanup, kNetworking, kImplemented);
// Xbox shares space between normal error codes and WSA errors.
// This under the hood returns directly value received from RtlGetLastError.
dword_result_t NetDll_WSAGetLastError_entry() {
uint32_t last_error = XThread::GetLastError();
XELOGD("NetDll_WSAGetLastError: {}", last_error);
return last_error;
return XThread::GetLastError();
}
DECLARE_XAM_EXPORT1(NetDll_WSAGetLastError, kNetworking, kImplemented);
File diff suppressed because it is too large Load Diff
+28 -9
View File
@@ -10,7 +10,11 @@
#ifndef XENIA_KERNEL_XSOCKET_H_
#define XENIA_KERNEL_XSOCKET_H_
// Asio must be included before Windows headers to avoid macro conflicts
#include <asio.hpp>
#include <cstring>
#include <optional>
#include <queue>
#include "xenia/base/byte_order.h"
@@ -80,29 +84,33 @@ class XSocket : public XObject {
public:
static const XObject::Type kObjectType = XObject::Type::Socket;
// Note: These enum values use X_ prefix to avoid conflicts with Windows
// macros
enum AddressFamily {
AF_INET = 2,
X_AF_INET = 2,
};
enum Type {
SOCK_STREAM = 1,
SOCK_DGRAM = 2,
X_SOCK_STREAM = 1,
X_SOCK_DGRAM = 2,
};
enum Protocol {
IPPROTO_TCP = 6,
IPPROTO_UDP = 17,
X_IPPROTO_TCP = 6,
X_IPPROTO_UDP = 17,
// LIVE Voice and Data Protocol
// https://blog.csdn.net/baozi3026/article/details/4277227
// Format: [cbGameData][GameData(encrypted)][VoiceData(unencrypted)]
IPPROTO_VDP = 254,
X_IPPROTO_VDP = 254,
};
XSocket(KernelState* kernel_state);
~XSocket();
uint64_t native_handle() const { return native_handle_; }
// Returns the native socket handle for use with select() etc.
// Returns -1 if socket is not initialized.
uint64_t native_handle();
uint16_t bound_port() const { return bound_port_; }
X_STATUS Initialize(AddressFamily af, Type type, Protocol proto);
@@ -118,6 +126,7 @@ class XSocket : public XObject {
X_STATUS Bind(N_XSOCKADDR_IN* name, int name_len);
X_STATUS Listen(int backlog);
X_STATUS GetSockName(uint8_t* buf, int* buf_len);
X_STATUS GetPeerName(uint8_t* buf, int* buf_len);
object_ref<XSocket> Accept(N_XSOCKADDR* name, int* name_len);
int Shutdown(int how);
@@ -145,8 +154,15 @@ class XSocket : public XObject {
size_t len);
private:
XSocket(KernelState* kernel_state, uint64_t native_handle);
uint64_t native_handle_ = -1;
// Private constructor for accepted sockets
XSocket(KernelState* kernel_state, asio::ip::tcp::socket socket);
// Socket storage - either TCP or UDP
std::optional<asio::ip::tcp::socket> tcp_socket_;
std::optional<asio::ip::udp::socket> udp_socket_;
// Acceptor for listening TCP sockets (created when Listen() is called)
std::optional<asio::ip::tcp::acceptor> acceptor_;
AddressFamily af_; // Address family
Type type_; // Type (DGRAM/Stream/etc)
@@ -158,6 +174,9 @@ class XSocket : public XObject {
bool broadcast_socket_ = false;
// Last error code for this socket
mutable uint32_t last_error_ = 0;
std::unique_ptr<xe::threading::Event> event_;
std::mutex incoming_packet_mutex_;
std::queue<uint8_t*> incoming_packets_;