diff --git a/include/Keyboard.hpp b/include/Keyboard.hpp index f4c5349..4553645 100644 --- a/include/Keyboard.hpp +++ b/include/Keyboard.hpp @@ -7,7 +7,6 @@ #include "nn/swkbd/swkbd.h" #include "logger.hpp" -#include "sead/prim/seadSafeString.h" typedef void (*KeyboardSetup)(nn::swkbd::KeyboardConfig&); @@ -37,7 +36,7 @@ class Keyboard { al::AsyncFunctorThread* mThread; nn::swkbd::String mResultString; - sead::FixedSafeString<0x10> mInitialText; + hostname mInitialText; KeyboardSetup mSetupFunc; const char16_t *mHeaderText = u"Enter Server IP Here!"; @@ -51,4 +50,4 @@ class Keyboard { int mTextCheckSize; char* mCustomizeDicBuf; int mCustomizeDicSize; -}; \ No newline at end of file +}; diff --git a/include/nn/socket.h b/include/nn/socket.h index b308e33..3e8290b 100644 --- a/include/nn/socket.h +++ b/include/nn/socket.h @@ -17,6 +17,15 @@ struct sockaddr u8 _8[8]; // 8 }; +struct hostent +{ + char* h_name; + char** h_aliases; + int h_addrtype; + int h_length; + char** h_addr_list; +}; + namespace nn { namespace socket { @@ -34,6 +43,8 @@ s32 Recv(s32 socket, void* out, ulong outLen, s32 flags); u16 InetHtons(u16 val); s32 InetAton(const char* addressStr, in_addr* addressOut); +struct hostent* GetHostByName(const char* name); + u32 GetLastErrno(); } } diff --git a/include/server/Client.hpp b/include/server/Client.hpp index 7682263..a01749d 100644 --- a/include/server/Client.hpp +++ b/include/server/Client.hpp @@ -259,7 +259,7 @@ class Client { Keyboard* mKeyboard = nullptr; // keyboard for setting server IP - sead::FixedSafeString<0x10> mServerIP; + hostname mServerIP; int mServerPort = 0; @@ -314,4 +314,4 @@ class Client { PuppetHolder *mPuppetHolder = nullptr; PuppetInfo mDebugPuppetInfo; -}; \ No newline at end of file +}; diff --git a/include/server/SocketClient.hpp b/include/server/SocketClient.hpp index 128af87..42dad30 100644 --- a/include/server/SocketClient.hpp +++ b/include/server/SocketClient.hpp @@ -33,4 +33,11 @@ class SocketClient : public SocketBase { private: int maxBufSize = 100; -}; \ No newline at end of file + + /** + * @param str a string containing an IPv4 address or a hostname that can be resolved via DNS + * @param out IPv4 address + * @return if this function was successfull and out contains a valid IP address + */ + bool stringToIPAddress(const char* str, in_addr* out); +}; diff --git a/include/types.h b/include/types.h index 397a50c..e571b4d 100644 --- a/include/types.h +++ b/include/types.h @@ -5,6 +5,7 @@ #include #include #include +#include "sead/prim/seadSafeString.h" typedef unsigned char u8; typedef unsigned short u16; @@ -41,6 +42,9 @@ typedef unsigned int undefined3; typedef unsigned int undefined4; typedef unsigned long undefined8; +const u8 MAX_HOSTNAME_LENGTH = 50; +typedef sead::FixedSafeString hostname; + enum SocketLogState { SOCKET_LOG_UNINITIALIZED = 0, SOCKET_LOG_CONNECTED = 1, diff --git a/source/server/Client.cpp b/source/server/Client.cpp index 6059bc1..9a339ef 100644 --- a/source/server/Client.cpp +++ b/source/server/Client.cpp @@ -30,7 +30,6 @@ #include "packets/PlayerConnect.h" #include "packets/PlayerDC.h" #include "packets/TagInf.h" -#include "prim/seadSafeString.h" #include "puppets/PuppetInfo.h" #include "sead/basis/seadRawPrint.h" #include "sead/math/seadQuat.h" @@ -300,13 +299,13 @@ bool Client::openKeyboardIP() { sInstance->mServerIP.cstr(), [](nn::swkbd::KeyboardConfig& config) { config.keyboardMode = nn::swkbd::KeyboardMode::ModeNumeric; config.leftOptionalSymbolKey = '.'; - config.textMaxLength = 15; + config.textMaxLength = MAX_HOSTNAME_LENGTH; config.textMinLength = 1; config.isUseUtf8 = true; config.inputFormMode = nn::swkbd::InputFormMode::OneLine; }); - sead::FixedSafeString<0x10> prevIp = sInstance->mServerIP; + hostname prevIp = sInstance->mServerIP; while (true) { if (sInstance->mKeyboard->isThreadDone()) { @@ -1573,4 +1572,4 @@ void Client::hideConnect() { return; sInstance->mConnectionWait->tryEnd(); -} \ No newline at end of file +} diff --git a/source/server/SocketClient.cpp b/source/server/SocketClient.cpp index 9dd5d97..1d06879 100644 --- a/source/server/SocketClient.cpp +++ b/source/server/SocketClient.cpp @@ -11,11 +11,10 @@ nn::Result SocketClient::init(const char* ip, u16 port) { - sock_ip = ip; - - this->port = port; + this->sock_ip = ip; + this->port = port; - in_addr hostAddress = { 0 }; + in_addr hostAddress = { 0 }; sockaddr serverAddress = { 0 }; Logger::log("SocketClient::init: %s:%d sock %s\n", ip, port, getStateChar()); @@ -34,18 +33,20 @@ nn::Result SocketClient::init(const char* ip, u16 port) { return -1; } #endif - + if ((this->socket_log_socket = nn::socket::Socket(2, 1, 6)) < 0) { - Logger::log("Socket Unavailable.\n"); - this->socket_errno = nn::socket::GetLastErrno(); this->socket_log_state = SOCKET_LOG_UNAVAILABLE; return -1; } - - nn::socket::InetAton(this->sock_ip, &hostAddress); + if (! this->stringToIPAddress(this->sock_ip, &hostAddress)) { + Logger::log("IP address is invalid or hostname not resolveable.\n"); + this->socket_errno = nn::socket::GetLastErrno(); + this->socket_log_state = SOCKET_LOG_UNAVAILABLE; + return -1; + } serverAddress.address = hostAddress; serverAddress.port = nn::socket::InetHtons(this->port); @@ -205,4 +206,24 @@ bool SocketClient::closeSocket() { } return result; -} \ No newline at end of file +} + +bool SocketClient::stringToIPAddress(const char* str, in_addr* out) { + // string to IPv4 + if (nn::socket::InetAton(str, out)) { + return true; + } + + // get IPs via DNS + struct hostent *he = nn::socket::GetHostByName(str); + if (! he) { return false; } + + // might give us multiple IP addresses, so pick the first one + struct in_addr **addr_list = (struct in_addr **) he->h_addr_list; + for (int i = 0 ; addr_list[i] != NULL ; i++) { + *out = *addr_list[i]; + return true; + } + + return false; +}