コード例 #1
0
int
main(int argc, char **argv)
{
	asyncns_t *asyncns;
	asyncns_query_t *query;
	struct addrinfo *result;
	struct pollfd pollfd = { .events = POLLIN };
	int status;

	asyncns = asyncns_new(10);
	assert(asyncns);
	assert(asyncns_getnqueries(asyncns) == 0);
	assert(asyncns_getnext(asyncns) == NULL);

	pollfd.fd = asyncns_fd(asyncns);
	assert(pollfd.fd > 2);

	query = asyncns_getaddrinfo(asyncns, "127.0.0.1", NULL, NULL);
	assert(query);
	assert(asyncns_getnqueries(asyncns) == 1);
	assert(asyncns_getnext(asyncns) == NULL);

	asyncns_cancel(asyncns, query);
	query = NULL;
	assert(asyncns_getnqueries(asyncns) == 0);
	assert(asyncns_getnext(asyncns) == NULL);

	query = asyncns_getaddrinfo(asyncns, "127.0.0.1", NULL, NULL);
	assert(query);
	assert(asyncns_getnqueries(asyncns) == 1);
	assert(asyncns_getnext(asyncns) == NULL);

	usleep(100000);
	status = poll(&pollfd, 1, 0);
	assert(status == 1);
	status = asyncns_wait(asyncns, 0);
	assert(status == 0);
	assert(asyncns_isdone(asyncns, query));
	assert(asyncns_getnqueries(asyncns) == 1);
	assert(asyncns_getnext(asyncns) == query);

	status = poll(&pollfd, 1, 100);
	assert(status == 0);

	status = asyncns_getaddrinfo_done(asyncns, query, &result);
	assert(asyncns_getnqueries(asyncns) == 0);

	/* Intuitively, this should not be needed but the docs state that
	 * a call to `asyncns_wait()` is necessary so that `asyncns_getnext()`
	 * provides meaningful results.
	 */
	status = asyncns_wait(asyncns, 0);
	assert(status == 0);

	/* There were two queries issued, one of which has been cancelled
	 * and the other has been freed afterwards. As none of them can be
	 * returned, the only meaningful result of `asyncns_getnext()` is
	 * NULL.
	 */
	assert(asyncns_getnext(asyncns) == NULL);

	asyncns_free(asyncns);
	asyncns_freeaddrinfo(result);

	return EXIT_SUCCESS;
}
コード例 #2
0
static void server_resolve_cb(EV_P_ ev_io *w, int revents)
{
    int err;
    struct addrinfo *result, *rp;
    struct listen_ctx *listen_ctx = (struct listen_ctx *)w;
    asyncns_t *asyncns = listen_ctx->asyncns;

    err = asyncns_handle(asyncns);
    if (err == ASYNCNS_HANDLE_AGAIN)
    {
        // try again
        return;
    }
    else if (err == ASYNCNS_HANDLE_ERROR)
    {
        // asyncns error
        FATAL("asyncns exit unexpectedly.");
    }

    asyncns_query_t *query = asyncns_getnext(asyncns);
    struct server *server= (struct server*) asyncns_getuserdata(asyncns, query);

    if (!asyncns_isdone(asyncns, query))
    {
        // wait for reolver
        return;
    }

    server->query = NULL;

    if (verbose)
    {
        LOGD("asyncns resolved.");
    }

    err = asyncns_getaddrinfo_done(asyncns, query, &result);

    if (err)
    {
        ERROR("getaddrinfo");
        close_and_free_server(EV_A_ server);
    }
    else
    {
        // Use IPV4 address if possible
        for (rp = result; rp != NULL; rp = rp->ai_next)
        {
            if (rp->ai_family == AF_INET) break;
        }

        if (rp == NULL)
        {
            rp = result;
        }

        struct remote *remote = connect_to_remote(rp, server->listen_ctx->iface);

        if (remote == NULL)
        {
            LOGE("connect error.");
            close_and_free_server(EV_A_ server);
        }
        else
        {
            server->remote = remote;
            remote->server = server;

            // XXX: should handel buffer carefully
            if (server->buf_len > 0)
            {
                memcpy(remote->buf, server->buf + server->buf_idx, server->buf_len);
                remote->buf_len = server->buf_len;
                remote->buf_idx = 0;
                server->buf_len = 0;
                server->buf_idx = 0;
            }

            // listen to remote connected event
            ev_io_start(EV_A_ &remote->send_ctx->io);
        }
    }

    // release addrinfo
    asyncns_freeaddrinfo(result);
}
コード例 #3
0
static void query_resolve_cb(EV_P_ ev_io *w, int revents)
{
    int err;
    struct addrinfo *result, *rp;
    struct resolve_ctx *resolve_ctx = (struct resolve_ctx *)w;
    asyncns_t *asyncns = resolve_ctx->asyncns;

    err = asyncns_handle(asyncns);
    if (err == ASYNCNS_HANDLE_AGAIN) {
        // try again
        return;
    } else if (err == ASYNCNS_HANDLE_ERROR) {
        // asyncns error
        FATAL("[udp] asyncns exit unexpectedly.");
    }

    asyncns_query_t *query = asyncns_getnext(asyncns);
    struct query_ctx *query_ctx = (struct query_ctx *)asyncns_getuserdata(
        asyncns, query);

    if (!asyncns_isdone(asyncns, query)) {
        // wait reolver
        return;
    }

    if (verbose) {
        LOGD("[udp] asyncns resolved.");
    }

    query_ctx->query = NULL;

    err = asyncns_getaddrinfo_done(asyncns, query, &result);

    if (err) {
        ERROR("[udp] asysncns_getaddrinfo");
    } else {
        // Use IPV4 address if possible
        for (rp = result; rp != NULL; rp = rp->ai_next) {
            if (rp->ai_family == AF_INET) {
                break;
            }
        }

        if (rp == NULL) {
            rp = result;
        }

        int remotefd = create_remote_socket(rp->ai_family == AF_INET6);
        if (remotefd != -1) {
            setnonblocking(remotefd);
#ifdef SO_BROADCAST
            set_broadcast(remotefd);
#endif
#ifdef SO_NOSIGPIPE
            set_nosigpipe(remotefd);
#endif
#ifdef SET_INTERFACE
            if (query_ctx->server_ctx->iface) {
                setinterface(remotefd, query_ctx->server_ctx->iface);
            }
#endif

            struct remote_ctx *remote_ctx = new_remote(remotefd,
                                                       query_ctx->server_ctx);
            remote_ctx->src_addr = query_ctx->src_addr;
            remote_ctx->dst_addr = *((struct sockaddr_storage *)rp->ai_addr);
            remote_ctx->server_ctx = query_ctx->server_ctx;
            remote_ctx->addr_header_len = query_ctx->addr_header_len;
            memcpy(remote_ctx->addr_header, query_ctx->addr_header,
                   query_ctx->addr_header_len);

            size_t addr_len = sizeof(struct sockaddr_in);
            if (remote_ctx->dst_addr.ss_family == AF_INET6) {
                addr_len = sizeof(struct sockaddr_in6);
            }
            int s = sendto(remote_ctx->fd, query_ctx->buf, query_ctx->buf_len,
                           0, (struct sockaddr *)&remote_ctx->dst_addr,
                           addr_len);

            if (s == -1) {
                ERROR("[udp] sendto_remote");
                close_and_free_remote(EV_A_ remote_ctx);
            } else {
                // Add to conn cache
                char *key = hash_key(remote_ctx->addr_header,
                                     remote_ctx->addr_header_len,
                                     &remote_ctx->src_addr);
                cache_insert(query_ctx->server_ctx->conn_cache, key,
                             (void *)remote_ctx);

                ev_io_start(EV_A_ & remote_ctx->io);
            }

        } else {
            ERROR("[udp] bind() error..");
        }
    }

    // clean up
    asyncns_freeaddrinfo(result);
    close_and_free_query(EV_A_ query_ctx);
}