mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 12:32:40 +02:00
Add multithreaded BSD/socket support; revise BSD service type handling so that bsd:u is the default (since it has 22 worker threads as opposed to bsd:s's 11)
This commit is contained in:
parent
bc13692938
commit
5340c7d7dc
@ -1,6 +1,13 @@
|
||||
#pragma once
|
||||
#include "../../types.h"
|
||||
|
||||
/// BSD service type used by the socket driver.
|
||||
typedef enum {
|
||||
BsdServiceType_User = BIT(0), ///< Uses bsd:u (default).
|
||||
BsdServiceType_System = BIT(1), ///< Uses bsd:s.
|
||||
BsdServiceType_Auto = BsdServiceType_User | BsdServiceType_System, ///< Tries to use bsd:s first, and if that fails uses bsd:u (official software behavior).
|
||||
} BsdServiceType;
|
||||
|
||||
/// Configuration structure for socketInitalize
|
||||
typedef struct {
|
||||
u32 bsdsockets_version; ///< Observed 1 on 2.0 LibAppletWeb, 2 on 3.0.
|
||||
@ -15,6 +22,9 @@ typedef struct {
|
||||
|
||||
u32 sb_efficiency; ///< Number of buffers for each socket (standard values range from 1 to 8).
|
||||
|
||||
u32 num_bsd_sessions; ///< Number of BSD service sessions (typically 3).
|
||||
BsdServiceType bsd_service_type; ///< BSD service type (typically \ref BsdServiceType_User).
|
||||
|
||||
size_t serialized_out_addrinfos_max_size; ///< For getaddrinfo.
|
||||
size_t serialized_out_hostent_max_size; ///< For gethostbyname/gethostbyaddr.
|
||||
bool bypass_nsd; ///< For name gethostbyname/getaddrinfo: bypass the Name Server Daemon.
|
||||
@ -33,7 +43,6 @@ Result socketGetLastSfdnsresResult(void);
|
||||
void socketExit(void);
|
||||
|
||||
/// Initalize the socket driver using the default configuration.
|
||||
static inline Result socketInitializeDefault(void) {
|
||||
return socketInitialize(socketGetDefaultInitConfig());
|
||||
NX_INLINE Result socketInitializeDefault(void) {
|
||||
return socketInitialize(NULL);
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ extern __thread int g_bsdErrno; ///< Last errno, per-thread
|
||||
/// Fetch the default configuration for bsdInitialize.
|
||||
const BsdInitConfig *bsdGetDefaultInitConfig(void);
|
||||
/// Initialize the BSD service.
|
||||
Result bsdInitialize(const BsdInitConfig *config);
|
||||
Result bsdInitialize(const BsdInitConfig *config, u32 num_sessions, u32 service_type);
|
||||
/// Deinitialize the BSD service.
|
||||
void bsdExit(void);
|
||||
Service* bsdGetServiceSession(void);
|
||||
@ -73,8 +73,3 @@ int bsdClose(int fd);
|
||||
int bsdDuplicateSocket(int sockfd);
|
||||
|
||||
// TODO: Reverse-engineer GetResourceStatistics. Implement sendmmsg/recvmmsg (custom (un)serialization)
|
||||
|
||||
/// Initialize the BSD service using the default configuration.
|
||||
static inline Result bsdInitializeDefault(void) {
|
||||
return bsdInitialize(bsdGetDefaultInitConfig());
|
||||
}
|
||||
|
@ -84,6 +84,9 @@ static const SocketInitConfig g_defaultSocketInitConfig = {
|
||||
|
||||
.sb_efficiency = 4,
|
||||
|
||||
.num_bsd_sessions = 3,
|
||||
.bsd_service_type = BsdServiceType_User,
|
||||
|
||||
.serialized_out_addrinfos_max_size = 0x1000,
|
||||
.serialized_out_hostent_max_size = 0x200,
|
||||
.bypass_nsd = false,
|
||||
@ -96,6 +99,9 @@ const SocketInitConfig *socketGetDefaultInitConfig(void) {
|
||||
|
||||
Result socketInitialize(const SocketInitConfig *config) {
|
||||
Result ret = 0;
|
||||
if (!config)
|
||||
config = &g_defaultSocketInitConfig;
|
||||
|
||||
BsdInitConfig bcfg = {
|
||||
.version = config->bsdsockets_version,
|
||||
|
||||
@ -110,6 +116,14 @@ Result socketInitialize(const SocketInitConfig *config) {
|
||||
.sb_efficiency = config->sb_efficiency,
|
||||
};
|
||||
|
||||
u32 num_bsd_sessions = config->num_bsd_sessions;
|
||||
u32 bsd_service_type = config->bsd_service_type;
|
||||
|
||||
if (!num_bsd_sessions)
|
||||
num_bsd_sessions = g_defaultSocketInitConfig.num_bsd_sessions;
|
||||
if (!bsd_service_type)
|
||||
bsd_service_type = g_defaultSocketInitConfig.bsd_service_type;
|
||||
|
||||
SfdnsresConfig sfdnsresConfig = {
|
||||
.serialized_out_addrinfos_max_size = config->serialized_out_addrinfos_max_size,
|
||||
.serialized_out_hostent_max_size = config->serialized_out_hostent_max_size,
|
||||
@ -124,7 +138,7 @@ Result socketInitialize(const SocketInitConfig *config) {
|
||||
ret = nifmInitialize();
|
||||
if(R_FAILED(ret)) return ret;
|
||||
|
||||
ret = bsdInitialize(&bcfg);
|
||||
ret = bsdInitialize(&bcfg, num_bsd_sessions, bsd_service_type);
|
||||
if(R_SUCCEEDED(ret))
|
||||
dev = AddDevice(&g_socketDevoptab);
|
||||
else {
|
||||
@ -1614,7 +1628,7 @@ long gethostid(void) {
|
||||
rc = nifmGetCurrentIpAddress(&id);
|
||||
if(R_SUCCEEDED(rc))
|
||||
return id;
|
||||
return INADDR_LOOPBACK;
|
||||
return INADDR_LOOPBACK;
|
||||
}
|
||||
|
||||
int gethostname(char *name, size_t namelen) {
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "service_guard.h"
|
||||
#include "kernel/shmem.h"
|
||||
#include "kernel/rwlock.h"
|
||||
#include "sf/sessionmgr.h"
|
||||
#include "services/bsd.h"
|
||||
|
||||
typedef struct BsdSelectTimeval {
|
||||
@ -27,6 +28,7 @@ __thread int g_bsdErrno;
|
||||
|
||||
static Service g_bsdSrv;
|
||||
static Service g_bsdMonitor;
|
||||
static SessionMgr g_bsdSessionMgr;
|
||||
static u64 g_bsdClientPid = -1;
|
||||
|
||||
static TransferMemory g_bsdTmem;
|
||||
@ -45,7 +47,7 @@ static const BsdInitConfig g_defaultBsdInitConfig = {
|
||||
.sb_efficiency = 4,
|
||||
};
|
||||
|
||||
NX_GENERATE_SERVICE_GUARD_PARAMS(bsd, (const BsdInitConfig *config), (config));
|
||||
NX_GENERATE_SERVICE_GUARD_PARAMS(bsd, (const BsdInitConfig *config, u32 num_sessions, u32 service_type), (config, num_sessions, service_type));
|
||||
|
||||
// This function computes the minimal size of the transfer memory to be passed to @ref bsdInitalize.
|
||||
// Should the transfer memory be smaller than that, the BSD sockets service would only send
|
||||
@ -112,7 +114,10 @@ NX_INLINE int _bsdDispatchImpl(
|
||||
if (in_data_size)
|
||||
__builtin_memcpy(in, in_data, in_data_size);
|
||||
|
||||
Result rc = svcSendSyncRequest(srv.session);
|
||||
int slot = sessionmgrAttachClient(&g_bsdSessionMgr);
|
||||
Result rc = svcSendSyncRequest(sessionmgrGetClientSession(&g_bsdSessionMgr, slot));
|
||||
sessionmgrDetachClient(&g_bsdSessionMgr, slot);
|
||||
|
||||
int ret = -1;
|
||||
int errno_ = -1;
|
||||
void* out_ptr = NULL;
|
||||
@ -187,19 +192,25 @@ const BsdInitConfig *bsdGetDefaultInitConfig(void) {
|
||||
return &g_defaultBsdInitConfig;
|
||||
}
|
||||
|
||||
Result _bsdInitialize(const BsdInitConfig *config) {
|
||||
Result _bsdInitialize(const BsdInitConfig *config, u32 num_sessions, u32 service_type) {
|
||||
if (!config)
|
||||
config = &g_defaultBsdInitConfig;
|
||||
|
||||
const char* bsd_srv = "bsd:s";
|
||||
Result rc = smGetService(&g_bsdSrv, bsd_srv);
|
||||
if (R_FAILED(rc)) {
|
||||
bsd_srv = "bsd:u";
|
||||
rc = smGetService(&g_bsdSrv, bsd_srv);
|
||||
SmServiceName bsd_srv = {0};
|
||||
Result rc = MAKERESULT(Module_Libnx, LibnxError_BadInput);
|
||||
|
||||
if (service_type & BIT(1)) {
|
||||
bsd_srv = smEncodeName("bsd:s");
|
||||
rc = smGetServiceWrapper(&g_bsdSrv, bsd_srv);
|
||||
}
|
||||
|
||||
if (R_FAILED(rc) && (service_type & BIT(0))) {
|
||||
bsd_srv = smEncodeName("bsd:u");
|
||||
rc = smGetServiceWrapper(&g_bsdSrv, bsd_srv);
|
||||
}
|
||||
|
||||
if (R_SUCCEEDED(rc))
|
||||
rc = smGetService(&g_bsdMonitor, bsd_srv);
|
||||
rc = smGetServiceWrapper(&g_bsdMonitor, bsd_srv);
|
||||
|
||||
if (R_SUCCEEDED(rc))
|
||||
rc = tmemCreate(&g_bsdTmem, _bsdGetTransferMemSizeForConfig(config), 0);
|
||||
@ -210,11 +221,15 @@ Result _bsdInitialize(const BsdInitConfig *config) {
|
||||
if (R_SUCCEEDED(rc))
|
||||
rc = _bsdStartMonitoring(g_bsdClientPid);
|
||||
|
||||
if (R_SUCCEEDED(rc))
|
||||
rc = sessionmgrCreate(&g_bsdSessionMgr, g_bsdSrv.session, num_sessions);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void _bsdCleanup(void) {
|
||||
g_bsdClientPid = 0;
|
||||
sessionmgrClose(&g_bsdSessionMgr);
|
||||
serviceClose(&g_bsdMonitor);
|
||||
serviceClose(&g_bsdSrv);
|
||||
tmemClose(&g_bsdTmem);
|
||||
|
Loading…
Reference in New Issue
Block a user