-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add API to resolve host name in background
- Loading branch information
Showing
3 changed files
with
132 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |