Skip to content

Commit

Permalink
more implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
bradh352 committed May 12, 2024
1 parent 4fc3c5e commit 6648d01
Show file tree
Hide file tree
Showing 4 changed files with 210 additions and 22 deletions.
9 changes: 8 additions & 1 deletion src/lib/ares_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,12 @@ typedef struct {
size_t (*wait)(ares_event_thread_t *e, unsigned long timeout_ms);
} ares_event_sys_t;

ares_status_t ares_event_configchg_init(ares_event_thread_t *e);
struct ares_event_configchg;
typedef struct ares_event_configchg ares_event_configchg_t;

ares_status_t ares_event_configchg_init(ares_event_configchg_t **configchg, ares_event_thread_t *e);

void ares_event_configchg_destroy(ares_event_configchg_t *configchg);

struct ares_event_thread {
/*! Whether the event thread should be online or not. Checked on every wake
Expand All @@ -105,6 +110,8 @@ struct ares_event_thread {
* file descriptors being waited on and to wake the event subsystem during
* shutdown */
ares_event_t *ev_signal;
/*! Handle for configuration change monitoring */
ares_event_configchg_t *configchg;
/* Event subsystem callbacks */
const ares_event_sys_t *ev_sys;
/* Event subsystem private data */
Expand Down
211 changes: 196 additions & 15 deletions src/lib/ares_event_configchg.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,17 @@ static void ares_event_configchg_reload(ares_event_thread_t *e)

# include <sys/inotify.h>

typedef struct {
struct ares_event_configchg {
int inotify_fd;
} ares_event_configchg_t;
};

void ares_event_configchg_destroy(ares_event_configchg_t *configchg)
{
(void)configchg;

/* Cleanup happens automatically */
}


static void ares_event_configchg_free(void *data)
{
Expand Down Expand Up @@ -141,18 +149,157 @@ ares_status_t ares_event_configchg_init(ares_event_thread_t *e)

#elif defined(_WIN32)

# include <winsock2.h>
# include <iphlpapi.h>
# include <stdio.h>
# include <windows.h>

struct ares_event_configchg {
ares__thread_t *thread;
HANDLE terminate_event;
HANDLE ifchg_hnd;
OVERLAPPED ifchg_ol;
HANDLE route_hnd;
OVERLAPPED route_ol;
};

void ares_event_configchg_destroy(ares_event_configchg_t *configchg)
{
if (configchg->terminate_event) {
SetEvent(configchg->terminate_event);
}

if (configchg->thread) {
void *rv = NULL;
ares__thread_join(thread, &rv);
configchg->thread = NULL;
}


if (configchg->terminate_event != NULL) {
CloseHandle(configchg->terminate_event);
configchg->terminate_event = NULL;
}

if (configchg->ifchg_hnd != NULL) {
CancelIPChangeNotify(configchg->ifchg_hnd);
configchg->ifchg_hnd = NULL;
}

if (configchg->ifchg_ol.hEvent != NULL) {
DeleteEvent(configchg->ifchg_ol.hEvent);
configchg->ifchg_ol.hEvent = NULL;
}

if (configchg->route_hnd != NULL) {
CancelIPChangeNotify(configchg->route_hnd);
configchg->route_hnd = NULL;
}

if (configchg->route_ol.hEvent != NULL) {
DeleteEvent(configchg->route_ol.hEvent);
configchg->route_ol.hEvent = NULL;
}

ares_free(configchg);
}

static void *ares_event_configchg_thread(void *arg)
{
ares_event_configchg_t *configchg = arg;
HANDLE handles[3] = { configchg->terminate_event, configchg->ifchg_ol.hEvent, configchg->route_ol.hEvent };

while (1) {
ares_bool_t triggered = ARES_FALSE;
DWORD ret = WaitForMultipleObjects(3, handles, FALSE, INFINITE);
if (ret < WAIT_OBJECT_0) {
continue;
}

/* Query each handle individually */
if (WaitForSingleObject(configchg->terminate_event, 0) == WAIT_OBJECT_0) {
break;
}

if (WaitForSingleObject(configchg->ifchg_ol.hEvent, 0) == WAIT_OBJECT_O) {
triggered = ARES_TRUE;
ResetEvent(configchg->ifchg_ol.hEvent);
}

if (WaitForSingleObject(configchg->route_ol.hEvent, 0) == WAIT_OBJECT_O) {
triggered = ARES_TRUE;
ResetEvent(configchg->route_ol.hEvent);
}

if (triggered) {
ares_event_configchg_reload(configchg->e);
}
}

return NULL;
}

ares_status_t ares_event_configchg_init(ares_event_configchg_t **configchg, ares_event_thread_t *e)
{
ares_status_t status = ARES_SUCCESS;

*configchg = ares_malloc_zero(sizeof(**configchg));
if (*configchg == NULL) {
return ARES_ENOMEM;
}

(*configchg)->e = e;

(*configchg)->terminate_event = CreateEvent();
if ((*configchg)->terminate_event == NULL) {
status = ARES_ESERVFAIL;
goto done;
}

if (NotifyRouteChange(&(*configchg)->route_hnd, &(*configchg)->route_ol) != NO_ERROR) {
status = ARES_ESERVFAIL;
goto done;
}

if (NotifyIpInterfaceChange(&(*configchg)->ifchg_hnd, &(*configchg)->ifchg_ol) != NO_ERROR) {
status = ARES_ESERVFAIL;
goto done;
}

status = ares__thread_create(&(*configchg)->thread, ares_event_configchg_thread, *configchg);
if (status != ARES_SUCCESS) {
goto done;
}

done:
if (status != ARES_SUCCESS) {
ares_event_configchg_destroy(*configchg);
*configchg = NULL;
}

return status;
}

#elif defined(__APPLE__)

# include <sys/types.h>
# include <unistd.h>
# include <notify.h>
# include <dlfcn.h>


typedef struct {
struct ares_event_configchg {
int fd;
int token;
} ares_event_configchg_t;
};

void ares_event_configchg_destroy(ares_event_configchg_t *configchg)
{
(void)configchg;

/* Cleanup happens automatically */
}


static void ares_event_configchg_free(void *data)
{
Expand Down Expand Up @@ -201,39 +348,73 @@ static void ares_event_configchg_cb(ares_event_thread_t *e, ares_socket_t fd,
}
}

ares_status_t ares_event_configchg_init(ares_event_thread_t *e)
ares_status_t ares_event_configchg_init(ares_event_configchg_t **configchg, ares_event_thread_t *e)
{
ares_status_t status = ARES_SUCCESS;
ares_event_configchg_t *configchg;
ares_status_t status = ARES_SUCCESS;
void *handle = NULL;
const char *(*pdns_configuration_notify_key)(void) = NULL;
const char *notify_key = NULL;

configchg = ares_malloc_zero(sizeof(*configchg));
if (configchg == NULL) {
*configchg = ares_malloc_zero(sizeof(**configchg));
if (*configchg == NULL) {
return ARES_ENOMEM;
}

if (notify_register_file_descriptor("com.apple.system.SystemConfiguration.dns_configuration",
&configchg->fd, 0, &configchg->token) != NOTIFY_STATUS_OK) {
/* Load symbol as it isn't normally public */
handle = dlopen("/usr/lib/libSystem.dylib", RTLD_LAZY | RTLD_NOLOAD);
if (handle == NULL) {
status = ARES_ESERVFAIL;
goto done;
}

pdns_configuration_notify_key =
dlsym(handle, "dns_configuration_notify_key");

if (pdns_configuration_notify_key == NULL) {
status = ARES_ESERVFAIL;
goto done;
}

notify_key = pdns_configuration_notify_key();
if (notify_key == NULL) {
status = ARES_ESERVFAIL;
goto done;
}

if (notify_register_file_descriptor(notify_key,
&(*configchg)->fd, 0, &(*configchg)->token) != NOTIFY_STATUS_OK) {
status = ARES_ESERVFAIL;
goto done;
}

status = ares_event_update(NULL, e, ARES_EVENT_FLAG_READ,
ares_event_configchg_cb, configchg->fd, configchg,
ares_event_configchg_free, NULL);
ares_event_configchg_cb, (*configchg)->fd,
*configchg, ares_event_configchg_free, NULL);

done:
if (status != ARES_SUCCESS) {
ares_event_configchg_free(configchg);
ares_event_configchg_free(*configchg);
*configchg = NULL;
}

if (handle) {
dlclose(handle);
}

return status;
}

#else

ares_status_t ares_event_configchg_init(ares_event_thread_t *e)
ares_status_t ares_event_configchg_init(ares_event_configchg_t **configchg, ares_event_thread_t *e)
{
/* Not implemented yet, need to spawn thread */
return ARES_SUCCESS;
}

void ares_event_configchg_destroy(ares_event_configchg_t *configchg)
{
/* Todo */
}

#endif
6 changes: 5 additions & 1 deletion src/lib/ares_event_thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,10 @@ static void ares_event_thread_destroy_int(ares_event_thread_t *e)
{
ares__llist_node_t *node;

/* Disable configuration change monitoring */
ares_event_configchg_destroy(e->configchg);
e->configchg = NULL;

/* Wake thread and tell it to shutdown if it exists */
ares__thread_mutex_lock(e->mutex);
if (e->isup) {
Expand Down Expand Up @@ -457,7 +461,7 @@ ares_status_t ares_event_thread_init(ares_channel_t *channel)
}

/* Initialize monitor for configuration changes */
status = ares_event_configchg_init(e);
status = ares_event_configchg_init(&e->configchg, e);
if (status != ARES_SUCCESS) {
ares_event_thread_destroy_int(e);
channel->sock_state_cb = NULL;
Expand Down
6 changes: 1 addition & 5 deletions src/lib/ares_sysconfig_mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@

typedef struct {
void *handle;
const char *(*dns_configuration_notify_key)(void);
dns_config_t *(*dns_configuration_copy)(void);
void (*dns_configuration_free)(dns_config_t *config);
} dnsinfo_t;
Expand Down Expand Up @@ -101,15 +100,12 @@ static ares_status_t dnsinfo_init(dnsinfo_t **dnsinfo_out)
goto done;
}

dnsinfo->dns_configuration_notify_key =
dlsym(dnsinfo->handle, "dns_configuration_notify_key");
dnsinfo->dns_configuration_copy =
dlsym(dnsinfo->handle, "dns_configuration_copy");
dnsinfo->dns_configuration_free =
dlsym(dnsinfo->handle, "dns_configuration_free");

if (dnsinfo->dns_configuration_notify_key == NULL ||
dnsinfo->dns_configuration_copy == NULL ||
if (dnsinfo->dns_configuration_copy == NULL ||
dnsinfo->dns_configuration_free == NULL) {
status = ARES_ESERVFAIL;
goto done;
Expand Down

0 comments on commit 6648d01

Please sign in to comment.