Merge branch 'autotest'

This commit is contained in:
Jan Vidar Krey
2012-11-01 10:40:51 +01:00
15 changed files with 2175 additions and 37 deletions

View File

@@ -146,6 +146,9 @@ int net_backend_process()
return 0;
}
// Process pending DNS results
net_dns_process();
g_backend->handler.backend_process(g_backend->data, res);
net_cleanup_process(g_backend->cleaner);

364
src/network/dnsresolver.c Normal file
View File

@@ -0,0 +1,364 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#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_result* find_and_remove_result(struct net_dns_job* job);
struct net_dns_job
{
net_dns_job_cb callback;
void* ptr;
char* host;
int af;
#ifdef DEBUG_LOOKUP_TIME
struct timeval time_start;
struct timeval time_finish;
#endif
uhub_thread_t* thread_handle;
};
struct net_dns_result
{
struct linked_list* addr_list;
struct net_dns_job* job;
};
static void free_job(struct net_dns_job* job)
{
if (job)
{
hub_free(job->host);
hub_free(job);
}
}
// NOTE: Any job manipulating the members of this
// struct must lock the mutex!
struct net_dns_subsystem
{
struct linked_list* jobs; // currently running jobs
struct linked_list* results; // queue of results that are awaiting being delivered to callback.
uhub_mutex_t mutex;
};
static struct net_dns_subsystem* g_dns = NULL;
void net_dns_initialize()
{
LOG_TRACE("net_dns_initialize()");
g_dns = (struct net_dns_subsystem*) hub_malloc_zero(sizeof(struct net_dns_subsystem));
g_dns->jobs = list_create();
g_dns->results = list_create();
uhub_mutex_init(&g_dns->mutex);
}
void net_dns_destroy()
{
struct net_dns_job* job;
uhub_mutex_lock(&g_dns->mutex);
LOG_TRACE("net_dns_destroy(): jobs=%d", (int) list_size(g_dns->jobs));
job = (struct net_dns_job*) list_get_first(g_dns->jobs);
uhub_mutex_unlock(&g_dns->mutex);
while (job)
{
net_dns_job_cancel(job);
uhub_mutex_lock(&g_dns->mutex);
job = (struct net_dns_job*) list_get_first(g_dns->jobs);
uhub_mutex_unlock(&g_dns->mutex);
}
}
static void dummy_free(void* ptr)
{
}
void net_dns_process()
{
struct net_dns_result* result;
uhub_mutex_lock(&g_dns->mutex);
LOG_DUMP("net_dns_process(): jobs=%d, results=%d", (int) list_size(g_dns->jobs), (int) list_size(g_dns->results));
for (result = (struct net_dns_result*) list_get_first(g_dns->results); result; result = (struct net_dns_result*) list_get_next(g_dns->results))
{
struct net_dns_job* job = result->job;
#ifdef DEBUG_LOOKUP_TIME
struct timeval time_result;
timersub(&result->job->time_finish, &result->job->time_start, &time_result);
LOG_TRACE("DNS lookup took %d ms", (time_result.tv_sec * 1000) + (time_result.tv_usec / 1000));
#endif
// wait for the work thread to finish
uhub_thread_join(job->thread_handle);
// callback - should we delete the data immediately?
if (job->callback(job, result))
{
net_dns_result_free(result);
}
else
{
/* Caller wants to keep the result data, and
* thus needs to call net_dns_result_free() to release it later.
* We only clean up the job data here and keep the results intact.
*/
result->job = NULL;
free_job(job);
}
}
list_clear(g_dns->results, &dummy_free);
uhub_mutex_unlock(&g_dns->mutex);
}
static void* job_thread_resolve_name(void* ptr)
{
struct net_dns_job* job = (struct net_dns_job*) ptr;
struct addrinfo hints, *result, *it;
struct net_dns_result* dns_results;
int ret;
memset(&hints, 0, sizeof(hints));
hints.ai_family = job->af;
hints.ai_protocol = IPPROTO_TCP;
ret = getaddrinfo(job->host, NULL, &hints, &result);
if (ret != 0)
{
LOG_WARN("getaddrinfo() failed: %s", gai_strerror(ret));
return NULL;
}
dns_results = (struct net_dns_result*) hub_malloc(sizeof(struct net_dns_result));
dns_results->addr_list = list_create();
dns_results->job = job;
for (it = result; it; it = it->ai_next)
{
struct ip_addr_encap* ipaddr = hub_malloc_zero(sizeof(struct ip_addr_encap));
ipaddr->af = it->ai_family;
if (it->ai_family == AF_INET)
{
struct sockaddr_in* addr4 = (struct sockaddr_in*) it->ai_addr;
memcpy(&ipaddr->internal_ip_data.in, &addr4->sin_addr, sizeof(struct in_addr));
}
else if (it->ai_family == AF_INET6)
{
struct sockaddr_in6* addr6 = (struct sockaddr_in6*) it->ai_addr;
memcpy(&ipaddr->internal_ip_data.in6, &addr6->sin6_addr, sizeof(struct in6_addr));
}
else
{
LOG_WARN("getaddrinfo() returned result with unknown address family: %d", it->ai_family);
hub_free(ipaddr);
continue;
}
LOG_WARN("getaddrinfo() - Address (%d): %s", ret++, ip_convert_to_string(ipaddr));
list_append(dns_results->addr_list, ipaddr);
}
freeaddrinfo(result);
#ifdef DEBUG_LOOKUP_TIME
gettimeofday(&job->time_finish, NULL);
#endif
uhub_mutex_lock(&g_dns->mutex);
list_remove(g_dns->jobs, job);
list_append(g_dns->results, dns_results);
uhub_mutex_unlock(&g_dns->mutex);
return dns_results;
}
extern struct net_dns_job* net_dns_gethostbyname(const char* host, int af, net_dns_job_cb callback, void* ptr)
{
struct net_dns_job* job = (struct net_dns_job*) hub_malloc_zero(sizeof(struct net_dns_job));
job->host = strdup(host);
job->af = af;
job->callback = callback;
job->ptr = ptr;
#ifdef DEBUG_LOOKUP_TIME
gettimeofday(&job->time_start, NULL);
#endif
// FIXME - scheduling - what about a max number of threads?
uhub_mutex_lock(&g_dns->mutex);
job->thread_handle = uhub_thread_create(job_thread_resolve_name, job);
if (!job->thread_handle)
{
LOG_WARN("Unable to create thread");
free_job(job);
job = NULL;
}
else
{
list_append(g_dns->jobs, job);
}
uhub_mutex_unlock(&g_dns->mutex);
return job;
}
extern struct net_dns_job* net_dns_gethostbyaddr(struct ip_addr_encap* ipaddr, net_dns_job_cb callback, void* ptr)
{
struct net_dns_job* job = (struct net_dns_job*) hub_malloc_zero(sizeof(struct net_dns_job));
// job->host = strdup(addr);
job->af = ipaddr->af;
job->callback = callback;
job->ptr = ptr;
// if (pthread_create(&job->thread_handle, NULL, start_job, job))
// {
// free_job(job);
// return NULL;
// }
return job;
}
// NOTE: mutex must be locked first!
static struct net_dns_job* find_and_remove_job(struct net_dns_job* job)
{
struct net_dns_job* it;
for (it = (struct net_dns_job*) list_get_first(g_dns->jobs); it; it = (struct net_dns_job*) list_get_next(g_dns->jobs))
{
if (it == job)
{
list_remove(g_dns->jobs, it);
return job;
}
}
return NULL;
}
// NOTE: mutex must be locked first!
static struct net_dns_result* find_and_remove_result(struct net_dns_job* job)
{
struct net_dns_result* it;
for (it = (struct net_dns_result*) list_get_first(g_dns->results); it; it = (struct net_dns_result*) list_get_next(g_dns->results))
{
if (it->job == job)
{
list_remove(g_dns->results, it);
return it;
}
}
return NULL;
}
extern int net_dns_job_cancel(struct net_dns_job* job)
{
int retval = 0;
struct net_dns_result* res;
LOG_TRACE("net_dns_job_cancel(): job=%p, name=%s", job, job->host);
/*
* This function looks up the job in the jobs queue (which contains only active jobs)
* If that is found then the thread is cancelled, and the object is deleted.
* If the job was not found, that is either because it was an invalid job, or because
* it was already finished. At which point it was not deleted.
* If the job is already finished, but the result has not been delivered, then this
* deletes the result and the job.
*/
uhub_mutex_lock(&g_dns->mutex);
if (find_and_remove_job(job))
{
// job still active - cancel it, then close it.
uhub_thread_cancel(job->thread_handle);
uhub_thread_join(job->thread_handle);
free_job(job);
retval = 1;
}
else if ((res = find_and_remove_result(job)))
{
// job already finished - close it.
uhub_thread_join(job->thread_handle);
net_dns_result_free(res);
}
uhub_mutex_unlock(&g_dns->mutex);
return retval;
}
extern struct net_dns_result* net_dns_job_sync_wait(struct net_dns_job* job)
{
struct net_dns_result* res = NULL;
// Wait for job to finish (if not already)
// This should make sure the job is removed from jobs and a result is
// present in results.
uhub_thread_join(job->thread_handle);
// Remove the result in order to prevent the callback from being called.
uhub_mutex_lock(&g_dns->mutex);
res = find_and_remove_result(job);
uhub_assert(res != NULL);
res->job = NULL;
free_job(job);
uhub_mutex_unlock(&g_dns->mutex);
return res;
}
void* net_dns_job_get_ptr(const struct net_dns_job* job)
{
return job->ptr;
}
extern size_t net_dns_result_size(const struct net_dns_result* res)
{
return list_size(res->addr_list);
}
extern struct ip_addr_encap* net_dns_result_first(const struct net_dns_result* res)
{
struct ip_addr_encap* ipaddr = list_get_first(res->addr_list);
LOG_TRACE("net_dns_result_first() - Address: %s", ip_convert_to_string(ipaddr));
return ipaddr;
}
extern struct ip_addr_encap* net_dns_result_next(const struct net_dns_result* res)
{
struct ip_addr_encap* ipaddr = list_get_next(res->addr_list);
LOG_TRACE("net_dns_result_next() - Address: %s", ip_convert_to_string(ipaddr));
return ipaddr;
}
extern void net_dns_result_free(struct net_dns_result* res)
{
list_clear(res->addr_list, &hub_free);
list_destroy(res->addr_list);
free_job(res->job);
hub_free(res);
}

119
src/network/dnsresolver.h Normal file
View File

@@ -0,0 +1,119 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef HAVE_UHUB_NETWORK_DNS_RESOLVER_H
#define HAVE_UHUB_NETWORK_DNS_RESOLVER_H
struct net_dns_job;
struct net_dns_result;
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
/// Initialize the DNS subsystem
void net_dns_initialize();
/// Shutdown and destroy the DNS subsystem. This will cancel any pending DNS jobs.
void net_dns_destroy();
/// Process finished DNS lookups.
void net_dns_process();
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
/**
* Callback to be called when the DNS job has finished.
* If the name or address could not be resolved to an IP address (host not found, or found but has no address)
* then 'result' contains an empty list (@see net_dns_result_size()).
* If resolving caused an error then result is NULL.
*
* After this callback is called the job is considered done, and is freed.
*
* @param If 1 is returned then result is deleted immediately after the callback,
* otherwise the callback becomes owner of the result data which must be freed with net_dns_result_free().
*/
typedef int (*net_dns_job_cb)(struct net_dns_job*, const struct net_dns_result* result);
/**
* Resolve a hostname.
*
* @param host the hostname to be resolved.
* @param af the indicated address family. Should be AF_INET, AF_INET6 (or AF_UNSPEC - which means both AF_INET and AF_INET6.
* @param callback the callback to be called when the hostname has been resolved.
* @param ptr A user-defined pointer value.
*
* @return A resolve job handle if the job has successfully started or NULL if unable to start resolving.
*/
extern struct net_dns_job* net_dns_gethostbyname(const char* host, int af, net_dns_job_cb callback, void* ptr);
/**
* Perform a reverse DNS lookup for a given IP address.
*
* @see net_dns_gethostbyname()
* @return A resolve job handle if the job has successfully started or NULL if unable to start resolving.
*/
extern struct net_dns_job* net_dns_gethostbyaddr(struct ip_addr_encap* ipaddr, net_dns_job_cb callback, void* ptr);
/**
* Cancel a DNS lookup job.
*
* It is only allowed to call this once after a job has been started (@see net_dns_gethostbyname(), @see net_dns_gethostbyaddr())
* but before it has finished and delivered a to the callback address (@see net_dns_job_cb).
*
* @returns 1 if cancelled, or 0 if not cancelled (because the job was not found!)
*/
extern int net_dns_job_cancel(struct net_dns_job* job);
/**
* Wait in a synchronous manner for a running DNS job to finished and
* return the result here.
* The job must be started with net_dns_gethostbyaddr/net_dns_gethostbyname
* and not finished or cancelled.
*
* If this function is invoked then the callback function will not be called and
* can therefore be NULL.
*
* <code>
* struct net_dns_job* job = net_dns_gethostbyname("www.example.com", AF_INET, NULL, NULL);
* struct net_dns_result* net_dns_job_sync_wait(job);
* </code>
*/
extern struct net_dns_result* net_dns_job_sync_wait(struct net_dns_job* job);
/**
* Returns the user specified pointer assigned to the resolving job
*/
extern void* net_dns_job_get_ptr(const struct net_dns_job* job);
/// Returns the number of results provided. This is 0 if the host could not be found (or has no matching IP address).
extern size_t net_dns_result_size(const struct net_dns_result*);
/// Returns the first result (if net_dns_result_size > 0), or NULL if not first result exists.
extern struct ip_addr_encap* net_dns_result_first(const struct net_dns_result*);
/// Returns the next result or NULL if no next result exists.
extern struct ip_addr_encap* net_dns_result_next(const struct net_dns_result*);
/// When finished with the results
extern void net_dns_result_free(struct net_dns_result*);
#endif /* HAVE_UHUB_NETWORK_DNS_RESOLVER_H */

View File

@@ -60,6 +60,9 @@ int net_initialize()
#endif
return -1;
}
net_dns_initialize();
net_stats_initialize();
net_initialized = 1;
return 0;
@@ -94,8 +97,10 @@ int net_destroy()
{
LOG_TRACE("Shutting down network monitor");
net_dns_destroy();
net_backend_shutdown();
#ifdef SSL_SUPPORT
net_ssl_library_shutdown();
#endif /* SSL_SUPPORT */
@@ -490,7 +495,6 @@ int net_socket_create(int af, int type, int protocol)
}
}
#endif
return sd;
}

View File

@@ -34,6 +34,7 @@
#ifndef WINSOCK
#define WINSOCK
#endif
#define WINTHREAD_SUPPORT 1
#endif
#if defined(__CYGWIN__) || defined(__MINGW32__)
@@ -113,11 +114,13 @@
#define uhub_assert assert
#ifdef __linux__
#define POSIX_THREAD_SUPPORT
#define USE_EPOLL
#include <sys/epoll.h>
#endif
#ifdef BSD_LIKE
#define POSIX_THREAD_SUPPORT
/*
#define USE_KQUEUE
#include <sys/event.h>
@@ -279,6 +282,10 @@ typedef unsigned __int64 uint64_t;
#define NEED_GETOPT
#endif
#ifdef POSIX_THREAD_SUPPORT
#include <pthread.h>
#endif
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(_MSC_VER)
#define PLUGIN_API __declspec(dllexport)
#else

View File

@@ -30,6 +30,7 @@
enum ADC_client_state
{
ps_none, /* Not connected */
ps_dns, /* looking up name */
ps_conn, /* Connecting... */
ps_conn_ssl, /* SSL handshake */
ps_protocol, /* Have sent HSUP */
@@ -46,6 +47,13 @@ enum ADC_client_flags
cflag_pipe = 4,
};
struct ADC_client_address
{
enum Protocol { ADC, ADCS } protocol;
char* hostname;
uint16_t port;
};
struct ADC_client
{
sid_t sid;
@@ -59,8 +67,9 @@ struct ADC_client
size_t timeout;
struct net_connection* con;
struct net_timer* timer;
struct sockaddr_in addr;
char* hub_address;
struct sockaddr_storage addr;
struct net_dns_job* dns_job;
struct ADC_client_address address;
char* nick;
char* desc;
int flags;
@@ -100,6 +109,7 @@ static void ADC_client_debug(struct ADC_client* client, const char* format, ...)
static const char* ADC_client_state_string[] =
{
"ps_none",
"ps_dns",
"ps_conn",
"ps_conn_ssl",
"ps_protocol",
@@ -154,6 +164,9 @@ static void event_callback(struct net_connection* con, int events, void *arg)
switch (client->state)
{
case ps_dns:
break;
case ps_conn:
if (events == NET_EVENT_TIMEOUT)
{
@@ -162,7 +175,7 @@ static void event_callback(struct net_connection* con, int events, void *arg)
}
if (events & NET_EVENT_WRITE)
ADC_client_connect(client, 0);
ADC_client_connect_internal(client);
break;
#ifdef SSL_SUPPORT
@@ -493,7 +506,7 @@ void ADC_client_send(struct ADC_client* client, struct adc_message* msg)
void ADC_client_send_info(struct ADC_client* client)
{
ADC_TRACE;
client->info = adc_msg_construct_source(ADC_CMD_BINF, client->sid, 64);
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);
@@ -502,7 +515,17 @@ void ADC_client_send_info(struct ADC_client* client)
adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_DESCRIPTION, client->desc);
}
adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_USER_AGENT, PRODUCT "/" VERSION);
adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_USER_AGENT, PRODUCT " " VERSION);
adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_UPLOAD_SLOTS, 0);
adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_SHARED_SIZE, 0);
adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_SHARED_FILES, 0);
adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_COUNT_HUB_NORMAL, 1);
adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_COUNT_HUB_REGISTER, 0);
adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_COUNT_HUB_OPERATOR, 0);
adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_DOWNLOAD_SPEED, 5 * 1024 * 1024);
adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_UPLOAD_SPEED, 10 * 1024 * 1024);
adc_cid_pid(client);
ADC_client_send(client, client->info);
@@ -541,20 +564,31 @@ void ADC_client_destroy(struct ADC_client* client)
adc_msg_free(client->info);
hub_free(client->nick);
hub_free(client->desc);
hub_free(client->hub_address);
hub_free(client->address.hostname);
}
int ADC_client_connect(struct ADC_client* client, const char* address)
{
ADC_TRACE;
if (!client->hub_address)
if (client->state == ps_none)
{
// Parse address and start name resolving!
if (!ADC_client_parse_address(client, address))
return 0;
return 1;
}
else if (client->state == ps_dns)
{
// Done name resolving!
client->callback(client, ADC_CLIENT_CONNECTING, 0);
ADC_client_set_state(client, ps_conn);
}
return ADC_client_connect_internal(client);
}
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))
{
@@ -632,19 +666,53 @@ void ADC_client_disconnect(struct ADC_client* client)
}
}
int ADC_client_dns_callback(struct net_dns_job* job, const struct net_dns_result* result)
{
struct ADC_client* client = (struct ADC_client*) net_dns_job_get_ptr(job);
struct ip_addr_encap* ipaddr;
LOG_WARN("ADC_client_dns_callback(): result=%p (%d)", result, net_dns_result_size(result));
memset(&client->addr, 0, sizeof(client->addr));
ipaddr = net_dns_result_first(result);
switch (ipaddr->af)
{
case AF_INET:
{
struct sockaddr_in* addr4 = (struct sockaddr_in*) &client->addr;
addr4->sin_family = AF_INET;
addr4->sin_port = htons(client->address.port);
memcpy(&addr4->sin_addr, &ipaddr->internal_ip_data.in, sizeof(struct in_addr));
break;
}
case AF_INET6:
{
struct sockaddr_in6* addr6 = (struct sockaddr_in6*) &client->addr;
addr6->sin6_family = AF_INET6;
addr6->sin6_port = htons(client->address.port);
memcpy(&addr6->sin6_addr, &ipaddr->internal_ip_data.in6, sizeof(struct in6_addr));
break;
}
default:
LOG_WARN("Unknown ipaddr!");
}
ADC_client_connect_internal(client);
return 1;
}
static int ADC_client_parse_address(struct ADC_client* client, const char* arg)
{
ADC_TRACE;
const char* hub_address = arg;
char* split;
int ssl = 0;
struct hostent* dns;
struct in_addr* addr;
if (!arg)
return 0;
client->hub_address = hub_strdup(arg);
/* Minimum length of a valid address */
if (strlen(arg) < 9)
return 0;
@@ -653,39 +721,33 @@ static int ADC_client_parse_address(struct ADC_client* client, const char* arg)
if (!strncmp(arg, "adc://", 6))
{
client->flags &= ~cflag_ssl;
client->address.protocol = ADC;
}
else if (!strncmp(arg, "adcs://", 7))
{
client->flags |= cflag_ssl;
ssl = 1;
client->address.protocol = ADCS;
}
else
return 0;
/* Split hostname and port (if possible) */
split = strrchr(client->hub_address + 6 + ssl, ':');
hub_address = arg + 6 + ssl;
split = strrchr(hub_address, ':');
if (split == 0 || strlen(split) < 2 || strlen(split) > 6)
return 0;
/* Ensure port number is valid */
int port = strtol(split+1, NULL, 10);
if (port <= 0 || port > 65535)
client->address.port = strtol(split+1, NULL, 10);
if (client->address.port <= 0 || client->address.port > 65535)
return 0;
split[0] = 0;
client->address.hostname = strndup(hub_address, &split[0] - &hub_address[0]);
/* Resolve IP address (FIXME: blocking call) */
dns = gethostbyname(client->hub_address + 6 + ssl);
if (dns)
{
addr = (struct in_addr*) dns->h_addr_list[0];
}
// Initialize the sockaddr struct.
memset(&client->addr, 0, sizeof(client->addr));
client->addr.sin_family = AF_INET;
client->addr.sin_port = htons(port);
memcpy(&client->addr.sin_addr, addr, sizeof(struct in_addr));
client->callback(client, ADC_CLIENT_NAME_LOOKUP, 0);
ADC_client_set_state(client, ps_dns);
client->dns_job = net_dns_gethostbyname(client->address.hostname, AF_UNSPEC, ADC_client_dns_callback, client);
return 1;
}

View File

@@ -28,6 +28,7 @@ struct ADC_client;
enum ADC_client_callback_type
{
ADC_CLIENT_NAME_LOOKUP = 1000,
ADC_CLIENT_CONNECTING = 1001,
ADC_CLIENT_CONNECTED = 1002,
ADC_CLIENT_DISCONNECTED = 1003,

View File

@@ -91,6 +91,10 @@ static int handle(struct ADC_client* client, enum ADC_client_callback_type type,
{
switch (type)
{
case ADC_CLIENT_NAME_LOOKUP:
status("Looking up hostname...");
break;
case ADC_CLIENT_CONNECTING:
status("Connecting...");
break;
@@ -107,6 +111,9 @@ static int handle(struct ADC_client* client, enum ADC_client_callback_type type,
status("SSL handshake.");
break;
case ADC_CLIENT_SSL_OK:
break;
case ADC_CLIENT_LOGGING_IN:
status("Logging in...");
break;

View File

@@ -68,12 +68,14 @@ extern "C" {
#include "util/memory.h"
#include "util/misc.h"
#include "util/tiger.h"
#include "util/threads.h"
#include "adc/sid.h"
#include "adc/message.h"
#include "network/network.h"
#include "network/connection.h"
#include "network/dnsresolver.h"
#include "network/ipcalc.h"
#include "network/timeout.h"

141
src/util/threads.c Normal file
View File

@@ -0,0 +1,141 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "uhub.h"
#ifdef POSIX_THREAD_SUPPORT
void uhub_mutex_init(uhub_mutex_t* mutex)
{
pthread_mutex_init(mutex, NULL);
}
void uhub_mutex_destroy(uhub_mutex_t* mutex)
{
pthread_mutex_destroy(mutex);
}
void uhub_mutex_lock(uhub_mutex_t* mutex)
{
pthread_mutex_lock(mutex);
}
void uhub_mutex_unlock(uhub_mutex_t* mutex)
{
pthread_mutex_unlock(mutex);
}
int uhub_mutex_trylock(uhub_mutex_t* mutex)
{
int ret = pthread_mutex_trylock(mutex);
return (ret == 0);
}
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));
int ret = pthread_create(thread, NULL, start, arg);
if (ret == 0)
return thread;
hub_free(thread);
return NULL;
}
void uhub_thread_cancel(uhub_thread_t* thread)
{
pthread_cancel(thread);
}
void* uhub_thread_join(uhub_thread_t* thread)
{
void* ret = NULL;
pthread_join(thread, &ret);
hub_free(thread);
return ret;
}
#endif /* POSIX_THREAD_SUPPORT */
#ifdef WINTHREAD_SUPPORT
struct winthread_data
{
uhub_thread_t* handle;
uhub_thread_start start;
void* arg;
};
static DWORD WINAPI uhub_winthread_start(void* ptr)
{
struct winthread_data* data = (struct winthread_data*) ptr;
DWORD ret = (DWORD) data->start(data->arg);
return ret;
}
void uhub_mutex_init(uhub_mutex_t* mutex)
{
InitializeCriticalSection(mutex);
}
void uhub_mutex_destroy(uhub_mutex_t* mutex)
{
DeleteCriticalSection(mutex);
}
void uhub_mutex_lock(uhub_mutex_t* mutex)
{
EnterCriticalSection(mutex);
}
void uhub_mutex_unlock(uhub_mutex_t* mutex)
{
LeaveCriticalSection(mutex);
}
int uhub_mutex_trylock(uhub_mutex_t* mutex)
{
return TryEnterCriticalSection(mutex);
}
uhub_thread_t* uhub_thread_create(uhub_thread_start start, void* arg)
{
struct winthread_data* thread = (struct winthread_data*) hub_malloc_zero(sizeof(struct winthread_data));
thread->start = start;
thread->arg = arg;
thread->handle = CreateThread(NULL, 0, uhub_winthread_start, thread, 0, 0);
return thread;
}
void uhub_thread_cancel(uhub_thread_t* thread)
{
TerminateThread(thread->handle, 0);
}
void* uhub_thread_join(uhub_thread_t* thread)
{
void* ret = NULL;
DWORD exitCode;
WaitForSingleObject(thread->handle, INFINITE);
GetExitCodeThread(thread->handle, &exitCode);
ret = &exitCode;
CloseHandle(thread->handle);
hub_free(thread);
return ret;
}
#endif /* WINTHREAD_SUPPORT */

49
src/util/threads.h Normal file
View File

@@ -0,0 +1,49 @@
/*
* uhub - A tiny ADC p2p connection hub
* Copyright (C) 2007-2012, Jan Vidar Krey
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef HAVE_UHUB_UTIL_THREADS_H
#define HAVE_UHUB_UTIL_THREADS_H
typedef void*(*uhub_thread_start)(void*) ;
#ifdef POSIX_THREAD_SUPPORT
typedef pthread_t uhub_thread_t;
typedef pthread_mutex_t uhub_mutex_t;
#endif
#ifdef WINTHREAD_SUPPORT
struct winthread_data;
typedef struct winthread_data uhub_thread_t;
typedef CRITICAL_SECTION uhub_mutex_t;
#endif
// Mutexes
extern void uhub_mutex_init(uhub_mutex_t* mutex);
extern void uhub_mutex_destroy(uhub_mutex_t* mutex);
extern void uhub_mutex_lock(uhub_mutex_t* mutex);
extern void uhub_mutex_unlock(uhub_mutex_t* mutex);
extern int uhub_mutex_trylock(uhub_mutex_t* mutex);
// Threads
uhub_thread_t* uhub_thread_create(uhub_thread_start start, void* arg);
void uhub_thread_cancel(uhub_thread_t* thread);
void* uhub_thread_join(uhub_thread_t* thread);
#endif /* HAVE_UHUB_UTIL_THREADS_H */