int accept(int sockfd, struct sockaddr *address, socklen_t *addrlen) { int ret, fd, dev; fd = _socketGetFd(sockfd); if(fd == -1) return -1; dev = __get_handle(sockfd)->device; sockfd = fd; fd = __alloc_handle(dev); if(fd == -1) return -1; ret = _socketParseBsdResult(NULL, bsdAccept(sockfd, address, addrlen)); if(ret == -1) { __release_handle(fd); return -1; } else { *(int *)__get_handle(fd)->fileStruct = ret; return fd; } }
int socket(int domain, int type, int protocol) { int ret, fd, dev; dev = FindDevice("soc:"); if(dev == -1) return -1; fd = __alloc_handle(dev); if(fd == -1) return -1; ret = _socketParseBsdResult(NULL, bsdSocket(domain, type, protocol)); if(ret == -1) { __release_handle(fd); return -1; } else { *(int *)__get_handle(fd)->fileStruct = ret; return fd; } }
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { int ret = 0; int tmp_addrlen = 0x1c; int fd, dev; __handle *handle; u32 *cmdbuf = getThreadCommandBuffer(); u8 tmpaddr[0x1c]; u32 saved_threadstorage[2]; sockfd = soc_get_fd(sockfd); if(sockfd < 0) { errno = -sockfd; return -1; } dev = FindDevice("soc:"); if(dev < 0) { errno = ENODEV; return -1; } fd = __alloc_handle(sizeof(__handle) + sizeof(Handle)); if(fd < 0) { errno = ENOMEM; return -1; } handle = __get_handle(fd); handle->device = dev; handle->fileStruct = ((void *)handle) + sizeof(__handle); memset(tmpaddr, 0, 0x1c); cmdbuf[0] = IPC_MakeHeader(0x4,2,2); // 0x40082 cmdbuf[1] = (u32)sockfd; cmdbuf[2] = (u32)tmp_addrlen; cmdbuf[3] = IPC_Desc_CurProcessHandle(); u32 * staticbufs = getThreadStaticBuffers(); saved_threadstorage[0] = staticbufs[0]; saved_threadstorage[1] = staticbufs[1]; staticbufs[0] = IPC_Desc_StaticBuffer(tmp_addrlen,0); staticbufs[1] = (u32)tmpaddr; ret = svcSendSyncRequest(SOCU_handle); staticbufs[0] = saved_threadstorage[0]; staticbufs[1] = saved_threadstorage[1]; if(ret != 0) { __release_handle(fd); errno = SYNC_ERROR; return ret; } ret = (int)cmdbuf[1]; if(ret == 0) ret = _net_convert_error(cmdbuf[2]); if(ret < 0) errno = -ret; if(ret >= 0 && addr != NULL) { addr->sa_family = tmpaddr[1]; if(*addrlen > tmpaddr[0]) *addrlen = tmpaddr[0]; memcpy(addr->sa_data, &tmpaddr[2], *addrlen - 2); } if(ret < 0) { __release_handle(fd); return -1; } else *(Handle*)handle->fileStruct = ret; return fd; }
int socket(int domain, int type, int protocol) { int ret = 0; int fd, dev; __handle *handle; u32 *cmdbuf = getThreadCommandBuffer(); // The protocol on the 3DS *must* be 0 to work // To that end, when appropriate, we will make the change for the user if (domain == AF_INET && type == SOCK_STREAM && protocol == IPPROTO_TCP) { protocol = 0; // TCP is the only option, so 0 will work as expected } if (domain == AF_INET && type == SOCK_DGRAM && protocol == IPPROTO_UDP) { protocol = 0; // UDP is the only option, so 0 will work as expected } cmdbuf[0] = IPC_MakeHeader(0x2,3,2); // 0x200C2 cmdbuf[1] = domain; cmdbuf[2] = type; cmdbuf[3] = protocol; cmdbuf[4] = IPC_Desc_CurProcessHandle(); dev = FindDevice("soc:"); if(dev < 0) { errno = ENODEV; return -1; } fd = __alloc_handle(sizeof(__handle) + sizeof(Handle)); if(fd < 0) { errno = ENOMEM; return -1; } handle = __get_handle(fd); handle->device = dev; handle->fileStruct = ((void *)handle) + sizeof(__handle); ret = svcSendSyncRequest(SOCU_handle); if(ret != 0) { __release_handle(fd); errno = SYNC_ERROR; return ret; } ret = (int)cmdbuf[1]; if(ret == 0)ret = cmdbuf[2]; if(ret < 0) { __release_handle(fd); if(cmdbuf[1] == 0)errno = _net_convert_error(ret); if(cmdbuf[1] != 0)errno = SYNC_ERROR; return -1; } *(Handle*)handle->fileStruct = cmdbuf[2]; return fd; }
Result socketInitialize(const SocketInitConfig *config) { Result ret = 0; BsdInitConfig bcfg = { .version = config->bsdsockets_version, .tcp_tx_buf_size = config->tcp_tx_buf_size, .tcp_rx_buf_size = config->tcp_rx_buf_size, .tcp_tx_buf_max_size = config->tcp_tx_buf_max_size, .tcp_rx_buf_max_size = config->tcp_rx_buf_max_size, .udp_tx_buf_size = config->udp_tx_buf_size, .udp_rx_buf_size = config->udp_rx_buf_size, .sb_efficiency = config->sb_efficiency, }; SfdnsresConfig sfdnsresConfig = { .serialized_out_addrinfos_max_size = config->serialized_out_addrinfos_max_size, .serialized_out_hostent_max_size = config->serialized_out_hostent_max_size, .bypass_nsd = config->bypass_nsd, .timeout = config->dns_timeout, }; int dev = FindDevice("soc:"); if(dev != -1) return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized); ret = bsdInitialize(&bcfg); if(R_SUCCEEDED(ret)) dev = AddDevice(&g_socketDevoptab); else { socketExit(); return ret; } if(dev == -1) { socketExit(); return MAKERESULT(Module_Libnx, LibnxError_TooManyDevOpTabs); } else { g_bsdResult = 0; g_bsdErrno = 0; g_sfdnsresConfig = sfdnsresConfig; g_sfdnsresResult = 0; } return ret; } void socketExit(void) { RemoveDevice("soc:"); bsdExit(); } Result socketGetLastBsdResult(void) { return g_bsdResult; } Result socketGetLastSfdnsresResult(void) { return g_sfdnsresResult; } /***********************************************************************************************************************/ static int _socketGetFd(int fd) { __handle *handle = __get_handle(fd); if(handle == NULL) { errno = EBADF; return -1; } if(strcmp(devoptab_list[handle->device]->name, "soc") != 0) { errno = ENOTSOCK; return -1; } return *(int *)handle->fileStruct; }