Add Find Host PC feature

This commit is contained in:
rock88 2021-02-23 14:54:11 +03:00
parent c4a10ced6f
commit 1be75b0c93
11 changed files with 139 additions and 16 deletions

View file

@ -35,11 +35,13 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
enableASanStackUseAfterReturn = "YES"
enableUBSanitizer = "YES"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View file

@ -49,16 +49,16 @@ void Settings::set_working_dir(std::string working_dir) {
}
void Settings::add_host(const Host& host) {
auto it = std::find_if(m_hosts.begin(), m_hosts.end(), [host](auto h){ return h.address == host.address; });
remove_host(host);
if (it == m_hosts.end()) {
m_hosts.push_back(host);
save();
}
m_hosts.push_back(host);
save();
}
void Settings::remove_host(const Host& host) {
auto it = std::find_if(m_hosts.begin(), m_hosts.end(), [host](auto h){ return h.address == host.address; });
auto it = std::find_if(m_hosts.begin(), m_hosts.end(), [host](auto h){
return h.address == host.address || h.hostname == host.hostname || h.mac == host.mac;
});
if (it != m_hosts.end()) {
m_hosts.erase(it);

View file

@ -10,6 +10,7 @@
#include <future>
#include <nanogui/nanogui.h>
#include <unistd.h>
#include <switch.h>
static std::mutex m_async_mutex;
static std::vector<std::function<void()>> m_tasks;
@ -33,7 +34,6 @@ static void task_loop() {
}
#ifdef __SWITCH__
#include <switch.h>
static Thread task_loop_thread;
static void start_task_loop() {
threadCreate(
@ -76,6 +76,59 @@ void GameStreamClient::stop() {
#endif
}
std::vector<std::string> GameStreamClient::host_addresses_for_find() {
std::vector<std::string> addresses;
u32 address;
Result result = nifmGetCurrentIpAddress(&address);
if (R_SUCCEEDED(result)) {
int a = address & 0xFF;
int b = (address >> 8) & 0xFF;
int c = (address >> 16) & 0xFF;
int d = (address >> 24) & 0xFF;
for (int i = 0; i < 256; i++) {
if (i == d) {
continue;
}
addresses.push_back(std::to_string(a) + "." + std::to_string(b) + "." + std::to_string(c) + "." + std::to_string(i));
}
}
return addresses;
}
void GameStreamClient::find_host(ServerCallback<Host> callback) {
perform_async([this, callback] {
auto addresses = host_addresses_for_find();
if (addresses.empty()) {
nanogui::async([callback] { callback(GSResult<Host>::failure("Can't obtain IP address...")); });
} else {
bool found = false;
for (int i = 0; i < addresses.size(); i++) {
SERVER_DATA server_data;
int status = gs_init(&server_data, addresses[i], true);
if (status == GS_OK) {
found = true;
Host host;
host.address = addresses[i];
host.hostname = server_data.hostname;
host.mac = server_data.mac;
nanogui::async([callback, host] { callback(GSResult<Host>::success(host)); });
break;
}
}
if (!found) {
nanogui::async([callback] { callback(GSResult<Host>::failure("Host PC not found...")); });
}
}
});
}
void GameStreamClient::wake_up_host(const Host &host, ServerCallback<bool> callback) {
perform_async([this, host, callback] {
if (WakeOnLanManager::instance().wake_up_host(host)) {

View file

@ -66,6 +66,8 @@ public:
void start();
void stop();
std::vector<std::string> host_addresses_for_find();
void find_host(ServerCallback<Host> callback);
void wake_up_host(const Host &host, ServerCallback<bool> callback);
void connect(const std::string &address, ServerCallback<SERVER_DATA> callback);
void pair(const std::string &address, const std::string &pin, ServerCallback<bool> callback);

View file

@ -25,8 +25,10 @@ int sigaction(int a, const struct sigaction* b, struct sigaction* c) {
void userAppInit() {
socketInitializeDefault();
nxlinkStdio();
nifmInitialize(NifmServiceType_User);
}
void userAppExit() {
socketExit();
nifmExit();
}

View file

@ -1,6 +1,12 @@
// Some mock part of libnx stuff for import and use <switch.h> on others plaforms
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <unistd.h>
#pragma once
typedef uint8_t u8; ///< 8-bit unsigned integer.
@ -480,3 +486,17 @@ inline static Result hidInitializeVibrationDevices(HidVibrationDeviceHandle *han
inline static Result hidSendVibrationValues(const HidVibrationDeviceHandle *handles, const HidVibrationValue *values, s32 count) {
return 0;
}
inline static Result nifmGetCurrentIpAddress(u32* out) {
struct ifreq ifr;
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, "en0", IFNAMSIZ - 1);
int fd = socket(AF_INET, SOCK_DGRAM, 0);
ioctl(fd, SIOCGIFADDR, &ifr);
close(fd);
*out = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
return 0;
}

View file

@ -28,6 +28,9 @@ void Alert::perform_layout(NVGcontext *ctx) {
m_button_container->set_fixed_width(screen()->width() / 2);
m_container->set_fixed_width(screen()->width() / 2);
for (auto child: m_container->children()) {
child->set_fixed_width(m_container->fixed_width() - 40);
}
for (auto child: m_button_container->children()) {
child->set_fixed_width(m_container->fixed_width() - 20);
}

View file

@ -3,10 +3,10 @@
using namespace nanogui;
AddHostButton::AddHostButton(Widget* parent): Button(parent, "") {
AddHostButton::AddHostButton(Widget* parent, AddHostButtonType type): Button(parent, ""), m_type(type) {
set_layout(new BoxLayout(Orientation::Vertical, Alignment::Middle));
add<Widget>()->set_fixed_height(170);
auto label = add<Label>("Add Host");
auto label = add<Label>(type == AddHostButtonTypeFind ? "Find Host" : "Add Host");
label->set_font_size(20);
screen()->perform_layout();
}
@ -25,7 +25,7 @@ void AddHostButton::draw(NVGcontext *ctx) {
nvgText(ctx, width() / 2, height() / 2 - 4, utf8(FA_DESKTOP).data(), NULL);
nvgFontSize(ctx, 40);
nvgText(ctx, width() / 2, height() / 2 - 16, utf8(FA_PLUS).data(), NULL);
nvgText(ctx, width() / 2, height() / 2 - 16, utf8(m_type == AddHostButtonTypeFind ? FA_SEARCH : FA_PLUS).data(), NULL);
nvgRestore(ctx);
}

View file

@ -1,9 +1,17 @@
#include <nanogui/nanogui.h>
#pragma once
enum AddHostButtonType: int {
AddHostButtonTypeFind = 0,
AddHostButtonTypeAdd
};
class AddHostButton: public nanogui::Button {
public:
AddHostButton(nanogui::Widget* parent);
AddHostButton(nanogui::Widget* parent, AddHostButtonType type);
void draw(NVGcontext *ctx) override;
private:
AddHostButtonType m_type;
};

View file

@ -61,7 +61,7 @@ void MainWindow::reload() {
});
}
} else {
auto alert = screen()->add<Alert>("Error", "Innactive host...");
auto alert = screen()->add<Alert>("Error", "Innactive host...", false);
if (!button->host().mac.empty()) {
alert->add_button("Wake Up", [this, button] {
@ -73,13 +73,30 @@ void MainWindow::reload() {
Settings::instance().remove_host(button->host());
reload();
});
alert->add_button("Cancel");
}
});
}
auto button = button_container->add<AddHostButton>();
button->set_fixed_size(Size(200, 200));
button->set_callback([this] {
auto find_button = button_container->add<AddHostButton>(AddHostButtonTypeFind);
find_button->set_fixed_size(Size(200, 200));
find_button->set_callback([this] {
auto addresses = GameStreamClient::instance().host_addresses_for_find();
if (addresses.empty()) {
screen()->add<Alert>("Error", "Can't obtain IP address...");
} else {
auto alert = screen()->add<Alert>("Find Host", "Search Host PC in the same network as yours Switch by evalute IP addresses from " + addresses.front() + " to " + addresses.back() + ".\nPlease check your PC and Switch network before tap on a Find.", false);
alert->add_button("Find", [this] {
find_host();
});
alert->add_button("Cancel");
}
});
auto add_button = button_container->add<AddHostButton>(AddHostButtonTypeAdd);
add_button->set_fixed_size(Size(200, 200));
add_button->set_callback([this] {
push<AddHostWindow>();
});
@ -114,3 +131,18 @@ void MainWindow::wake_up_host(const Host &host) {
}
});
}
void MainWindow::find_host() {
auto loader = add<LoadingOverlay>("Find Host...");
GameStreamClient::instance().find_host([this, loader](auto result) {
loader->dispose();
if (result.isSuccess()) {
Settings::instance().add_host(result.value());
reload();
} else {
screen()->add<Alert>("Error", result.error());
}
});
}

View file

@ -14,4 +14,5 @@ public:
private:
void reload();
void wake_up_host(const Host &host);
void find_host();
};