Skip to content

Commit

Permalink
uuid based host discovery
Browse files Browse the repository at this point in the history
  • Loading branch information
mariotaku committed Oct 3, 2024
1 parent 4f51fcd commit de96621
Show file tree
Hide file tree
Showing 24 changed files with 511 additions and 101 deletions.
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
4 changes: 3 additions & 1 deletion src/app/backend/pcmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,6 @@ 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_ip(worker_context_t *context, const char *ip, uint16_t port, bool force);

int pcmanager_update_by_addr(worker_context_t *context, sockaddr_t *addr, 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

0 comments on commit de96621

Please sign in to comment.