Merge branch 'async_dns_api'

This commit is contained in:
Jan Vidar Krey 2012-11-01 10:42:19 +01:00
commit 2d2ccc0039
5 changed files with 158 additions and 55 deletions

View File

@ -19,9 +19,6 @@
#include "uhub.h" #include "uhub.h"
// #define DEBUG_LOOKUP_TIME 1
#define MAX_CONCURRENT_JOBS 25
static struct net_dns_job* find_and_remove_job(struct net_dns_job* job); static struct net_dns_job* find_and_remove_job(struct net_dns_job* job);
static struct net_dns_result* find_and_remove_result(struct net_dns_job* job); static struct net_dns_result* find_and_remove_result(struct net_dns_job* job);
@ -56,6 +53,22 @@ static void free_job(struct net_dns_job* job)
} }
} }
static void shutdown_free_jobs(void* ptr)
{
struct net_dns_job* job = (struct net_dns_job*) ptr;
uhub_thread_cancel(job->thread_handle);
uhub_thread_join(job->thread_handle);
free_job(job);
}
static void shutdown_free_results(void* ptr)
{
struct net_dns_result* result = (struct net_dns_result*) ptr;
uhub_thread_join(result->job->thread_handle);
net_dns_result_free(result);
}
// NOTE: Any job manipulating the members of this // NOTE: Any job manipulating the members of this
// struct must lock the mutex! // struct must lock the mutex!
struct net_dns_subsystem struct net_dns_subsystem
@ -79,19 +92,21 @@ void net_dns_initialize()
void net_dns_destroy() void net_dns_destroy()
{ {
struct net_dns_job* job; struct net_dns_job* job;
struct net_dns_result* result;
uhub_mutex_lock(&g_dns->mutex); uhub_mutex_lock(&g_dns->mutex);
LOG_TRACE("net_dns_destroy(): jobs=%d", (int) list_size(g_dns->jobs)); LOG_TRACE("net_dns_destroy(): jobs=%d", (int) list_size(g_dns->jobs));
job = (struct net_dns_job*) list_get_first(g_dns->jobs); list_clear(g_dns->jobs, &shutdown_free_jobs);
LOG_TRACE("net_dns_destroy(): results=%d", (int) list_size(g_dns->results));
list_clear(g_dns->results, &shutdown_free_results);
uhub_mutex_unlock(&g_dns->mutex); uhub_mutex_unlock(&g_dns->mutex);
while (job) list_destroy(g_dns->jobs);
{ list_destroy(g_dns->results);
net_dns_job_cancel(job); uhub_mutex_destroy(&g_dns->mutex);
hub_free(g_dns);
uhub_mutex_lock(&g_dns->mutex); g_dns = NULL;
job = (struct net_dns_job*) list_get_first(g_dns->jobs);
uhub_mutex_unlock(&g_dns->mutex);
}
} }
static void dummy_free(void* ptr) static void dummy_free(void* ptr)
@ -149,9 +164,9 @@ static void* job_thread_resolve_name(void* ptr)
hints.ai_protocol = IPPROTO_TCP; hints.ai_protocol = IPPROTO_TCP;
ret = getaddrinfo(job->host, NULL, &hints, &result); ret = getaddrinfo(job->host, NULL, &hints, &result);
if (ret != 0) if (ret != 0 && ret != EAI_NONAME)
{ {
LOG_WARN("getaddrinfo() failed: %s", gai_strerror(ret)); LOG_TRACE("getaddrinfo() failed: %s", gai_strerror(ret));
return NULL; return NULL;
} }
@ -159,32 +174,39 @@ static void* job_thread_resolve_name(void* ptr)
dns_results->addr_list = list_create(); dns_results->addr_list = list_create();
dns_results->job = job; dns_results->job = job;
for (it = result; it; it = it->ai_next) if (ret != EAI_NONAME)
{ {
struct ip_addr_encap* ipaddr = hub_malloc_zero(sizeof(struct ip_addr_encap)); for (it = result; it; it = it->ai_next)
ipaddr->af = it->ai_family; {
struct ip_addr_encap* ipaddr = hub_malloc_zero(sizeof(struct ip_addr_encap));
ipaddr->af = it->ai_family;
if (it->ai_family == AF_INET) if (it->ai_family == AF_INET)
{ {
struct sockaddr_in* addr4 = (struct sockaddr_in*) it->ai_addr; struct sockaddr_in* addr4 = (struct sockaddr_in*) it->ai_addr;
memcpy(&ipaddr->internal_ip_data.in, &addr4->sin_addr, sizeof(struct in_addr)); memcpy(&ipaddr->internal_ip_data.in, &addr4->sin_addr, sizeof(struct in_addr));
} }
else if (it->ai_family == AF_INET6) else if (it->ai_family == AF_INET6)
{ {
struct sockaddr_in6* addr6 = (struct sockaddr_in6*) it->ai_addr; struct sockaddr_in6* addr6 = (struct sockaddr_in6*) it->ai_addr;
memcpy(&ipaddr->internal_ip_data.in6, &addr6->sin6_addr, sizeof(struct in6_addr)); memcpy(&ipaddr->internal_ip_data.in6, &addr6->sin6_addr, sizeof(struct in6_addr));
} }
else else
{ {
LOG_WARN("getaddrinfo() returned result with unknown address family: %d", it->ai_family); LOG_TRACE("getaddrinfo() returned result with unknown address family: %d", it->ai_family);
hub_free(ipaddr); hub_free(ipaddr);
continue; continue;
} }
LOG_WARN("getaddrinfo() - Address (%d): %s", ret++, ip_convert_to_string(ipaddr)); LOG_DUMP("getaddrinfo() - Address (%d) %s for \"%s\"", ret++, ip_convert_to_string(ipaddr), job->host);
list_append(dns_results->addr_list, ipaddr); list_append(dns_results->addr_list, ipaddr);
}
freeaddrinfo(result);
}
else
{
/* hm */
} }
freeaddrinfo(result);
#ifdef DEBUG_LOOKUP_TIME #ifdef DEBUG_LOOKUP_TIME
gettimeofday(&job->time_finish, NULL); gettimeofday(&job->time_finish, NULL);

View File

@ -508,6 +508,7 @@ void ADC_client_send_info(struct ADC_client* client)
ADC_TRACE; ADC_TRACE;
client->info = adc_msg_construct_source(ADC_CMD_BINF, client->sid, 96); client->info = adc_msg_construct_source(ADC_CMD_BINF, client->sid, 96);
adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_NICK, client->nick); adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_NICK, client->nick);
if (client->desc) if (client->desc)
@ -528,6 +529,7 @@ void ADC_client_send_info(struct ADC_client* client)
adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_UPLOAD_SPEED, 10 * 1024 * 1024); adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_UPLOAD_SPEED, 10 * 1024 * 1024);
adc_cid_pid(client); adc_cid_pid(client);
ADC_client_send(client, client->info); ADC_client_send(client, client->info);
} }
@ -565,6 +567,7 @@ void ADC_client_destroy(struct ADC_client* client)
hub_free(client->nick); hub_free(client->nick);
hub_free(client->desc); hub_free(client->desc);
hub_free(client->address.hostname); hub_free(client->address.hostname);
hub_free(client);
} }
int ADC_client_connect(struct ADC_client* client, const char* address) int ADC_client_connect(struct ADC_client* client, const char* address)
@ -577,19 +580,20 @@ int ADC_client_connect(struct ADC_client* client, const char* address)
return 0; return 0;
return 1; return 1;
} }
else if (client->state == ps_dns) return ADC_client_connect_internal(client);
}
int ADC_client_connect_internal(struct ADC_client* client)
{
int ret;
if (client->state == ps_dns)
{ {
// Done name resolving! // Done name resolving!
client->callback(client, ADC_CLIENT_CONNECTING, 0); client->callback(client, ADC_CLIENT_CONNECTING, 0);
ADC_client_set_state(client, ps_conn); ADC_client_set_state(client, ps_conn);
} }
return ADC_client_connect_internal(client); ret = net_connect(net_con_get_sd(client->con), (struct sockaddr*) &client->addr, sizeof(struct sockaddr_in));
}
int ADC_client_connect_internal(struct ADC_client* client)
{
int ret = net_connect(net_con_get_sd(client->con), (struct sockaddr*) &client->addr, sizeof(struct sockaddr_in));
if (ret == 0 || (ret == -1 && net_error() == EISCONN)) if (ret == 0 || (ret == -1 && net_error() == EISCONN))
{ {
ADC_client_on_connected(client); ADC_client_on_connected(client);
@ -622,10 +626,12 @@ static void ADC_client_on_connected(struct ADC_client* client)
else else
#endif #endif
{ {
struct adc_message* handshake = adc_msg_create(ADC_HANDSHAKE);
net_con_update(client->con, NET_EVENT_READ); net_con_update(client->con, NET_EVENT_READ);
client->callback(client, ADC_CLIENT_CONNECTED, 0); client->callback(client, ADC_CLIENT_CONNECTED, 0);
ADC_client_send(client, adc_msg_create(ADC_HANDSHAKE)); ADC_client_send(client, handshake);
ADC_client_set_state(client, ps_protocol); ADC_client_set_state(client, ps_protocol);
adc_msg_free(handshake);
} }
} }
@ -633,11 +639,13 @@ static void ADC_client_on_connected(struct ADC_client* client)
static void ADC_client_on_connected_ssl(struct ADC_client* client) static void ADC_client_on_connected_ssl(struct ADC_client* client)
{ {
ADC_TRACE; ADC_TRACE;
struct adc_message* handshake = adc_msg_create(ADC_HANDSHAKE);
client->callback(client, ADC_CLIENT_SSL_OK, 0); client->callback(client, ADC_CLIENT_SSL_OK, 0);
client->callback(client, ADC_CLIENT_CONNECTED, 0); client->callback(client, ADC_CLIENT_CONNECTED, 0);
net_con_update(client->con, NET_EVENT_READ); net_con_update(client->con, NET_EVENT_READ);
ADC_client_send(client, adc_msg_create(ADC_HANDSHAKE)); ADC_client_send(client, handshake);
ADC_client_set_state(client, ps_protocol); ADC_client_set_state(client, ps_protocol);
adc_msg_free(handshake);
} }
#endif #endif

View File

@ -35,7 +35,6 @@ static struct ADC_user* user_get(sid_t sid)
return user; return user;
} }
static void user_remove(const struct ADC_client_quit_reason* quit) static void user_remove(const struct ADC_client_quit_reason* quit)
{ {
struct ADC_user* user = user_get(quit->sid); struct ADC_user* user = user_get(quit->sid);
@ -162,6 +161,68 @@ static int handle(struct ADC_client* client, enum ADC_client_callback_type type,
static int running = 1; static int running = 1;
#if !defined(WIN32)
void adm_handle_signal(int sig)
{
switch (sig)
{
case SIGINT:
LOG_INFO("Interrupted. Shutting down...");
running = 0;
break;
case SIGTERM:
LOG_INFO("Terminated. Shutting down...");
running = 0;
break;
case SIGPIPE:
break;
case SIGHUP:
break;
default:
LOG_TRACE("hub_handle_signal(): caught unknown signal: %d", signal);
running = 0;
break;
}
}
static int signals[] =
{
SIGINT, /* Interrupt the application */
SIGTERM, /* Terminate the application */
SIGPIPE, /* prevent sigpipe from kills the application */
SIGHUP, /* reload configuration */
0
};
void adm_setup_signal_handlers()
{
sigset_t sig_set;
struct sigaction act;
int i;
sigemptyset(&sig_set);
act.sa_mask = sig_set;
act.sa_flags = SA_ONSTACK | SA_RESTART;
act.sa_handler = adm_handle_signal;
for (i = 0; signals[i]; i++)
{
if (sigaction(signals[i], &act, 0) != 0)
{
LOG_ERROR("Error setting signal handler %d", signals[i]);
}
}
}
void adm_shutdown_signal_handlers()
{
}
#endif /* !WIN32 */
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
if (argc < 2) if (argc < 2)
@ -170,6 +231,9 @@ int main(int argc, char** argv)
return 1; return 1;
} }
hub_set_log_verbosity(5);
adm_setup_signal_handlers();
struct ADC_client* client; struct ADC_client* client;
net_initialize(); net_initialize();
@ -183,6 +247,7 @@ int main(int argc, char** argv)
ADC_client_destroy(client); ADC_client_destroy(client);
net_destroy(); net_destroy();
adm_shutdown_signal_handlers();
return 0; return 0;
} }

View File

@ -20,6 +20,12 @@
#include "uhub.h" #include "uhub.h"
#ifdef POSIX_THREAD_SUPPORT #ifdef POSIX_THREAD_SUPPORT
struct pthread_data
{
pthread_t handle;
};
void uhub_mutex_init(uhub_mutex_t* mutex) void uhub_mutex_init(uhub_mutex_t* mutex)
{ {
pthread_mutex_init(mutex, NULL); pthread_mutex_init(mutex, NULL);
@ -48,23 +54,25 @@ int uhub_mutex_trylock(uhub_mutex_t* mutex)
uhub_thread_t* uhub_thread_create(uhub_thread_start start, void* arg) uhub_thread_t* uhub_thread_create(uhub_thread_start start, void* arg)
{ {
uhub_thread_t* thread = (uhub_thread_t*) hub_malloc_zero(sizeof(uhub_thread_t)); struct pthread_data* thread = (struct pthread_data*) hub_malloc_zero(sizeof(struct pthread_data));
int ret = pthread_create(thread, NULL, start, arg); int ret = pthread_create(&thread->handle, NULL, start, arg);
if (ret == 0) if (ret != 0)
return thread; {
hub_free(thread); hub_free(thread);
return NULL; thread = NULL;
}
return thread;
} }
void uhub_thread_cancel(uhub_thread_t* thread) void uhub_thread_cancel(uhub_thread_t* thread)
{ {
pthread_cancel(thread); pthread_cancel(thread->handle);
} }
void* uhub_thread_join(uhub_thread_t* thread) void* uhub_thread_join(uhub_thread_t* thread)
{ {
void* ret = NULL; void* ret = NULL;
pthread_join(thread, &ret); pthread_join(thread->handle, &ret);
hub_free(thread); hub_free(thread);
return ret; return ret;
} }

View File

@ -23,7 +23,7 @@
typedef void*(*uhub_thread_start)(void*) ; typedef void*(*uhub_thread_start)(void*) ;
#ifdef POSIX_THREAD_SUPPORT #ifdef POSIX_THREAD_SUPPORT
typedef pthread_t uhub_thread_t; typedef struct pthread_data uhub_thread_t;
typedef pthread_mutex_t uhub_mutex_t; typedef pthread_mutex_t uhub_mutex_t;
#endif #endif