Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Supports Hostname & Multiple Instances on Single Machine #457

Merged
merged 2 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ target_link_libraries(moonlight-lib PUBLIC commons-ss4s-modules-list commons-sps

target_link_libraries(moonlight-lib PUBLIC commons-logging commons-gamecontrollerdb-updater commons-lazy
commons-refcounter commons-executor commons-linked-list commons-wol commons-ini-writer commons-copyfile
commons-sockaddr)
commons-sockaddr commons-host)

configure_file(src/app/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h @ONLY)
target_include_directories(moonlight-lib PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
Expand Down
2 changes: 1 addition & 1 deletion core/libgamestream/src/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -866,7 +866,7 @@ static int load_server_status(GS_CLIENT hnd, PSERVER_DATA server) {
}

i++;
} while (ret != GS_OK && i < 2);
} while (ret == GS_ERROR && i < 2);

if (ret == GS_OK && !server->unsupported) {
if (server->serverMajorVersion > MAX_SUPPORTED_GFE_VERSION) {
Expand Down
6 changes: 4 additions & 2 deletions src/app/backend/pcmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "libgamestream/client.h"
#include "uuidstr.h"
#include "sockaddr.h"
#include "host.h"

typedef struct app_t app_t;
typedef struct pcmanager_t pcmanager_t;
Expand Down Expand Up @@ -77,7 +78,7 @@ void pcmanager_unregister_listener(pcmanager_t *manager, const pcmanager_listene
* @param userdata
* @return
*/
bool pcmanager_manual_add(pcmanager_t *manager, sockaddr_t *address, pcmanager_callback_t callback, void *userdata);
bool pcmanager_manual_add(pcmanager_t *manager, host_t *host, pcmanager_callback_t callback, void *userdata);

/**
* @brief Generates a PIN code, and start pairing process.
Expand Down Expand Up @@ -133,4 +134,5 @@ bool pcmanager_send_wol(pcmanager_t *manager, const uuidstr_t *uuid, pcmanager_c
* @param userdata
* @return
*/
int pcmanager_update_by_ip(worker_context_t *context, const char *ip, uint16_t port, bool force);
int pcmanager_update_by_host(worker_context_t *context, const char *ip, uint16_t port, bool force);

2 changes: 2 additions & 0 deletions src/app/backend/pcmanager/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
target_sources(moonlight-lib PRIVATE discovery_callback.c)

add_subdirectory(discovery)
19 changes: 2 additions & 17 deletions src/app/backend/pcmanager/discovery/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,17 +1,2 @@
include(CheckSymbolExists)

check_symbol_exists(DNSServiceCreateConnection "dns_sd.h" HAVE_DNSSD)

if (HAVE_DNSSD)
target_sources(moonlight-lib PRIVATE discovery_dnssd.c)
elseif (OS_WINDOWS)
pkg_check_modules(MICRODNS REQUIRED microdns)
target_link_libraries(moonlight-lib PUBLIC ${MICRODNS_LIBRARIES})
target_sources(moonlight-lib PRIVATE discovery_libmicrodns.c)
else ()
set(BUILD_SHARED_LIBS ON)
include(BuildMicrodns)
target_link_libraries(moonlight-lib PUBLIC microdns)
unset(BUILD_SHARED_LIBS)
target_sources(moonlight-lib PRIVATE discovery_libmicrodns.c)
endif ()
target_sources(moonlight-lib PRIVATE discovery.c throttle.c)
add_subdirectory(impl)
62 changes: 62 additions & 0 deletions src/app/backend/pcmanager/discovery/discovery.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include "discovery.h"
#include "throttle.h"

#include "impl/impl.h"

#include "util/bus.h"
#include "logging.h"

static int discovery_worker_wrapper(void *arg);

void discovery_init(discovery_t *discovery, discovery_callback callback, void *user_data) {
discovery->lock = SDL_CreateMutex();
discovery->task = NULL;
discovery_throttle_init(&discovery->throttle, callback, user_data);
}

void discovery_deinit(discovery_t *discovery) {
discovery_throttle_deinit(&discovery->throttle);
discovery_stop(discovery);
SDL_DestroyMutex(discovery->lock);
}

void discovery_start(discovery_t *discovery) {
SDL_LockMutex(discovery->lock);
if (discovery->task != NULL) {
SDL_UnlockMutex(discovery->lock);
return;
}
discovery_task_t *task = SDL_calloc(1, sizeof(discovery_task_t));
commons_log_info("Discovery", "Start task %p", task);
task->discovery = discovery;
task->lock = SDL_CreateMutex();
task->stop = false;
SDL_Thread *thread = SDL_CreateThread(discovery_worker_wrapper, "discovery", task);
SDL_DetachThread(thread);
discovery->task = task;
SDL_UnlockMutex(discovery->lock);
}

void discovery_stop(discovery_t *discovery) {
SDL_LockMutex(discovery->lock);
discovery_task_t *task = discovery->task;
if (task == NULL) {
SDL_UnlockMutex(discovery->lock);
return;
}
discovery->task = NULL;
discovery_worker_stop(task);
SDL_UnlockMutex(discovery->lock);
}

void discovery_discovered(struct discovery_t *discovery, const sockaddr_t *addr) {
discovery_throttle_on_discovered(&discovery->throttle, addr, 10000);
}

int discovery_worker_wrapper(void *arg) {
discovery_task_t *task = (discovery_task_t *) arg;
int result = discovery_worker(task);
SDL_DestroyMutex(task->lock);
free(arg);
return result;
}
48 changes: 48 additions & 0 deletions src/app/backend/pcmanager/discovery/discovery.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2024 Mariotaku <https://github.com/mariotaku>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

#pragma once

#include <stdbool.h>
#include <SDL2/SDL.h>
#include "sockaddr.h"

typedef void (*discovery_callback)(const sockaddr_t *addr, void *user_data);

typedef struct discovery_throttle_host_t discovery_throttle_host_t;

typedef struct discovery_throttle_t {
discovery_callback callback;
void *user_data;
discovery_throttle_host_t *hosts;
SDL_mutex *lock;
} discovery_throttle_t;

typedef struct discovery_t {
SDL_mutex *lock;
struct discovery_task_t *task;
discovery_throttle_t throttle;
} discovery_t;

void discovery_init(discovery_t *discovery, discovery_callback callback, void *user_data);

void discovery_start(discovery_t *discovery);

void discovery_stop(discovery_t *discovery);

void discovery_deinit(discovery_t *discovery);
17 changes: 17 additions & 0 deletions src/app/backend/pcmanager/discovery/impl/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
include(CheckSymbolExists)

check_symbol_exists(DNSServiceCreateConnection "dns_sd.h" HAVE_DNSSD)

if (HAVE_DNSSD)
target_sources(moonlight-lib PRIVATE dnssd.c)
else ()
target_sources(moonlight-lib PRIVATE microdns.c)
if (OS_WINDOWS)
pkg_check_modules(MICRODNS REQUIRED microdns)
target_link_libraries(moonlight-lib PUBLIC ${MICRODNS_LIBRARIES})
endif ()
set(BUILD_SHARED_LIBS ON)
include(BuildMicrodns)
target_link_libraries(moonlight-lib PUBLIC microdns)
unset(BUILD_SHARED_LIBS)
endif ()
36 changes: 36 additions & 0 deletions src/app/backend/pcmanager/discovery/impl/impl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2024 Mariotaku <https://github.com/mariotaku>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

#pragma once

#include <stdbool.h>
#include <SDL2/SDL.h>

#include "sockaddr.h"

typedef struct discovery_task_t {
struct discovery_t *discovery;
SDL_mutex *lock;
bool stop;
} discovery_task_t;

int discovery_worker(discovery_task_t *task);

void discovery_worker_stop(discovery_task_t *task);

void discovery_discovered(struct discovery_t *discovery, const sockaddr_t *addr);
Original file line number Diff line number Diff line change
@@ -1,54 +1,31 @@
#include "backend/pcmanager/priv.h"
#include "logging.h"
/*
* Copyright (c) 2024 Mariotaku <https://github.com/mariotaku>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "impl.h"

#include <microdns/microdns.h>
#include "util/bus.h"
#include "backend/pcmanager/worker/worker.h"
#include "sockaddr.h"

struct discovery_task_t {
pcmanager_t *manager;
SDL_mutex *lock;
SDL_Thread *thread;
bool stop;
};

static int discovery_worker(discovery_task_t *task);

static bool discovery_stopped(discovery_task_t *task);
#include "logging.h"

static void discovery_callback(discovery_task_t *task, int status, const struct rr_entry *entries);

static void discovery_finalize(void *arg, int result);
static bool discovery_is_stopped(discovery_task_t *task);

void pcmanager_auto_discovery_start(pcmanager_t *manager) {
pcmanager_lock(manager);
if (manager->discovery_task != NULL) {
pcmanager_unlock(manager);
return;
}
discovery_task_t *task = SDL_calloc(1, sizeof(discovery_task_t));
commons_log_info("Discovery", "Start task %p", task);
task->manager = manager;
task->lock = SDL_CreateMutex();
task->stop = false;
task->thread = SDL_CreateThread((SDL_ThreadFunction) discovery_worker, "discovery", task);
manager->discovery_task = task;
pcmanager_unlock(manager);
}

void pcmanager_auto_discovery_stop(pcmanager_t *manager) {
pcmanager_lock(manager);
discovery_task_t *task = manager->discovery_task;
if (task == NULL) {
pcmanager_unlock(manager);
return;
}
manager->discovery_task = NULL;
executor_submit(manager->executor, executor_noop, discovery_finalize, task);
pcmanager_unlock(manager);
}

static int discovery_worker(discovery_task_t *task) {
int discovery_worker(discovery_task_t *task) {
int r;
char err[128];
static const char *const service_name[] = {"_nvstream._tcp.local"};
Expand All @@ -58,7 +35,7 @@ static int discovery_worker(discovery_task_t *task) {
goto err;
}
commons_log_info("Discovery", "Start mDNS discovery");
if ((r = mdns_listen(ctx, service_name, 1, RR_PTR, 10, (mdns_stop_func) discovery_stopped,
if ((r = mdns_listen(ctx, service_name, 1, RR_PTR, 10, (mdns_stop_func) discovery_is_stopped,
(mdns_listen_callback) discovery_callback, task)) < 0) {
goto err;
}
Expand All @@ -74,14 +51,13 @@ static int discovery_worker(discovery_task_t *task) {
return r;
}

static bool discovery_stopped(discovery_task_t *task) {
void discovery_worker_stop(discovery_task_t *task) {
SDL_LockMutex(task->lock);
bool stop = task->stop;
task->stop = true;
SDL_UnlockMutex(task->lock);
return stop;
}

static void discovery_callback(discovery_task_t *task, int status, const struct rr_entry *entries) {
void discovery_callback(discovery_task_t *task, int status, const struct rr_entry *entries) {
char err[128];

if (status < 0) {
Expand Down Expand Up @@ -114,19 +90,12 @@ static void discovery_callback(discovery_task_t *task, int status, const struct
if (addr->sa_family == AF_UNSPEC) {
return;
}
worker_context_t *ctx = worker_context_new(task->manager, NULL, NULL, NULL);
ctx->arg1 = addr;
pcmanager_worker_queue(task->manager, worker_host_discovered, ctx);
discovery_discovered(task->discovery, addr);
}

static void discovery_finalize(void *arg, int result) {
(void) result;
commons_log_info("Discovery", "Finalize task %p", arg);
discovery_task_t *task = arg;
bool discovery_is_stopped(discovery_task_t *task) {
SDL_LockMutex(task->lock);
task->stop = true;
bool stop = task->stop;
SDL_UnlockMutex(task->lock);
SDL_WaitThread(task->thread, NULL);
SDL_DestroyMutex(task->lock);
free(task);
}
return stop;
}
Loading