Start using the async DNS API.

This commit is contained in:
Jan Vidar Krey 2012-10-24 23:22:10 +02:00
parent 793790d089
commit b34b90f95a
3 changed files with 98 additions and 28 deletions

View File

@ -30,6 +30,7 @@
enum ADC_client_state enum ADC_client_state
{ {
ps_none, /* Not connected */ ps_none, /* Not connected */
ps_dns, /* looking up name */
ps_conn, /* Connecting... */ ps_conn, /* Connecting... */
ps_conn_ssl, /* SSL handshake */ ps_conn_ssl, /* SSL handshake */
ps_protocol, /* Have sent HSUP */ ps_protocol, /* Have sent HSUP */
@ -46,6 +47,13 @@ enum ADC_client_flags
cflag_pipe = 4, cflag_pipe = 4,
}; };
struct ADC_client_address
{
enum Protocol { ADC, ADCS } protocol;
char* hostname;
uint16_t port;
};
struct ADC_client struct ADC_client
{ {
sid_t sid; sid_t sid;
@ -59,8 +67,9 @@ struct ADC_client
size_t timeout; size_t timeout;
struct net_connection* con; struct net_connection* con;
struct net_timer* timer; struct net_timer* timer;
struct sockaddr_in addr; struct sockaddr_storage addr;
char* hub_address; struct net_dns_job* dns_job;
struct ADC_client_address address;
char* nick; char* nick;
char* desc; char* desc;
int flags; 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[] = static const char* ADC_client_state_string[] =
{ {
"ps_none", "ps_none",
"ps_dns",
"ps_conn", "ps_conn",
"ps_conn_ssl", "ps_conn_ssl",
"ps_protocol", "ps_protocol",
@ -154,6 +164,9 @@ static void event_callback(struct net_connection* con, int events, void *arg)
switch (client->state) switch (client->state)
{ {
case ps_dns:
break;
case ps_conn: case ps_conn:
if (events == NET_EVENT_TIMEOUT) 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) if (events & NET_EVENT_WRITE)
ADC_client_connect(client, 0); ADC_client_connect_internal(client);
break; break;
#ifdef SSL_SUPPORT #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) void ADC_client_send_info(struct ADC_client* client)
{ {
ADC_TRACE; 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); 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_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_cid_pid(client);
ADC_client_send(client, client->info); ADC_client_send(client, client->info);
@ -541,20 +564,31 @@ void ADC_client_destroy(struct ADC_client* client)
adc_msg_free(client->info); adc_msg_free(client->info);
hub_free(client->nick); hub_free(client->nick);
hub_free(client->desc); 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) int ADC_client_connect(struct ADC_client* client, const char* address)
{ {
ADC_TRACE; ADC_TRACE;
if (!client->hub_address) if (client->state == ps_none)
{ {
// Parse address and start name resolving!
if (!ADC_client_parse_address(client, address)) if (!ADC_client_parse_address(client, address))
return 0; return 0;
return 1;
}
else if (client->state == ps_dns)
{
// Done name resolving!
client->callback(client, ADC_CLIENT_CONNECTING, 0); 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)); 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))
{ {
@ -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) static int ADC_client_parse_address(struct ADC_client* client, const char* arg)
{ {
ADC_TRACE; ADC_TRACE;
const char* hub_address = arg;
char* split; char* split;
int ssl = 0; int ssl = 0;
struct hostent* dns;
struct in_addr* addr;
if (!arg) if (!arg)
return 0; return 0;
client->hub_address = hub_strdup(arg);
/* Minimum length of a valid address */ /* Minimum length of a valid address */
if (strlen(arg) < 9) if (strlen(arg) < 9)
return 0; return 0;
@ -653,39 +721,33 @@ static int ADC_client_parse_address(struct ADC_client* client, const char* arg)
if (!strncmp(arg, "adc://", 6)) if (!strncmp(arg, "adc://", 6))
{ {
client->flags &= ~cflag_ssl; client->flags &= ~cflag_ssl;
client->address.protocol = ADC;
} }
else if (!strncmp(arg, "adcs://", 7)) else if (!strncmp(arg, "adcs://", 7))
{ {
client->flags |= cflag_ssl; client->flags |= cflag_ssl;
ssl = 1; ssl = 1;
client->address.protocol = ADCS;
} }
else else
return 0; return 0;
/* Split hostname and port (if possible) */ /* 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) if (split == 0 || strlen(split) < 2 || strlen(split) > 6)
return 0; return 0;
/* Ensure port number is valid */ /* Ensure port number is valid */
int port = strtol(split+1, NULL, 10); client->address.port = strtol(split+1, NULL, 10);
if (port <= 0 || port > 65535) if (client->address.port <= 0 || client->address.port > 65535)
return 0; return 0;
split[0] = 0; client->address.hostname = strndup(hub_address, &split[0] - &hub_address[0]);
/* Resolve IP address (FIXME: blocking call) */ client->callback(client, ADC_CLIENT_NAME_LOOKUP, 0);
dns = gethostbyname(client->hub_address + 6 + ssl); ADC_client_set_state(client, ps_dns);
if (dns) client->dns_job = net_dns_gethostbyname(client->address.hostname, AF_UNSPEC, ADC_client_dns_callback, client);
{
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));
return 1; return 1;
} }

View File

@ -28,6 +28,7 @@ struct ADC_client;
enum ADC_client_callback_type enum ADC_client_callback_type
{ {
ADC_CLIENT_NAME_LOOKUP = 1000,
ADC_CLIENT_CONNECTING = 1001, ADC_CLIENT_CONNECTING = 1001,
ADC_CLIENT_CONNECTED = 1002, ADC_CLIENT_CONNECTED = 1002,
ADC_CLIENT_DISCONNECTED = 1003, 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) switch (type)
{ {
case ADC_CLIENT_NAME_LOOKUP:
status("Looking up hostname...");
break;
case ADC_CLIENT_CONNECTING: case ADC_CLIENT_CONNECTING:
status("Connecting..."); status("Connecting...");
break; break;
@ -107,6 +111,9 @@ static int handle(struct ADC_client* client, enum ADC_client_callback_type type,
status("SSL handshake."); status("SSL handshake.");
break; break;
case ADC_CLIENT_SSL_OK:
break;
case ADC_CLIENT_LOGGING_IN: case ADC_CLIENT_LOGGING_IN:
status("Logging in..."); status("Logging in...");
break; break;