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); }
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); }