From 6e407578c3f76241f4a9f0b42d13feee06b43724 Mon Sep 17 00:00:00 2001 From: Yukino Song Date: Sat, 31 Aug 2024 12:04:39 +0800 Subject: [PATCH] Add QR code pairing --- src/confighttp.cpp | 2 + src/main.cpp | 2 +- src/platform/common.h | 3 + src/platform/linux/misc.cpp | 77 ++++++++++ src/platform/macos/misc.mm | 6 + src/platform/windows/misc.cpp | 56 +++++++ src_assets/common/assets/web/pin.html | 142 ++++++++++++++---- .../assets/web/public/assets/js/qrcode.min.js | 1 + .../assets/web/public/assets/locale/en.json | 2 +- .../assets/web/public/assets/locale/zh.json | 2 +- 10 files changed, 262 insertions(+), 31 deletions(-) create mode 100644 src_assets/common/assets/web/public/assets/js/qrcode.min.js diff --git a/src/confighttp.cpp b/src/confighttp.cpp index dea8d411..e1f91963 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -835,6 +835,8 @@ namespace confighttp { } outputTree.put("otp", nvhttp::request_otp(passphrase, deviceName)); + outputTree.put("ip", platf::get_local_ip_for_gateway()); + outputTree.put("name", config::nvhttp.sunshine_name); outputTree.put("status", true); outputTree.put("message", "OTP created, effective within 3 minutes."); } diff --git a/src/main.cpp b/src/main.cpp index 26a47d6e..9a29c913 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -292,7 +292,7 @@ main(int argc, char *argv[]) { BOOST_LOG(fatal) << "HTTP interface failed to initialize"sv; #ifdef _WIN32 - BOOST_LOG(fatal) << "To relaunch Apollo successfully, use the shortcut in the Start Menu. Do not run Sunshine.exe manually."sv; + BOOST_LOG(fatal) << "To relaunch Apollo successfully, use the shortcut in the Start Menu. Do not run sunshine.exe manually."sv; std::this_thread::sleep_for(10s); #endif diff --git a/src/platform/common.h b/src/platform/common.h index d9c9583c..e8051fc2 100644 --- a/src/platform/common.h +++ b/src/platform/common.h @@ -567,6 +567,9 @@ namespace platf { std::string get_mac_address(const std::string_view &address); + std::string + get_local_ip_for_gateway(); + std::string from_sockaddr(const sockaddr *const); std::pair diff --git a/src/platform/linux/misc.cpp b/src/platform/linux/misc.cpp index b3e31ec6..3947d20f 100644 --- a/src/platform/linux/misc.cpp +++ b/src/platform/linux/misc.cpp @@ -239,6 +239,83 @@ namespace platf { return "00:00:00:00:00:00"s; } + std::string + get_local_ip_for_gateway() { + int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if (fd < 0) { + BOOST_LOG(warning) << "Socket creation failed"; + return ""; + } + + char buffer[8192]; + struct nlmsghdr *nlMsg = (struct nlmsghdr *)buffer; + struct rtmsg *rtMsg = (struct rtmsg *)NLMSG_DATA(nlMsg); + struct rtattr *rtAttr; + int len = 0; + + memset(nlMsg, 0, sizeof(struct nlmsghdr)); + nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); + nlMsg->nlmsg_type = RTM_GETROUTE; + nlMsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; + nlMsg->nlmsg_seq = 1; + nlMsg->nlmsg_pid = getpid(); + + if (send(fd, nlMsg, nlMsg->nlmsg_len, 0) < 0) { + close(fd); + BOOST_LOG(warning) << "Send message failed"; + return ""; + } + + len = recv(fd, nlMsg, sizeof(buffer), 0); + if (len < 0) { + close(fd); + BOOST_LOG(warning) << "Receive message failed"; + return ""; + } + + std::string local_ip; + + for (; NLMSG_OK(nlMsg, len); nlMsg = NLMSG_NEXT(nlMsg, len)) { + rtMsg = (struct rtmsg *)NLMSG_DATA(nlMsg); + if (rtMsg->rtm_family != AF_INET || rtMsg->rtm_table != RT_TABLE_MAIN) + continue; + + rtAttr = (struct rtattr *)RTM_RTA(rtMsg); + int rtLen = RTM_PAYLOAD(nlMsg); + + in_addr gateway; + in_addr local; + memset(&gateway, 0, sizeof(gateway)); + memset(&local, 0, sizeof(local)); + + for (; RTA_OK(rtAttr, rtLen); rtAttr = RTA_NEXT(rtAttr, rtLen)) { + switch(rtAttr->rta_type) { + case RTA_GATEWAY: + gateway.s_addr = *reinterpret_cast(RTA_DATA(rtAttr)); + break; + case RTA_PREFSRC: + local.s_addr = *reinterpret_cast(RTA_DATA(rtAttr)); + break; + default: + break; + } + } + + if (gateway.s_addr != 0 && local.s_addr != 0) { + local_ip = inet_ntoa(local); + break; + } + } + + close(fd); + + if (local_ip.empty()) { + BOOST_LOG(warning) << "No associated IP address found for the default gateway"; + } + + return local_ip; +} + bp::child run_command(bool elevated, bool interactive, const std::string &cmd, boost::filesystem::path &working_dir, const bp::environment &env, FILE *file, std::error_code &ec, bp::group *group) { if (!group) { diff --git a/src/platform/macos/misc.mm b/src/platform/macos/misc.mm index 6eca7d2e..cd07c830 100644 --- a/src/platform/macos/misc.mm +++ b/src/platform/macos/misc.mm @@ -168,6 +168,12 @@ namespace platf { return "00:00:00:00:00:00"s; } + // TODO: return actual IP + std::string + get_local_ip_for_gateway() { + return ""; + } + bp::child run_command(bool elevated, bool interactive, const std::string &cmd, boost::filesystem::path &working_dir, const bp::environment &env, FILE *file, std::error_code &ec, bp::group *group) { if (!group) { diff --git a/src/platform/windows/misc.cpp b/src/platform/windows/misc.cpp index 657807fa..412fef11 100644 --- a/src/platform/windows/misc.cpp +++ b/src/platform/windows/misc.cpp @@ -190,6 +190,62 @@ namespace platf { return "00:00:00:00:00:00"s; } + std::string + get_local_ip_for_gateway() { + PIP_ADAPTER_INFO pAdapterInfo; + PIP_ADAPTER_INFO pAdapter = nullptr; + DWORD dwRetVal = 0; + ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO); + + pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO)); + if (pAdapterInfo == nullptr) { + BOOST_LOG(warning) << "Error allocating memory needed to call GetAdaptersInfo"; + return ""; + } + + // Make an initial call to GetAdaptersInfo to get the necessary size into the ulOutBufLen variable + if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) { + free(pAdapterInfo); + pAdapterInfo = (IP_ADAPTER_INFO *)malloc(ulOutBufLen); + if (pAdapterInfo == nullptr) { + BOOST_LOG(warning) << "Error allocating memory needed to call GetAdaptersInfo"; + return ""; + } + } + + if ((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) != NO_ERROR) { + if (pAdapterInfo) { + free(pAdapterInfo); + } + BOOST_LOG(warning) << "GetAdaptersInfo failed with error: " + std::to_string(dwRetVal); + return ""; + } + + pAdapter = pAdapterInfo; + std::string local_ip; + + // Iterate through the list of adapters + while (pAdapter) { + IP_ADDR_STRING* pGateway = &pAdapter->GatewayList; + if (pGateway && pGateway->IpAddress.String[0] != '\0') { + // This adapter has a default gateway, use its IP address + local_ip = pAdapter->IpAddressList.IpAddress.String; + break; + } + pAdapter = pAdapter->Next; + } + + if (pAdapterInfo) { + free(pAdapterInfo); + } + + if (local_ip.empty()) { + BOOST_LOG(warning) << "No associated IP address found for the default gateway"; + } + + return local_ip; + } + HDESK syncThreadDesktop() { auto hDesk = OpenInputDesktop(DF_ALLOWOTHERACCOUNTHOOK, FALSE, GENERIC_ALL); diff --git a/src_assets/common/assets/web/pin.html b/src_assets/common/assets/web/pin.html index 79df60ec..56c2f31e 100644 --- a/src_assets/common/assets/web/pin.html +++ b/src_assets/common/assets/web/pin.html @@ -4,6 +4,7 @@ <%- header %> +