diff --git a/nx/include/switch/runtime/devices/socket.h b/nx/include/switch/runtime/devices/socket.h index 155eea6f..1f5cd82a 100644 --- a/nx/include/switch/runtime/devices/socket.h +++ b/nx/include/switch/runtime/devices/socket.h @@ -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); } - diff --git a/nx/include/switch/services/bsd.h b/nx/include/switch/services/bsd.h index 7081e247..127482ab 100644 --- a/nx/include/switch/services/bsd.h +++ b/nx/include/switch/services/bsd.h @@ -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()); -} diff --git a/nx/source/runtime/devices/socket.c b/nx/source/runtime/devices/socket.c index acc752c7..37b448e9 100644 --- a/nx/source/runtime/devices/socket.c +++ b/nx/source/runtime/devices/socket.c @@ -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) { diff --git a/nx/source/services/bsd.c b/nx/source/services/bsd.c index e0eb22fa..3f171397 100644 --- a/nx/source/services/bsd.c +++ b/nx/source/services/bsd.c @@ -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);