Ejemplo n.º 1
0
static void
dns_search_test(void *arg)
{
	struct basic_test_data *data = arg;
	struct event_base *base = data->base;
	struct evdns_base *dns = NULL;
	ev_uint16_t portnum = 0;
	char buf[64];

	struct generic_dns_callback_result r1, r2, r3, r4, r5;

	tt_assert(regress_dnsserver(base, &portnum, search_table));
	evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum);

	dns = evdns_base_new(base, 0);
	tt_assert(!evdns_base_nameserver_ip_add(dns, buf));

	evdns_base_search_add(dns, "a.example.com");
	evdns_base_search_add(dns, "b.example.com");
	evdns_base_search_add(dns, "c.example.com");

	n_replies_left = 5;
	exit_base = base;

	evdns_base_resolve_ipv4(dns, "host", 0, generic_dns_callback, &r1);
	evdns_base_resolve_ipv4(dns, "host2", 0, generic_dns_callback, &r2);
	evdns_base_resolve_ipv4(dns, "host", DNS_NO_SEARCH, generic_dns_callback, &r3);
	evdns_base_resolve_ipv4(dns, "host2", DNS_NO_SEARCH, generic_dns_callback, &r4);
	evdns_base_resolve_ipv4(dns, "host3", 0, generic_dns_callback, &r5);

	event_base_dispatch(base);

	tt_int_op(r1.type, ==, DNS_IPv4_A);
	tt_int_op(r1.count, ==, 1);
	tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0x0b16212c));
	tt_int_op(r2.type, ==, DNS_IPv4_A);
	tt_int_op(r2.count, ==, 1);
	tt_int_op(((ev_uint32_t*)r2.addrs)[0], ==, htonl(0xc8640064));
	tt_int_op(r3.result, ==, DNS_ERR_NOTEXIST);
	tt_int_op(r4.result, ==, DNS_ERR_NOTEXIST);
	tt_int_op(r5.result, ==, DNS_ERR_NOTEXIST);

end:
	if (dns)
		evdns_base_free(dns, 0);

	regress_clean_dnsserver();
}
Ejemplo n.º 2
0
static
void
handle_tcp_connect_stage1(struct async_network_task_s *task)
{
    struct evdns_request *req;
    struct sockaddr_in sai;

    memset(&sai, 0, sizeof(sai));
    if (inet_pton(AF_INET, task->host, &sai.sin_addr) == 1) {
        // already a valid IP address
        handle_tcp_connect_stage2(DNS_ERR_NONE, DNS_IPv4_A, 1, 300, &sai.sin_addr, task);
        return;
    }

    // queue DNS request
    req = evdns_base_resolve_ipv4(evdns_b, task->host, DNS_QUERY_NO_SEARCH,
                                  handle_tcp_connect_stage2, task);
    // TODO: what about ipv6?

    if (!req) {
        trace_warning("%s, early dns resolution failure (%s:%u)\n", __func__, task->host,
                      (unsigned int)task->port);
        ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0,
                                               PP_ERROR_NAME_NOT_RESOLVED, 0, __func__);
        task_destroy(task);
        return;
    }
}
Ejemplo n.º 3
0
static void
dns_search_test(void *arg)
{
	struct basic_test_data *data = arg;
	struct event_base *base = data->base;
	struct evdns_base *dns = NULL;
	ev_uint16_t portnum = 0;
	char buf[64];

	struct generic_dns_callback_result r[8];

	tt_assert(regress_dnsserver(base, &portnum, search_table));
	evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum);

	dns = evdns_base_new(base, 0);
	tt_assert(!evdns_base_nameserver_ip_add(dns, buf));

	evdns_base_search_add(dns, "a.example.com");
	evdns_base_search_add(dns, "b.example.com");
	evdns_base_search_add(dns, "c.example.com");

	n_replies_left = sizeof(r)/sizeof(r[0]);
	exit_base = base;

	evdns_base_resolve_ipv4(dns, "host", 0, generic_dns_callback, &r[0]);
	evdns_base_resolve_ipv4(dns, "host2", 0, generic_dns_callback, &r[1]);
	evdns_base_resolve_ipv4(dns, "host", DNS_NO_SEARCH, generic_dns_callback, &r[2]);
	evdns_base_resolve_ipv4(dns, "host2", DNS_NO_SEARCH, generic_dns_callback, &r[3]);
	evdns_base_resolve_ipv4(dns, "host3", 0, generic_dns_callback, &r[4]);
	evdns_base_resolve_ipv4(dns, "hostn.a.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[5]);
	evdns_base_resolve_ipv4(dns, "hostn.b.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[6]);
	evdns_base_resolve_ipv4(dns, "hostn.c.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[7]);

	event_base_dispatch(base);

	tt_int_op(r[0].type, ==, DNS_IPv4_A);
	tt_int_op(r[0].count, ==, 1);
	tt_int_op(((ev_uint32_t*)r[0].addrs)[0], ==, htonl(0x0b16212c));
	tt_int_op(r[1].type, ==, DNS_IPv4_A);
	tt_int_op(r[1].count, ==, 1);
	tt_int_op(((ev_uint32_t*)r[1].addrs)[0], ==, htonl(0xc8640064));
	tt_int_op(r[2].result, ==, DNS_ERR_NOTEXIST);
	tt_int_op(r[3].result, ==, DNS_ERR_NOTEXIST);
	tt_int_op(r[4].result, ==, DNS_ERR_NOTEXIST);
	tt_int_op(r[5].result, ==, DNS_ERR_NODATA);
	tt_int_op(r[5].ttl, ==, 42);
	tt_int_op(r[6].result, ==, DNS_ERR_NOTEXIST);
	tt_int_op(r[6].ttl, ==, 42);
	tt_int_op(r[7].result, ==, DNS_ERR_NODATA);
	tt_int_op(r[7].ttl, ==, 0);

end:
	if (dns)
		evdns_base_free(dns, 0);

	regress_clean_dnsserver();
}
Ejemplo n.º 4
0
bool Server::connect(const char *h, const char *n, int p, const char *alias_) {
	host = strdup(h);
	port = p;
	if(alias_) alias = strdup(alias_); else alias = strdup(h);
	nick = strdup(n);
	DEBUGF(evdns_base_resolve_ipv4(client->dnsbase, host, 0, irc_dnscb, this));
	return true;
}
Ejemplo n.º 5
0
static void
dns_reissue_test(void *arg)
{
	struct basic_test_data *data = arg;
	struct event_base *base = data->base;
	struct evdns_server_port *port1 = NULL, *port2 = NULL;
	struct evdns_base *dns = NULL;
	struct generic_dns_callback_result r1;
	ev_uint16_t portnum1 = 0, portnum2=0;
	char buf1[64], buf2[64];

	port1 = regress_get_dnsserver(base, &portnum1, NULL,
	    regress_dns_server_cb, internal_error_table);
	tt_assert(port1);
	port2 = regress_get_dnsserver(base, &portnum2, NULL,
	    regress_dns_server_cb, reissue_table);
	tt_assert(port2);
	evutil_snprintf(buf1, sizeof(buf1), "127.0.0.1:%d", (int)portnum1);
	evutil_snprintf(buf2, sizeof(buf2), "127.0.0.1:%d", (int)portnum2);

	dns = evdns_base_new(base, 0);
	tt_assert(!evdns_base_nameserver_ip_add(dns, buf1));
	tt_assert(! evdns_base_set_option(dns, "timeout:", "0.3"));
	tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "2"));
	tt_assert(! evdns_base_set_option(dns, "attempts:", "5"));

	memset(&r1, 0, sizeof(r1));
	evdns_base_resolve_ipv4(dns, "foof.example.com", 0,
	    generic_dns_callback, &r1);

	/* Add this after, so that we are sure to get a reissue. */
	tt_assert(!evdns_base_nameserver_ip_add(dns, buf2));

	n_replies_left = 1;
	exit_base = base;

	event_base_dispatch(base);
	tt_int_op(r1.result, ==, DNS_ERR_NONE);
	tt_int_op(r1.type, ==, DNS_IPv4_A);
	tt_int_op(r1.count, ==, 1);
	tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0xf00ff00f));

	/* Make sure we dropped at least once. */
	tt_int_op(internal_error_table[0].seen, >, 0);

end:
	if (dns)
		evdns_base_free(dns, 0);
	if (port1)
		evdns_close_server_port(port1);
	if (port2)
		evdns_close_server_port(port2);
}
Ejemplo n.º 6
0
/* Implements the asynchronous-resolve side of
 * bufferevent_socket_connect_hostname(). */
int
_bufferevent_socket_connect_hostname_evdns(
    struct bufferevent *bufev,
    struct evdns_base *evdns_base,
    int family,
    const char *hostname,
    int port)
{
    struct evdns_request *r;
    struct resolveinfo *resolveinfo;

    if (family == AF_UNSPEC)
        family = AF_INET; /* XXXX handle "unspec" correctly */
    if (family != AF_INET && family != AF_INET6)
        return -1;
    if (!bufev || !evdns_base || !hostname)
        return -1;
    if (port < 1 || port > 65535)
        return -1;

    resolveinfo = mm_calloc(1, sizeof(resolveinfo));
    if (!resolveinfo)
        return -1;
    resolveinfo->family = family;
    resolveinfo->port = htons(port);
    resolveinfo->bev = bufev;

    if (family == AF_INET) {
        r = evdns_base_resolve_ipv4(evdns_base, hostname, 0,
                                    dns_reply_callback, resolveinfo);
    } else {
        r = evdns_base_resolve_ipv6(evdns_base, hostname, 0,
                                    dns_reply_callback, resolveinfo);
    }

    if (!r) {
        mm_free(resolveinfo);
        return -1;
    }

    /* We either need to incref the bufferevent here, or have some code to
     * cancel the resolve if the bufferevent gets freed.  Let's take the
     * first approach. */
    bufferevent_incref(bufev);
    return 0;
}
Ejemplo n.º 7
0
IoObject *IoEvDNSRequest_resolveIPv4(IoEvDNSRequest *self, IoObject *locals, IoMessage *m)
{	
	IoSeq *host = IoObject_seqGetSlot_(self, IOSYMBOL("host"));
	IoEvDNS *evDns = IoObject_getSlot_(self, IOSYMBOL("evDns"));
	IOASSERT(ISEVDNS(evDns), "evDns slot not set properly");
	
	struct evdns_base *dnsBase = IoObject_dataPointer(evDns);
	struct evdns_request *req = evdns_base_resolve_ipv4(dnsBase, 
		CSTRING(host),
		DNS_QUERY_NO_SEARCH,
		(EvDNSRequest_callback_type)EvDNSRequest_callback,
		(void *)self 
	);
	
	IoObject_setDataPointer_(self, req);
	
	return self;
}
Ejemplo n.º 8
0
static void
dns_inflight_test(void *arg)
{
	struct basic_test_data *data = arg;
	struct event_base *base = data->base;
	struct evdns_base *dns = NULL;
	ev_uint16_t portnum = 53900;/*XXXX let the code pick a port*/

	struct generic_dns_callback_result r[20];
	int i;

	tt_assert(regress_dnsserver(base, &portnum, reissue_table));

	/* Make sure that having another (very bad!) RNG doesn't mess us
	 * up. */
	evdns_set_random_bytes_fn(dumb_bytes_fn);

	dns = evdns_base_new(base, 0);
	tt_assert(!evdns_base_nameserver_ip_add(dns, "127.0.0.1:53900"));
	tt_assert(! evdns_base_set_option(dns, "max-inflight:", "3", DNS_OPTIONS_ALL));
	tt_assert(! evdns_base_set_option(dns, "randomize-case:", "0", DNS_OPTIONS_ALL));

	for(i=0;i<20;++i)
		evdns_base_resolve_ipv4(dns, "foof.example.com", 0, generic_dns_callback, &r[i]);

	n_replies_left = 20;
	exit_base = base;

	event_base_dispatch(base);

	for (i=0;i<20;++i) {
		tt_int_op(r[i].type, ==, DNS_IPv4_A);
		tt_int_op(r[i].count, ==, 1);
		tt_int_op(((ev_uint32_t*)r[i].addrs)[0], ==, htonl(0xf00ff00f));
	}

end:
	if (dns)
		evdns_base_free(dns, 0);
	regress_clean_dnsserver();
}
Ejemplo n.º 9
0
int main(int argc, char *argv[])
{
    struct evdns_base *evdns_base;

    if (options_parse(&app_context, argc, argv) != 0) {
        return 1;
    }
#ifdef _WIN32
    WSADATA wsa_data;
    WSAStartup(MAKEWORD(2, 2), &wsa_data);
#endif
    if ((app_context.event_loop = event_base_new()) == NULL) {
        perror("event_base_new");
        return 1;
    }
    if ((evdns_base = evdns_base_new(app_context.event_loop, 0)) == NULL) {
        perror("evdns_base");
        return 1;
    }
    evdns_base_set_option(evdns_base, "use-tcp", "on-tc");
    evdns_base_set_option(evdns_base, "randomize-case", "0");
    if (evdns_base_nameserver_ip_add(evdns_base,
                                     app_context.resolver_ip) != 0) {
        fprintf(stderr, "Unable to use [%s] as a resolver\n",
                app_context.resolver_ip);
        return 1;
    }
    if (app_context.want_ipv6 != 0) {
        evdns_base_resolve_ipv6(evdns_base, app_context.host_name,
                                DNS_QUERY_NO_SEARCH,
                                ipv6_query_cb, &app_context);
    } else {
        evdns_base_resolve_ipv4(evdns_base, app_context.host_name,
                                DNS_QUERY_NO_SEARCH,
                                ipv4_query_cb, &app_context);
    }
    event_base_dispatch(app_context.event_loop);
    event_base_free(app_context.event_loop);

    return 0;
}
Ejemplo n.º 10
0
static void
dns_search_cancel_test(void *arg)
{
	struct basic_test_data *data = arg;
	struct event_base *base = data->base;
	struct evdns_base *dns = NULL;
	struct evdns_server_port *port = NULL;
	ev_uint16_t portnum = 0;
	struct generic_dns_callback_result r1;
	char buf[64];

	port = regress_get_dnsserver(base, &portnum, NULL,
	    search_cancel_server_cb, NULL);
	tt_assert(port);
	evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum);

	dns = evdns_base_new(base, 0);
	tt_assert(!evdns_base_nameserver_ip_add(dns, buf));

	evdns_base_search_add(dns, "a.example.com");
	evdns_base_search_add(dns, "b.example.com");
	evdns_base_search_add(dns, "c.example.com");
	evdns_base_search_add(dns, "d.example.com");

	exit_base = base;
	request_count = 3;
	n_replies_left = 1;

	current_req = evdns_base_resolve_ipv4(dns, "host", 0,
					generic_dns_callback, &r1);
	event_base_dispatch(base);

	tt_int_op(r1.result, ==, DNS_ERR_CANCEL);

end:
	if (port)
		evdns_close_server_port(port);
	if (dns)
		evdns_base_free(dns, 0);
}
Ejemplo n.º 11
0
static void
dns_inflight_test(void *arg)
{
	struct basic_test_data *data = arg;
	struct event_base *base = data->base;
	struct evdns_base *dns = NULL;
	ev_uint16_t portnum = 0;
	char buf[64];

	struct generic_dns_callback_result r[20];
	int i;

	tt_assert(regress_dnsserver(base, &portnum, reissue_table));
	evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum);

	dns = evdns_base_new(base, 0);
	tt_assert(!evdns_base_nameserver_ip_add(dns, buf));
	tt_assert(! evdns_base_set_option(dns, "max-inflight:", "3"));
	tt_assert(! evdns_base_set_option(dns, "randomize-case:", "0"));

	for (i=0;i<20;++i)
		evdns_base_resolve_ipv4(dns, "foof.example.com", 0, generic_dns_callback, &r[i]);

	n_replies_left = 20;
	exit_base = base;

	event_base_dispatch(base);

	for (i=0;i<20;++i) {
		tt_int_op(r[i].type, ==, DNS_IPv4_A);
		tt_int_op(r[i].count, ==, 1);
		tt_int_op(((ev_uint32_t*)r[i].addrs)[0], ==, htonl(0xf00ff00f));
	}

end:
	if (dns)
		evdns_base_free(dns, 0);
	regress_clean_dnsserver();
}
Ejemplo n.º 12
0
static void
dns_retry_test(void *arg)
{
	struct basic_test_data *data = arg;
	struct event_base *base = data->base;
	struct evdns_server_port *port = NULL;
	struct evdns_base *dns = NULL;
	int drop_count = 2;
	ev_uint16_t portnum = 53900;/*XXXX let the code pick a port*/

	struct generic_dns_callback_result r1;

	port = regress_get_dnsserver(base, &portnum, NULL,
	    fail_server_cb, &drop_count);
	tt_assert(port);

	dns = evdns_base_new(base, 0);
	tt_assert(!evdns_base_nameserver_ip_add(dns, "127.0.0.1:53900"));
	tt_assert(! evdns_base_set_option(dns, "timeout", "0.3", DNS_OPTIONS_ALL));
	tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "10", DNS_OPTIONS_ALL));
	tt_assert(! evdns_base_set_option(dns, "initial-probe-timeout", "0.5", DNS_OPTIONS_ALL));

	evdns_base_resolve_ipv4(dns, "host.example.com", 0,
	    generic_dns_callback, &r1);

	n_replies_left = 1;
	exit_base = base;

	event_base_dispatch(base);

	tt_int_op(drop_count, ==, 0);

	tt_int_op(r1.type, ==, DNS_IPv4_A);
	tt_int_op(r1.count, ==, 1);
	tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0x10204080));

	/* Now try again, but this time have the server get treated as
	 * failed, so we can send it a test probe. */
	drop_count = 4;
	tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "3", DNS_OPTIONS_ALL));
	tt_assert(! evdns_base_set_option(dns, "attempts:", "4", DNS_OPTIONS_ALL));
	memset(&r1, 0, sizeof(r1));

	evdns_base_resolve_ipv4(dns, "host.example.com", 0,
	    generic_dns_callback, &r1);

	n_replies_left = 2;

	/* This will run until it answers the "google.com" probe request. */
	event_base_dispatch(base);

	/* We'll treat the server as failed here. */
	tt_int_op(r1.result, ==, DNS_ERR_TIMEOUT);

	/* It should work this time. */
	tt_int_op(drop_count, ==, 0);
	evdns_base_resolve_ipv4(dns, "host.example.com", 0,
	    generic_dns_callback, &r1);

	event_base_dispatch(base);
	tt_int_op(r1.result, ==, DNS_ERR_NONE);
	tt_int_op(r1.type, ==, DNS_IPv4_A);
	tt_int_op(r1.count, ==, 1);
	tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0x10204080));

end:
	if (dns)
		evdns_base_free(dns, 0);
	if (port)
		evdns_close_server_port(port);
}
Ejemplo n.º 13
0
static void
dns_server(void)
{
        evutil_socket_t sock=-1;
	struct sockaddr_in my_addr;
	struct evdns_server_port *port=NULL;
	struct in_addr resolve_addr;
	struct in6_addr resolve_addr6;
	struct evdns_base *base=NULL;
	struct evdns_request *req=NULL;

	dns_ok = 1;

	base = evdns_base_new(NULL, 0);

	/* Add ourself as the only nameserver, and make sure we really are
	 * the only nameserver. */
	evdns_base_nameserver_ip_add(base, "127.0.0.1:35353");

	tt_int_op(evdns_base_count_nameservers(base), ==, 1);
	/* Now configure a nameserver port. */
	sock = socket(AF_INET, SOCK_DGRAM, 0);
        if (sock<0) {
                tt_abort_perror("socket");
        }

        evutil_make_socket_nonblocking(sock);

	memset(&my_addr, 0, sizeof(my_addr));
	my_addr.sin_family = AF_INET;
	my_addr.sin_port = htons(35353);
	my_addr.sin_addr.s_addr = htonl(0x7f000001UL);
	if (bind(sock, (struct sockaddr*)&my_addr, sizeof(my_addr)) < 0) {
		tt_abort_perror("bind");
	}
	port = evdns_add_server_port(sock, 0, dns_server_request_cb, NULL);

	/* Send some queries. */
	evdns_base_resolve_ipv4(base, "zz.example.com", DNS_QUERY_NO_SEARCH,
					   dns_server_gethostbyname_cb, NULL);
	evdns_base_resolve_ipv6(base, "zz.example.com", DNS_QUERY_NO_SEARCH,
					   dns_server_gethostbyname_cb, NULL);
	resolve_addr.s_addr = htonl(0xc0a80b0bUL); /* 192.168.11.11 */
	evdns_base_resolve_reverse(base, &resolve_addr, 0,
            dns_server_gethostbyname_cb, NULL);
	memcpy(resolve_addr6.s6_addr,
	    "\xff\xf0\x00\x00\x00\x00\xaa\xaa"
	    "\x11\x11\x00\x00\x00\x00\xef\xef", 16);
	evdns_base_resolve_reverse_ipv6(base, &resolve_addr6, 0,
            dns_server_gethostbyname_cb, (void*)6);

	req = evdns_base_resolve_ipv4(base,
	    "drop.example.com", DNS_QUERY_NO_SEARCH,
	    dns_server_gethostbyname_cb, (void*)(char*)90909);

	evdns_cancel_request(base, req);

	event_dispatch();

	tt_assert(dns_got_cancel);
        test_ok = dns_ok;

end:
        if (port)
                evdns_close_server_port(port);
        if (sock >= 0)
                EVUTIL_CLOSESOCKET(sock);
	if (base)
		evdns_base_free(base, 0);
}
Ejemplo n.º 14
0
static
void
handle_disconnect_stage1(struct async_network_task_s *task)
{
    struct event *ev = evtimer_new(event_b, handle_disconnect_stage2, task);
    struct timeval timeout = {.tv_sec = 0};
    add_event_mapping(task, ev);
    event_add(ev, &timeout);
}

static
void
handle_udp_recv_stage2(int sock, short event_flags, void *arg)
{
    struct async_network_task_s *task = arg;

    struct pp_udp_socket_s *us = pp_resource_acquire(task->resource, PP_RESOURCE_UDP_SOCKET);
    if (!us) {
        trace_error("%s, bad resource\n", __func__);
        task_destroy(task);
        return;
    }

    socklen_t len = sizeof(task->addr_from->data);
    int32_t retval = recvfrom(sock, task->buffer, task->bufsize, 0,
                              (struct sockaddr *)task->addr_from->data, &len);
    task->addr_from->size = len;

    if (task->addr_from_resource)
        pp_resource_unref(task->addr_from_resource);

    if (retval < 0)
        retval = get_pp_errno();
    else if (retval == 0) {
        us->seen_eof = 1;   // TODO: is it needed?
    }

    pp_resource_release(task->resource);
    ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0, retval, 0,
                                           __func__);
    task_destroy(task);
}

static
void
handle_udp_recv_stage1(struct async_network_task_s *task)
{
    struct pp_udp_socket_s *us = pp_resource_acquire(task->resource, PP_RESOURCE_UDP_SOCKET);
    if (!us) {
        trace_error("%s, bad resource\n", __func__);
        task_destroy(task);
        return;
    }

    memset(task->addr_from, 0, sizeof(*task->addr_from));

    struct event *ev = event_new(event_b, us->sock, EV_READ, handle_udp_recv_stage2, task);
    pp_resource_release(task->resource);
    add_event_mapping(task, ev);
    event_add(ev, NULL);
}

static
void
handle_udp_send_stage2(int sock, short event_flags, void *arg)
{
    struct async_network_task_s *task = arg;

    int retval = sendto(sock, task->buffer, task->bufsize, MSG_NOSIGNAL,
                        (struct sockaddr *)task->netaddr.data, task->netaddr.size);
    if (retval < 0)
        retval = get_pp_errno();

    ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0, retval, 0,
                                           __func__);
    task_destroy(task);
}

static
void
handle_udp_send_stage1(struct async_network_task_s *task)
{
    struct pp_udp_socket_s *us = pp_resource_acquire(task->resource, PP_RESOURCE_UDP_SOCKET);
    if (!us) {
        trace_error("%s, bad resource\n", __func__);
        task_destroy(task);
        return;
    }

    // try to send immediately, but don't wait
    int retval = sendto(us->sock, task->buffer, task->bufsize, MSG_DONTWAIT | MSG_NOSIGNAL,
                        (struct sockaddr *)task->netaddr.data, task->netaddr.size);
    pp_resource_release(task->resource);

    if (retval >= 0) {
        // successfully sent
        ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0, retval, 0,
                                               __func__);
        task_destroy(task);
        return;
    }

    // need to wait
    struct event *ev = event_new(event_b, us->sock, EV_WRITE, handle_udp_send_stage2, task);
    add_event_mapping(task, ev);
    event_add(ev, NULL);
}

static
void
handle_host_resolve_stage2(int result, char type, int count, int ttl, void *addresses, void *arg)
{
    struct async_network_task_s *task = arg;

    if (result != DNS_ERR_NONE || count < 1) {
        trace_warning("%s, evdns returned code %d, count = %d (%s:%u)\n", __func__, result, count,
                      task->host, (unsigned int)task->port);
        ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0,
                                               PP_ERROR_NAME_NOT_RESOLVED, 0, __func__);
        task_destroy(task);
        return;
    }

    struct pp_host_resolver_s *hr = pp_resource_acquire(task->resource, PP_RESOURCE_HOST_RESOLVER);
    if (!hr) {
        trace_error("%s, bad resource\n", __func__);
        task_destroy(task);
        return;
    }

    hr->addr_count = count;
    hr->addrs = calloc(count, sizeof(struct PP_NetAddress_Private));

    if (type == DNS_IPv4_A) {
        struct in_addr *ipv4_addrs = addresses;

        for (int k = 0; k < count; k ++) {
            struct sockaddr_in sai = {
                .sin_family = AF_INET,
                .sin_port =   htons(task->port),
            };

            memcpy(&sai.sin_addr, &ipv4_addrs[k], sizeof(struct in_addr));

            hr->addrs[k].size = sizeof(struct sockaddr_in);
            memcpy(hr->addrs[k].data, &sai, sizeof(sai));
        }

        ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0, PP_OK, 0,
                                               __func__);

    } else if (type == DNS_IPv6_AAAA) {
        struct in6_addr *ipv6_addrs = addresses;

        for (int k = 0; k < count; k ++) {
            struct sockaddr_in6 sai6 = {
                .sin6_family = AF_INET6,
                .sin6_port =   htons(task->port),
            };

            memcpy(&sai6.sin6_addr, &ipv6_addrs[k], sizeof(struct in6_addr));

            hr->addrs[k].size = sizeof(struct sockaddr_in6);
            memcpy(hr->addrs[k].data, &sai6, sizeof(sai6));
        }

        ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0, PP_OK, 0,
                                               __func__);

    } else {
        trace_error("%s, bad evdns type %d (%s:%u)\n", __func__, type, task->host,
                    (unsigned int)task->port);
        ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0,
                                               PP_ERROR_FAILED, 0, __func__);

    }

    pp_resource_release(task->resource);
    task_destroy(task);
}

static
void
handle_host_resolve_stage1(struct async_network_task_s *task)
{
    struct evdns_request *req;

    // queue DNS request
    req = evdns_base_resolve_ipv4(evdns_b, task->host, DNS_QUERY_NO_SEARCH,
                                  handle_host_resolve_stage2, task);
    // TODO: what about ipv6?

    if (!req) {
        trace_warning("%s, early dns resolution failure (%s:%u)\n", __func__, task->host,
                      (unsigned int)task->port);
        ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0,
                                               PP_ERROR_NAME_NOT_RESOLVED, 0, __func__);
        task_destroy(task);
        return;
    }
}

static
void *
network_worker_thread(void *param)
{
    event_base_dispatch(event_b);
    event_base_free(event_b);
    trace_error("%s, thread terminated\n", __func__);
    return NULL;
}
Ejemplo n.º 15
0
void
IghtConnectionState::handle_resolve(int result, char type, int count,
    int ttl, void *addresses, void *opaque)
{
	auto self = (IghtConnectionState *) opaque;
	const char *_family;
	const char *p;
	int error, family, size;
	char string[128];

	(void) ttl;

	ight_info("handle_resolve - enter");

	if (!self->connecting)
		abort();

	if (self->closing) {
		delete (self);
		return;
	}

	if (result != DNS_ERR_NONE)
		goto finally;

	switch (type) {
	case DNS_IPv4_A:
		ight_info("handle_resolve - IPv4");
		family = PF_INET;
		_family = "PF_INET";
		size = 4;
		break;
	case DNS_IPv6_AAAA:
		ight_info("handle_resolve - IPv6");
		family = PF_INET6;
		_family = "PF_INET6";
		size = 16;
		break;
	default:
		abort();
	}

	while (--count >= 0) {
		if (count > INT_MAX / size) {
			continue;
		}
		// Note: address already in network byte order
		p = inet_ntop(family, (char *)addresses + count * size,
		    string, sizeof (string));
		if (p == NULL) {
			ight_warn("handle_resolve - inet_ntop() failed");
			continue;
		}
		ight_info("handle_resolve - address %s", p);
		error = self->addrlist->append(string);
		if (error != 0) {
			ight_warn("handle_resolve - cannot append");
			continue;
		}
		ight_info("handle_resolve - family %s", _family);
		error = self->pflist->append(_family);
		if (error != 0) {
			ight_warn("handle_resolve - cannot append");
			// Oops the two vectors are not in sync anymore now
			self->connecting = 0;
			self->on_error(IghtError(-3));
			return;
		}
	}

    finally:
	auto dns_base = ight_get_global_evdns_base();

	if (self->must_resolve_ipv6) {
		self->must_resolve_ipv6 = 0;
		evdns_request *request = evdns_base_resolve_ipv6(dns_base,
		    self->address, DNS_QUERY_NO_SEARCH, self->handle_resolve,
		    self);
		if (request != NULL)
			return;
		/* FALLTHROUGH */
	}
	if (self->must_resolve_ipv4) {
		self->must_resolve_ipv4 = 0;
		evdns_request *request = evdns_base_resolve_ipv4(dns_base,
		    self->address, DNS_QUERY_NO_SEARCH, self->handle_resolve,
		    self);
		if (request != NULL)
			return;
		/* FALLTHROUGH */
	}
	self->connect_next();
}
Ejemplo n.º 16
0
void
IghtConnectionState::resolve(IghtConnectionState *self)
{
	struct sockaddr_storage storage;
	int result;

	if (!self->connecting)
		abort();

	if (self->closing) {
		delete (self);
		return;
	}

	// If self->address is a valid IPv4 address, connect directly
	memset(&storage, 0, sizeof (storage));
	result = inet_pton(PF_INET, self->address, &storage);
	if (result == 1) {
		ight_info("resolve - address %s", self->address);
		ight_info("resolve - family PF_INET");
		if (self->addrlist->append(self->address) != 0 ||
		    self->pflist->append("PF_INET") != 0) {
			ight_warn("resolve - cannot append");
			self->connecting = 0;
			self->on_error(IghtError(-4));
			return;
		}
		self->connect_next();
		return;
	}

	// If self->address is a valid IPv6 address, connect directly
	memset(&storage, 0, sizeof (storage));
	result = inet_pton(PF_INET6, self->address, &storage);
	if (result == 1) {
		ight_info("resolve - address %s", self->address);
		ight_info("resolve - family PF_INET6");
		if (self->addrlist->append(self->address) != 0 ||
		    self->pflist->append("PF_INET6") != 0) {
			ight_warn("resolve - cannot append");
			self->connecting = 0;
			self->on_error(IghtError(-4));
			return;
		}
		self->connect_next();
		return;
	}

	auto dns_base = ight_get_global_evdns_base();

	// Note: PF_UNSPEC6 means that we try with IPv6 first
	if (strcmp(self->family, "PF_INET") == 0)
		self->must_resolve_ipv4 = 1;
	else if (strcmp(self->family, "PF_INET6") == 0)
		self->must_resolve_ipv6 = 1;
	else if (strcmp(self->family, "PF_UNSPEC") == 0)
		self->must_resolve_ipv4 = 1;
	else if (strcmp(self->family, "PF_UNSPEC6") == 0)
		self->must_resolve_ipv6 = 1;
	else {
		ight_warn("connection::resolve - invalid PF_xxx");
		self->connecting = 0;
		self->on_error(IghtError(-5));
		return;
	}

	evdns_request *request;

	if (self->must_resolve_ipv4) {
		self->must_resolve_ipv4 = 0;
		request = evdns_base_resolve_ipv4(dns_base, self->address,
		    DNS_QUERY_NO_SEARCH, self->handle_resolve, self);
	} else {
		self->must_resolve_ipv6 = 0;
		request = evdns_base_resolve_ipv6(dns_base, self->address,
		    DNS_QUERY_NO_SEARCH, self->handle_resolve, self);
	}
	if (request == NULL) {
		self->connecting = 0;
		self->on_error(IghtError(-6));
		return;
	}

	// Arrange for the next resolve operation that we will need
	if (strcmp(self->family, "PF_UNSPEC") == 0)
		self->must_resolve_ipv6 = 1;
	else if (strcmp(self->family, "PF_UNSPEC6") == 0)
		self->must_resolve_ipv4 = 1;
}
Ejemplo n.º 17
0
static void irc_reconnectcb(int fd, short type, void *arg) {
	printf("Reconnecting...\n");
	Server *s = (Server *)arg;
	DEBUGF(evdns_base_resolve_ipv4(s->client->dnsbase, s->host, 0, irc_dnscb, arg));
}