From fb9e126f3a615ec63f56d7c3ca9e414530219dee Mon Sep 17 00:00:00 2001 From: TuxSH Date: Mon, 22 Jan 2018 18:50:44 +0100 Subject: [PATCH] Make the bsd service work properly --- nx/include/switch/services/bsd.h | 55 ++++++++++++++++++++++++++++---- nx/source/services/bsd.c | 44 +++++++++++++++++-------- 2 files changed, 78 insertions(+), 21 deletions(-) diff --git a/nx/include/switch/services/bsd.h b/nx/include/switch/services/bsd.h index 89fbb56d..51a0f1d3 100644 --- a/nx/include/switch/services/bsd.h +++ b/nx/include/switch/services/bsd.h @@ -2,6 +2,21 @@ #include "types.h" #include "kernel/tmem.h" +/// Configuration structure for bsdInitalize +typedef struct { + u32 version; ///< Observed 1 on 2.0 LibAppletWeb, 2 on 3.0. + + u32 tcp_tx_buf_size; ///< Size of the TCP transfer (send) buffer (initial or fixed). + u32 tcp_rx_buf_size; ///< Size of the TCP recieve buffer (initial or fixed). + u32 tcp_tx_buf_max_size; ///< Maximum size of the TCP transfer (send) buffer. If it is 0, the size of the buffer is fixed to its initial value. + u32 tcp_rx_buf_max_size; ///< Maximum size of the TCP receive buffer. If it is 0, the size of the buffer is fixed to its initial value. + + u32 udp_tx_buf_size; ///< Size of the UDP transfer (send) buffer (typically 0x2400 bytes). + u32 udp_rx_buf_size; ///< Size of the UDP receive buffer (typically 0xA500 bytes). + + u32 sb_efficiency; ///< Number of buffers for each socket (standard values range from 1 to 8). +} BsdConfig; + struct bsd_sockaddr_in { u8 sin_len; u8 sin_family; @@ -10,21 +25,47 @@ struct bsd_sockaddr_in { u8 sin_zero[8]; }; -Result bsdInitialize(TransferMemory* tmem); +const BsdConfig *bsdGetDefaultConfig(void); +Result bsdInitialize(TransferMemory* tmem, const BsdConfig *config); int bsdGetErrno(void); -int bsdConnect(int sockfd, void* addr, u32 addrlen); +int bsdConnect(int sockfd, const void* addr, u32 addrlen); int bsdSocket(int domain, int type, int protocol); -int bsdBind(int sockfd, void* addr, u32 addrlen); +int bsdBind(int sockfd, const void* addr, u32 addrlen); int bsdListen(int sockfd, int backlog); -int bsdSend(int sockfd, void* buffer, size_t length, int flags); -int bsdSendTo(int sockfd, void* buffer, size_t length, int flags, const struct bsd_sockaddr_in *dest_addr, size_t dest_len); +int bsdSend(int sockfd, const void* buffer, size_t length, int flags); +int bsdSendTo(int sockfd, const void* buffer, size_t length, int flags, const struct bsd_sockaddr_in *dest_addr, size_t dest_len); int bsdRecv(int sockfd, void* buffer, size_t length, int flags); int bsdSetSockOpt(int sockfd, int level, int option_name, const void *option_value, size_t option_size); -int bsdWrite(int sockfd, void* buffer, size_t length); +int bsdWrite(int sockfd, const void* buffer, size_t length); + +/** + * @brief 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 + * ZeroWindow packets (for TCP), resulting in a transfer rate not exceeding 1 byte/s. + * @param config Pointer to the BSD sockets service configuration. + */ +static inline size_t bsdGetTransferMemSizeForConfig(const BsdConfig *config) +{ + u32 tcp_tx_buf_max_size = config->tcp_tx_buf_max_size != 0 ? config->tcp_tx_buf_max_size : config->tcp_tx_buf_size; + u32 tcp_rx_buf_max_size = config->tcp_rx_buf_max_size != 0 ? config->tcp_rx_buf_max_size : config->tcp_rx_buf_size; + u32 sum = tcp_tx_buf_max_size + tcp_rx_buf_max_size + config->udp_tx_buf_size + config->udp_rx_buf_size; + + sum = ((sum + 0xFFF) >> 12) << 12; // page round-up + return (size_t)(config->sb_efficiency * sum); +} + +static inline size_t bsdGetTransferMemSizeForDefaultConfig(void) +{ + return bsdGetTransferMemSizeForConfig(bsdGetDefaultConfig()); +} + +static inline Result bsdInitializeDefault(TransferMemory* tmem) +{ + return bsdInitialize(tmem, bsdGetDefaultConfig()); +} #define BSD_AF_INET 2 #define BSD_AF_INET6 10 - #define BSD_IPPROTO_IP 0 #define BSD_IPPROTO_TCP 6 #define BSD_IPPROTO_UDP 17 diff --git a/nx/source/services/bsd.c b/nx/source/services/bsd.c index 374dce7c..fb7884d3 100644 --- a/nx/source/services/bsd.c +++ b/nx/source/services/bsd.c @@ -12,9 +12,23 @@ static Service g_bsdMonitor; static u64 g_bsdClientPid = -1; static int g_Errno = 0; +static const BsdConfig g_defaultBsdConfig = { + .version = 2, + + .tcp_tx_buf_size = 0x8000, + .tcp_rx_buf_size = 0x10000, + .tcp_tx_buf_max_size = 0x40000, + .tcp_rx_buf_max_size = 0x40000, + + .udp_tx_buf_size = 0x2400, + .udp_rx_buf_size = 0xA500, + + .sb_efficiency = 4, +}; + #define EPIPE 32 -static Result _bsdRegisterClient(Service* srv, TransferMemory* tmem, u64* pid_out) { +static Result _bsdRegisterClient(Service* srv, TransferMemory* tmem, const BsdConfig *config, u64* pid_out) { IpcCommand c; ipcInitialize(&c); ipcSendPid(&c); @@ -23,7 +37,8 @@ static Result _bsdRegisterClient(Service* srv, TransferMemory* tmem, u64* pid_ou struct { u64 magic; u64 cmd_id; - u64 unk0[5]; + BsdConfig config; + u64 pid_reserved; u64 tmem_sz; u64 pad[2]; } *raw; @@ -32,11 +47,8 @@ static Result _bsdRegisterClient(Service* srv, TransferMemory* tmem, u64* pid_ou raw->magic = SFCI_MAGIC; raw->cmd_id = 0; - raw->unk0[0] = 1; - raw->unk0[1] = 0x10000; - raw->unk0[2] = 0x40000; - raw->unk0[3] = 0xA500; - raw->unk0[4] = 13; + raw->config = *config; + raw->pid_reserved = 0; raw->tmem_sz = tmem->size; Result rc = serviceIpcDispatch(srv); @@ -92,7 +104,11 @@ static Result _bsdStartMonitor(Service* srv, u64 pid) { return rc; } -Result bsdInitialize(TransferMemory* tmem) { +const BsdConfig *bsdGetDefaultConfig(void) { + return &g_defaultBsdConfig; +} + +Result bsdInitialize(TransferMemory* tmem, const BsdConfig *config) { const char* bsd_srv = "bsd:s"; Result rc = smGetService(&g_bsdSrv, bsd_srv); @@ -105,7 +121,7 @@ Result bsdInitialize(TransferMemory* tmem) { rc = smGetService(&g_bsdMonitor, bsd_srv); if (R_SUCCEEDED(rc)) { - rc = _bsdRegisterClient(&g_bsdSrv, tmem, &g_bsdClientPid); + rc = _bsdRegisterClient(&g_bsdSrv, tmem, config, &g_bsdClientPid); if (R_SUCCEEDED(rc)) { rc = _bsdStartMonitor(&g_bsdMonitor, g_bsdClientPid); @@ -218,7 +234,7 @@ int bsdRecv(int sockfd, void* buffer, size_t length, int flags) { return ret; } -int bsdSend(int sockfd, void* buffer, size_t length, int flags) { +int bsdSend(int sockfd, const void* buffer, size_t length, int flags) { IpcCommand c; ipcInitialize(&c); ipcAddSendBuffer(&c, buffer, length, 0); @@ -267,7 +283,7 @@ int bsdSend(int sockfd, void* buffer, size_t length, int flags) { return ret; } -int bsdSendTo(int sockfd, void* buffer, size_t length, int flags, const struct bsd_sockaddr_in *dest_addr, size_t dest_len) { +int bsdSendTo(int sockfd, const void* buffer, size_t length, int flags, const struct bsd_sockaddr_in *dest_addr, size_t dest_len) { IpcCommand c; ipcInitialize(&c); ipcAddSendBuffer(&c, buffer, length, 0); @@ -319,7 +335,7 @@ int bsdSendTo(int sockfd, void* buffer, size_t length, int flags, const struct b return ret; } -int bsdConnect(int sockfd, void* addr, u32 addrlen) { +int bsdConnect(int sockfd, const void* addr, u32 addrlen) { IpcCommand c; ipcInitialize(&c); ipcAddSendBuffer(&c, addr, addrlen, 0); @@ -367,7 +383,7 @@ int bsdConnect(int sockfd, void* addr, u32 addrlen) { return fd; } -int bsdBind(int sockfd, void* addr, u32 addrlen) { +int bsdBind(int sockfd, const void* addr, u32 addrlen) { IpcCommand c; ipcInitialize(&c); ipcAddSendBuffer(&c, addr, addrlen, 0); @@ -513,7 +529,7 @@ int bsdSetSockOpt(int sockfd, int level, int option_name, const void *option_val return ret; } -int bsdWrite(int sockfd, void* buffer, size_t length) { +int bsdWrite(int sockfd, const void* buffer, size_t length) { IpcCommand c; ipcInitialize(&c); ipcAddSendBuffer(&c, buffer, length, 0);