Skip to content

Commit

Permalink
Add API to resolve host name in background
Browse files Browse the repository at this point in the history
  • Loading branch information
norihiro committed Oct 30, 2024
1 parent 309cae0 commit 0e26d25
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 0 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ set(PLUGIN_SOURCES
src/vban-output.c
src/vban-output-thread.c
src/vban-filter.c
src/resolve-thread.c
)

add_library(${PROJECT_NAME} MODULE ${PLUGIN_SOURCES})
Expand Down
111 changes: 111 additions & 0 deletions src/resolve-thread.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// SPDX-License-Identifier: GPL-2.0-or-later

#include <obs-module.h>
#include <util/threading.h>
#ifndef _WIN32
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <ctype.h>
#else
#include <ws2tcpip.h>
#endif
#include "plugin-macros.generated.h"
#include "resolve-thread.h"

struct resolve_thread_s
{
char *name;
resolve_thread_resolved_cb resolved_cb;
resolve_thread_failed_cb failed_cb;
void *cb_data;
};

static void *resolve_thread_main(void *data);

static bool is_valid_hostname(const char *host)
{
if (!host)
return false;

bool mid = false;
bool prev_was_alnum = false;

while (*host) {
char c = *host++;
if (c == '.') {
if (!prev_was_alnum)
return false;
mid = false;
prev_was_alnum = false;
}
else if (c == '-') {
if (!mid)
return false;
prev_was_alnum = false;
}
else if (isalnum((unsigned char)c)) {
mid = true;
prev_was_alnum = true;
}
}

return prev_was_alnum;
}

bool resolve_thread_start(const char *name, void *cb_data, resolve_thread_resolved_cb resolved_cb,
resolve_thread_failed_cb failed_cb)
{
if (!is_valid_hostname(name)) {
if (failed_cb)
failed_cb(cb_data);
return false;
}

struct resolve_thread_s *ctx = bzalloc(sizeof(struct resolve_thread_s));
ctx->name = bstrdup(name);
ctx->resolved_cb = resolved_cb;
ctx->failed_cb = failed_cb;
ctx->cb_data = cb_data;

pthread_t thread;
if (pthread_create(&thread, NULL, resolve_thread_main, ctx)) {
blog(LOG_ERROR, "Failed to create resolving thread for '%s'", ctx->name);
return false;
}

pthread_detach(thread);

return true;
}

static void *resolve_thread_main(void *data)
{
struct resolve_thread_s *ctx = data;

struct addrinfo hints = {
.ai_family = AF_INET,
.ai_socktype = SOCK_DGRAM,
.ai_protocol = IPPROTO_UDP,
.ai_flags = 0,
};

struct addrinfo *res;

if (getaddrinfo(ctx->name, NULL, &hints, &res) == 0) {
struct in_addr addr = {0};
addr.s_addr = ((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr;
freeaddrinfo(res);

if (ctx->resolved_cb)
ctx->resolved_cb(ctx->cb_data, &addr);
}
else {
if (ctx->failed_cb)
ctx->failed_cb(ctx->cb_data);
}

bfree(ctx->name);
bfree(ctx);
return NULL;
}
20 changes: 20 additions & 0 deletions src/resolve-thread.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: GPL-2.0-or-later

#ifdef __cplusplus
extern "C" {
#endif

/* The API resolves host name in a newly created thread.
* If the resolution has succeeded, `resolved` will be called.
* Otherwise, `failed` will be called.
*/

typedef void (*resolve_thread_resolved_cb)(void *data, const struct in_addr *addr);
typedef void (*resolve_thread_failed_cb)(void *data);

bool resolve_thread_start(const char *name, void *cb_data, resolve_thread_resolved_cb resolved_cb,
resolve_thread_failed_cb failed_cb);

#ifdef __cplusplus
} // extern "C"
#endif

0 comments on commit 0e26d25

Please sign in to comment.