Example #1
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);
}
Example #2
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);
}