unsigned int state;
ISC_LIST(dns_dispatch_t) list;
- /* locked by buffer_lock */
dns_qid_t *qid;
in_port_t *v4ports; /*%< available ports for IPv4 */
isc_nmhandle_t *handle; /*%< netmgr handle for UDP connection */
unsigned int bucket;
unsigned int timeout;
+ unsigned int retries;
isc_sockaddr_t local;
isc_sockaddr_t peer;
in_port_t port;
ISC_LINK(dns_dispentry_t) link;
ISC_LINK(dns_dispentry_t) alink;
ISC_LINK(dns_dispentry_t) plink;
+ ISC_LINK(dns_dispentry_t) rlink;
};
/*%
isc_refcount_t references;
unsigned int shutdown_out : 1;
- ISC_LIST(dns_dispentry_t) pending;
- ISC_LIST(dns_dispentry_t) active;
+ dns_displist_t pending;
+ dns_displist_t active;
unsigned int nsockets;
unsigned int requests; /*%< how many requests we have */
in_port_t *ports = NULL;
in_port_t port;
+ if (resp->retries++ > 5) {
+ return (ISC_R_FAILURE);
+ }
+
if (isc_sockaddr_pf(&disp->local) == AF_INET) {
nports = mgr->nv4ports;
ports = mgr->v4ports;
ISC_LIST_UNLINK(disp->active, resp, alink);
}
- if (ISC_LINK_LINKED(resp, plink)) {
- ISC_LIST_UNLINK(disp->pending, resp, plink);
- }
-
if (resp->handle != NULL) {
INSIST(disp->socktype == isc_socktype_udp);
resp->magic = 0;
+ if (ISC_LINK_LINKED(resp, plink)) {
+ ISC_LIST_UNLINK(disp->pending, resp, plink);
+ }
+
+ INSIST(!ISC_LINK_LINKED(resp, alink));
+ INSIST(!ISC_LINK_LINKED(resp, rlink));
+
if (resp->handle != NULL) {
isc_nmhandle_detach(&resp->handle);
}
* if event queue is not empty, queue. else, send.
* restart.
*/
-
-/* FIXME: If we read invalid packet, we never receive next that could be valid
- * and we also don't notify the read callback
- */
-
static void
udp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
void *arg) {
LOCK(&disp->lock);
- if (isc_log_wouldlog(dns_lctx, LVL(90))) {
- dispatch_log(disp, LVL(90), "got UDP packet: requests %d",
- disp->requests);
+ dispatch_log(disp, LVL(90), "UDP response %p:%s:requests %d", resp,
+ isc_result_totext(eresult), disp->requests);
+
+ /*
+ * The resp may have been deactivated by shutdown; if
+ * so, we can skip the response callback.
+ */
+ if (ISC_LINK_LINKED(resp, alink)) {
+ response = resp->response;
}
- if (eresult == ISC_R_CANCELED) {
+ if (eresult != ISC_R_SUCCESS) {
/*
- * This dispatcher is shutting down.
+ * This is most likely a network error on a connected
+ * socket, a timeout, or the query has been canceled.
+ * It makes no sense to check the address or parse the
+ * packet, but we can return the error to the caller.
*/
- goto sendevent;
- }
-
- if (!ISC_LINK_LINKED(resp, alink)) {
- goto unlock;
+ goto done;
}
- id = resp->id;
+ INSIST(ISC_LINK_LINKED(resp, alink));
peer = isc_nmhandle_peeraddr(handle);
isc_netaddr_fromsockaddr(&netaddr, &peer);
- if (eresult != ISC_R_SUCCESS) {
- /*
- * This is most likely a network error on a connected
- * socket, or a timeout on a timer that has not been
- * reset. It makes no sense to check the address or
- * parse the packet, but it will help to return the
- * error to the caller.
- */
- goto sendevent;
- }
-
/*
* If this is from a blackholed address, drop it.
*/
dispatch_log(disp, LVL(10), "blackholed packet from %s",
netaddrstr);
}
- goto unlock;
+ goto next;
}
/*
* Peek into the buffer to see what we can see.
*/
+ id = resp->id;
isc_buffer_init(&source, region->base, region->length);
isc_buffer_add(&source, region->length);
dres = dns_message_peekheader(&source, &id, &flags);
if (dres != ISC_R_SUCCESS) {
dispatch_log(disp, LVL(10), "got garbage packet");
- goto unlock;
+ goto next;
}
dispatch_log(disp, LVL(92),
(((flags & DNS_MESSAGEFLAG_QR) != 0) ? '1' : '0'), id);
/*
- * Look at flags. If query, drop it. If response,
- * look to see where it goes.
+ * Look at the message flags. If it's a query, ignore it.
*/
if ((flags & DNS_MESSAGEFLAG_QR) == 0) {
- /* query */
- goto unlock;
+ goto next;
}
/*
if (resp->id != id || !isc_sockaddr_equal(&peer, &resp->peer)) {
dispatch_log(disp, LVL(90), "response doesn't match");
inc_stats(disp->mgr, dns_resstatscounter_mismatch);
- goto unlock;
+ goto next;
}
-sendevent:
/*
- * At this point, rev contains the event we want to fill in, and
- * resp contains the information on the place to send it to.
- * Send the event off.
+ * We have the right resp, so call the caller back.
*/
+ goto done;
- response = resp->response;
+next:
+ /*
+ * This is the wrong response. Don't call the caller back
+ * but keep listening.
+ */
+ response = NULL;
+ dispatch_getnext(disp, resp, resp->timeout);
-unlock:
+done:
UNLOCK(&disp->lock);
if (response != NULL) {
tcp_recv(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
void *arg) {
dns_dispatch_t *disp = (dns_dispatch_t *)arg;
- dns_dispentry_t *resp = NULL;
+ dns_dispentry_t *resp = NULL, *next = NULL;
dns_messageid_t id;
isc_result_t dres;
unsigned int flags;
char buf[ISC_SOCKADDR_FORMATSIZE];
isc_buffer_t source;
isc_sockaddr_t peer;
+ dns_displist_t resps;
REQUIRE(VALID_DISPATCH(disp));
LOCK(&disp->lock);
- dispatch_log(disp, LVL(90), "got TCP packet: requests %d, buffers %d",
- disp->requests, disp->tcpbuffers);
+ dispatch_log(disp, LVL(90), "TCP read:%s:requests %d, buffers %d",
+ isc_result_totext(eresult), disp->requests,
+ disp->tcpbuffers);
peer = isc_nmhandle_peeraddr(handle);
+ ISC_LIST_INIT(resps);
switch (eresult) {
case ISC_R_SUCCESS:
/* got our answer */
break;
- case ISC_R_CANCELED:
- dispatch_log(disp, LVL(90), "shutting down on cancel");
- goto unlock;
+ case ISC_R_SHUTTINGDOWN:
+ case ISC_R_CANCELED:
case ISC_R_EOF:
- dispatch_log(disp, LVL(90), "shutting down on EOF");
- goto unlock;
+ dispatch_log(disp, LVL(90), "shutting down: %s",
+ isc_result_totext(eresult));
+ /*
+ * If there are any active responses, shut them all down.
+ */
+ for (resp = ISC_LIST_HEAD(disp->active); resp != NULL;
+ resp = next) {
+ next = ISC_LIST_NEXT(resp, alink);
+ dispentry_attach(resp, &(dns_dispentry_t *){ NULL });
+ ISC_LIST_UNLINK(disp->active, resp, alink);
+ ISC_LIST_APPEND(resps, resp, rlink);
+ }
+ goto done;
case ISC_R_TIMEDOUT:
/*
- * Time out the first active response for which
- * no event has already been sent.
+ * Time out the oldest response in the active queue,
+ * and move it to the end. (We don't remove it from the
+ * active queue immediately, though, because the callback
+ * might decide to keep waiting and leave it active.)
*/
resp = ISC_LIST_HEAD(disp->active);
- INSIST(resp != NULL);
-
- ISC_LIST_UNLINK(disp->active, resp, alink);
- ISC_LIST_APPEND(disp->active, resp, alink);
-
- goto unlock;
+ if (resp != NULL) {
+ dispentry_attach(resp, &(dns_dispentry_t *){ NULL });
+ ISC_LIST_UNLINK(disp->active, resp, alink);
+ ISC_LIST_APPEND(disp->active, resp, alink);
+ }
+ goto done;
default:
if (eresult == ISC_R_CONNECTIONRESET) {
"shutting down due to TCP "
"receive error: %s: %s",
buf, isc_result_totext(eresult));
- goto unlock;
+ goto done;
}
- dispatch_log(disp, LVL(90), "result %d, length == %d, addr = %p",
- eresult, region->length, region->base);
+ dispatch_log(disp, LVL(90), "success, length == %d, addr = %p",
+ region->length, region->base);
/*
* Peek into the buffer to see what we can see.
(((flags & DNS_MESSAGEFLAG_QR) != 0) ? '1' : '0'), id);
/*
- * Allocate an event to send to the query or response client, and
- * allocate a new buffer for our use.
- */
-
- /*
- * Look at flags. If query, drop it. If response,
- * look to see where it goes.
+ * Look at the message flags. If it's a query, ignore it
+ * and keep reading.
*/
if ((flags & DNS_MESSAGEFLAG_QR) == 0) {
/*
}
/*
- * We have a response; find the associated dispentry.
+ * We have a valid response; find the associated dispentry object
+ * and call the caller back.
*/
bucket = dns_hash(qid, &peer, id, disp->localport);
LOCK(&qid->lock);
resp = entry_search(qid, &peer, id, disp->localport, bucket);
+ if (resp != NULL) {
+ dispentry_attach(resp, &(dns_dispentry_t *){ NULL });
+ }
dispatch_log(disp, LVL(90), "search for response in bucket %d: %s",
bucket, (resp == NULL ? "not found" : "found"));
UNLOCK(&qid->lock);
next:
- /* Restart the reading from the TCP socket */
- dispatch_getnext(disp, resp, -1);
+ dispatch_getnext(disp, NULL, -1);
-unlock:
+done:
UNLOCK(&disp->lock);
if (resp != NULL) {
+ /* We got a matching response, or timed out */
resp->response(eresult, region, resp->arg);
+ dispentry_detach(&resp);
+ } else {
+ /* We're being shut down; cancel all outstanding resps */
+ for (resp = ISC_LIST_HEAD(resps); resp != NULL; resp = next) {
+ next = ISC_LIST_NEXT(resp, rlink);
+ ISC_LIST_UNLINK(resps, resp, rlink);
+ resp->response(ISC_R_SHUTTINGDOWN, region, resp->arg);
+ dispentry_detach(&resp);
+ }
}
dns_dispatch_detach(&disp);
ISC_LIST_APPEND(mgr->list, disp, link);
UNLOCK(&mgr->lock);
- if (isc_log_wouldlog(dns_lctx, 90)) {
- mgr_log(mgr, LVL(90),
- "dns_dispatch_createtcp: created TCP dispatch %p",
- disp);
- }
+ mgr_log(mgr, LVL(90), "dns_dispatch_createtcp: created TCP dispatch %p",
+ disp);
*dispp = disp;
return (ISC_R_SUCCESS);
dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr,
const isc_sockaddr_t *localaddr, bool *connected,
dns_dispatch_t **dispp) {
- dns_dispatch_t *disp = NULL;
+ dns_dispatch_t *disp_connected = NULL;
+ dns_dispatch_t *disp_fallback = NULL;
+ isc_result_t result = ISC_R_NOTFOUND;
REQUIRE(VALID_DISPATCHMGR(mgr));
REQUIRE(destaddr != NULL);
REQUIRE(connected != NULL);
REQUIRE(dispp != NULL && *dispp == NULL);
- /* First pass, look for connected TCP dispatches */
- *connected = true;
-
LOCK(&mgr->lock);
-again:
- for (disp = ISC_LIST_HEAD(mgr->list); disp != NULL && *dispp == NULL;
+
+ for (dns_dispatch_t *disp = ISC_LIST_HEAD(mgr->list); disp != NULL;
disp = ISC_LIST_NEXT(disp, link))
{
isc_sockaddr_t sockname;
peeraddr = disp->peer;
}
- if (*connected == true &&
- atomic_load(&disp->state) != DNS_DISPATCHSTATE_CONNECTED)
- {
- goto unlock;
- }
-
- /* We don't reuse UDP sockets */
- if (disp->socktype != isc_socktype_tcp) {
- goto unlock;
- }
-
- /* Different destination address */
- if (!isc_sockaddr_equal(destaddr, &peeraddr)) {
- goto unlock;
- }
-
- /* Different local addr */
- if (localaddr != NULL) {
- /* FIXME: This is weird as sockname == disp-local */
- if (!isc_sockaddr_eqaddr(localaddr, &disp->local) ||
- !isc_sockaddr_eqaddr(localaddr, &sockname))
- {
- goto unlock;
- }
- }
-
/*
* The conditions match:
* 1. socktype is TCP
* 2. destination address is same
* 3. local address is either NULL or same
*/
- dns_dispatch_attach(disp, dispp);
- unlock:
+ if (disp->socktype == isc_socktype_tcp &&
+ isc_sockaddr_equal(destaddr, &peeraddr) &&
+ (localaddr == NULL ||
+ isc_sockaddr_eqaddr(localaddr, &sockname)))
+ {
+ if (atomic_load(&disp->state) ==
+ DNS_DISPATCHSTATE_CONNECTED) {
+ /* We found connected dispatch */
+ disp_connected = disp;
+ UNLOCK(&disp->lock);
+ break;
+ }
+
+ /* We found "a" dispatch, store it for later */
+ if (disp_fallback == NULL) {
+ disp_fallback = disp;
+ }
+
+ UNLOCK(&disp->lock);
+ continue;
+ }
+
UNLOCK(&disp->lock);
}
- if (*dispp != NULL) {
- UNLOCK(&mgr->lock);
- return (ISC_R_SUCCESS);
- }
+ if (disp_connected != NULL) {
+ /* We found connected dispatch */
+ INSIST(disp_connected->handle != NULL);
- if (*connected) {
- /* Second pass, look also for not-yet-connected dispatch */
+ *connected = true;
+ dns_dispatch_attach(disp_connected, dispp);
+
+ result = ISC_R_SUCCESS;
+ } else if (disp_fallback != NULL) {
+ /* We found matching dispatch */
*connected = false;
- goto again;
+
+ dns_dispatch_attach(disp_fallback, dispp);
+
+ result = ISC_R_SUCCESS;
}
UNLOCK(&mgr->lock);
- return (ISC_R_NOTFOUND);
+
+ return (result);
}
isc_result_t
ISC_LINK_INIT(res, link);
ISC_LINK_INIT(res, alink);
ISC_LINK_INIT(res, plink);
+ ISC_LINK_INIT(res, rlink);
if (disp->socktype == isc_socktype_udp) {
isc_result_t result = setup_socket(disp, res, dest, &localport);
switch (disp->socktype) {
case isc_socktype_udp:
dispentry_attach(resp, &(dns_dispentry_t *){ NULL });
-
if (timeout > 0) {
isc_nmhandle_settimeout(resp->handle, timeout);
}
isc_nm_read(resp->handle, udp_recv, resp);
-
break;
+
case isc_socktype_tcp:
dns_dispatch_attach(disp, &(dns_dispatch_t *){ NULL });
-
if (timeout > 0) {
isc_nmhandle_settimeout(disp->handle, timeout);
}
isc_nm_read(disp->handle, tcp_recv, disp);
break;
+
default:
INSIST(0);
ISC_UNREACHABLE();
REQUIRE(VALID_RESPONSE(resp));
disp = resp->disp;
+
REQUIRE(VALID_DISPATCH(disp));
LOCK(&disp->lock);
-
dispatch_getnext(disp, resp, resp->timeout);
-
UNLOCK(&disp->lock);
-
return (ISC_R_SUCCESS);
}
break;
case isc_socktype_tcp:
- REQUIRE(resp != NULL && resp->handle == NULL);
- REQUIRE(disp != NULL && disp->handle == NULL);
+ REQUIRE(disp != NULL);
+ LOCK(&disp->lock);
+ REQUIRE(disp->handle == NULL);
isc_nmhandle_attach(handle, &disp->handle);
dns_dispatch_attach(disp, &(dns_dispatch_t *){ NULL });
isc_nm_read(disp->handle, tcp_recv, disp);
+ UNLOCK(&disp->lock);
+
break;
default:
}
}
-/*
- * FIXME: Split into tcp_connected() and udp_connected()
- */
-
static void
-disp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
- dns_dispentry_t *resp = (dns_dispentry_t *)arg;
- dns_dispentry_t *pending = NULL, *next = NULL;
- dns_dispatch_t *disp = resp->disp;
+tcp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
+ dns_dispatch_t *disp = (dns_dispatch_t *)arg;
+ dns_dispentry_t *resp = NULL, *next = NULL;
+ dns_displist_t resps;
+
+ dispatch_log(disp, LVL(90), "TCP connected (%p): %s", disp,
+ isc_result_totext(eresult));
+
+ ISC_LIST_INIT(resps);
+
+ if (MGR_IS_SHUTTINGDOWN(disp->mgr)) {
+ eresult = ISC_R_SHUTTINGDOWN;
+ }
if (eresult == ISC_R_SUCCESS) {
- if (resp->canceled) {
- dispentry_detach(&resp);
- return;
- }
+ REQUIRE(atomic_compare_exchange_strong(
+ &disp->state,
+ &(uint_fast32_t){ DNS_DISPATCHSTATE_CONNECTING },
+ DNS_DISPATCHSTATE_CONNECTED));
+ startrecv(handle, disp, NULL);
+ }
- if (disp->socktype == isc_socktype_tcp) {
- REQUIRE(atomic_compare_exchange_strong(
- &disp->state,
- &(uint_fast32_t){ DNS_DISPATCHSTATE_CONNECTING },
- DNS_DISPATCHSTATE_CONNECTED));
- }
+ /*
+ * If there are pending responses, call the connect
+ * callbacks for all of them.
+ */
+ LOCK(&disp->lock);
+ for (resp = ISC_LIST_HEAD(disp->pending); resp != NULL; resp = next) {
+ next = ISC_LIST_NEXT(resp, plink);
+ ISC_LIST_UNLINK(disp->pending, resp, plink);
+ ISC_LIST_APPEND(resps, resp, plink);
+ }
+ UNLOCK(&disp->lock);
- startrecv(handle, disp, resp);
+ for (resp = ISC_LIST_HEAD(resps); resp != NULL; resp = next) {
+ next = ISC_LIST_NEXT(resp, plink);
+ ISC_LIST_UNLINK(resps, resp, plink);
+
+ if (resp->connected != NULL) {
+ resp->connected(eresult, NULL, resp->arg);
+ }
+ dispentry_detach(&resp);
}
+ dns_dispatch_detach(&disp);
+}
+
+static void
+udp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
+ dns_dispentry_t *resp = (dns_dispentry_t *)arg;
+ dns_dispatch_t *disp = resp->disp;
+
+ dispatch_log(disp, LVL(90), "UDP connected (%p): %s", resp,
+ isc_result_totext(eresult));
+
if (MGR_IS_SHUTTINGDOWN(disp->mgr)) {
eresult = ISC_R_SHUTTINGDOWN;
}
- if (resp->connected != NULL) {
- resp->connected(eresult, NULL, resp->arg);
+ if (eresult == ISC_R_SUCCESS && resp->canceled) {
+ eresult = ISC_R_CANCELED;
+ } else if (eresult == ISC_R_SUCCESS) {
+ startrecv(handle, disp, resp);
+ } else if (eresult == ISC_R_ADDRINUSE) {
+ in_port_t localport = 0;
+ isc_result_t result;
+
+ /* probably a port collision; try a different one */
+ disp->nsockets--;
+ result = setup_socket(disp, resp, &resp->peer, &localport);
+ if (result == ISC_R_SUCCESS) {
+ dns_dispatch_connect(resp);
+ goto detach;
+ }
}
- for (pending = ISC_LIST_HEAD(disp->pending); pending != NULL;
- pending = next) {
- next = ISC_LIST_NEXT(pending, plink);
- ISC_LIST_UNLINK(disp->pending, pending, plink);
-
- if (pending->connected != NULL) {
- pending->connected(eresult, NULL, pending->arg);
- }
- dispentry_detach(&pending);
+ if (resp->connected != NULL) {
+ resp->connected(eresult, NULL, resp->arg);
}
+detach:
dispentry_detach(&resp);
}
disp = resp->disp;
- /* This will be detached in disp_connected() */
+ /* This will be detached once we've connected. */
dispentry_attach(resp, &(dns_dispentry_t *){ NULL });
switch (disp->socktype) {
case isc_socktype_tcp:
/*
- * Check whether the dispatch was already connecting.
- * If so, add resp to the pending responses.
+ * Check whether the dispatch is already connecting
+ * or connected.
*/
atomic_compare_exchange_strong(&disp->state,
(uint_fast32_t *)&state,
DNS_DISPATCHSTATE_CONNECTING);
-
switch (state) {
case DNS_DISPATCHSTATE_NONE:
/* First connection, continue with connecting */
- INSIST(disp->handle == NULL);
+ LOCK(&disp->lock);
+ INSIST(ISC_LIST_EMPTY(disp->pending));
+ ISC_LIST_APPEND(disp->pending, resp, plink);
+ UNLOCK(&disp->lock);
+ dns_dispatch_attach(disp, &(dns_dispatch_t *){ NULL });
isc_nm_tcpdnsconnect(disp->mgr->nm, &disp->local,
- &disp->peer, disp_connected, resp,
+ &disp->peer, tcp_connected, disp,
resp->timeout, 0);
break;
+
case DNS_DISPATCHSTATE_CONNECTING:
+ /* Connection pending; add resp to the list */
+ LOCK(&disp->lock);
ISC_LIST_APPEND(disp->pending, resp, plink);
- return (ISC_R_SUCCESS);
+ UNLOCK(&disp->lock);
+ break;
+
case DNS_DISPATCHSTATE_CONNECTED:
- /* We are already connected, call the connected cb */
+ /* We are already connected; call the connected cb */
if (resp->connected != NULL) {
resp->connected(ISC_R_SUCCESS, NULL, resp->arg);
}
- return (ISC_R_SUCCESS);
+ dispentry_detach(&resp);
+ break;
+
default:
INSIST(0);
ISC_UNREACHABLE();
}
break;
+
case isc_socktype_udp:
isc_nm_udpconnect(disp->mgr->nm, &resp->local, &resp->peer,
- disp_connected, resp, resp->timeout, 0);
+ udp_connected, resp, resp->timeout, 0);
break;
+
default:
return (ISC_R_NOTIMPLEMENTED);
}
void
dns_dispatch_resume(dns_dispentry_t *resp, uint16_t timeout) {
dns_dispatch_t *disp = NULL;
+
REQUIRE(VALID_RESPONSE(resp));
disp = resp->disp;
resp->canceled = true;
- /* UDP case. */
+ /* Connected UDP */
if (resp->handle != NULL) {
isc_nm_cancelread(resp->handle);
return;
}
- /*
- * TCP case. We only want to cancel if this is the last resp
- * listening on this TCP connection.
- */
+ /* TCP pending connection. */
if (ISC_LINK_LINKED(resp, plink)) {
ISC_LIST_UNLINK(resp->disp->pending, resp, plink);
if (resp->connected != NULL) {
resp->connected(ISC_R_CANCELED, NULL, resp->arg);
+ dispentry_detach(&resp);
}
- } else if (ISC_LINK_LINKED(resp, alink)) {
+ return;
+ }
+
+ /*
+ * Connected TCP, or unconnected UDP.
+ *
+ * If TCP, we don't want to cancel the dispatch
+ * unless this is the last resp waiting.
+ */
+ if (ISC_LINK_LINKED(resp, alink)) {
ISC_LIST_UNLINK(resp->disp->active, resp, alink);
if (ISC_LIST_EMPTY(resp->disp->active) &&
resp->disp->handle != NULL) {
req_send(request);
req_detach(&rclone);
} else {
- result = dns_dispatch_connect(request->dispentry);
- if (result != ISC_R_SUCCESS) {
- goto unlink;
- }
request->flags |= DNS_REQUEST_F_CONNECTING;
-
if (tcp) {
request->flags |= DNS_REQUEST_F_TCP;
}
+
+ result = dns_dispatch_connect(request->dispentry);
+ if (result != ISC_R_SUCCESS) {
+ goto unlink;
+ }
}
req_log(ISC_LOG_DEBUG(3), "dns_request_createraw: request %p", request);
req_send(request);
req_detach(&rclone);
} else {
- result = dns_dispatch_connect(request->dispentry);
- if (result != ISC_R_SUCCESS) {
- goto unlink;
- }
request->flags |= DNS_REQUEST_F_CONNECTING;
if (tcp) {
request->flags |= DNS_REQUEST_F_TCP;
}
+
+ result = dns_dispatch_connect(request->dispentry);
+ if (result != ISC_R_SUCCESS) {
+ goto unlink;
+ }
}
req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: request %p", request);
void
request_cancel(dns_request_t *request) {
if (!DNS_REQUEST_CANCELED(request)) {
- req_log(ISC_LOG_DEBUG(3), "do_cancel: request %p", request);
+ req_log(ISC_LOG_DEBUG(3), "request_cancel: request %p",
+ request);
request->flags |= DNS_REQUEST_F_CANCELED;
request->flags &= ~DNS_REQUEST_F_CONNECTING;
req_detach(&request);
}
-/***
- *** Private: request.
- ***/
static void
req_connected(isc_result_t eresult, isc_region_t *region, void *arg) {
dns_request_t *request = (dns_request_t *)arg;
req_log(ISC_LOG_DEBUG(3), "req_connected: request %p: %s", request,
isc_result_totext(eresult));
- if (eresult == ISC_R_CANCELED) {
- req_detach(&request);
- return;
- }
-
REQUIRE(VALID_REQUEST(request));
- REQUIRE(DNS_REQUEST_CONNECTING(request));
+ REQUIRE(DNS_REQUEST_CONNECTING(request) ||
+ DNS_REQUEST_CANCELED(request));
LOCK(&request->requestmgr->locks[request->hash]);
request->flags &= ~DNS_REQUEST_F_CONNECTING;
req_response(isc_result_t result, isc_region_t *region, void *arg) {
dns_request_t *request = (dns_request_t *)arg;
- if (result == ISC_R_CANCELED) {
+ req_log(ISC_LOG_DEBUG(3), "req_response: request %p: %s", request,
+ dns_result_totext(result));
+
+ if (result == ISC_R_CANCELED || result == ISC_R_EOF) {
return;
}
if (result == ISC_R_TIMEDOUT) {
- req_log(ISC_LOG_DEBUG(3), "req_timeout: request %p", request);
-
LOCK(&request->requestmgr->locks[request->hash]);
if (--request->udpcount != 0) {
dns_dispatch_resume(request->dispentry,
REQUIRE(VALID_REQUEST(request));
- req_log(ISC_LOG_DEBUG(3), "req_response: request %p: %s", request,
- dns_result_totext(result));
-
LOCK(&request->requestmgr->locks[request->hash]);
if (result != ISC_R_SUCCESS) {
if (result != ISC_R_SUCCESS) {
isc_buffer_free(&request->answer);
}
+
done:
/*
* Cleanup.
*/
- dns_dispatch_removeresponse(&request->dispentry);
+ if (request->dispentry != NULL) {
+ dns_dispatch_removeresponse(&request->dispentry);
+ }
request_cancel(request);
/*
}
/*
- * Check for any outstanding dispatch responses. If they exist,
- * cancel them and let their callbacks finish the cleanup.
+ * Check for any outstanding dispatch responses and if they
+ * exist, cancel them.
*/
if (query->dispentry != NULL) {
dns_dispatch_cancel(query->dispentry);
switch (eresult) {
case ISC_R_SUCCESS:
+ case ISC_R_SHUTTINGDOWN:
goto detach;
case ISC_R_HOSTUNREACH:
FCTX_ATTR_CLR(fctx, FCTX_ATTR_ADDRWAIT);
fctx_try(fctx, true, false);
break;
+
case ISC_R_CANCELED:
break;
+
default:
FCTXTRACE3("query canceled in resquery_senddone() "
"due to unexpected result; responding",
}
goto detach;
+ case ISC_R_SHUTTINGDOWN:
+ FCTXTRACE3("shutdown in resquery_connected(): no response",
+ eresult);
+ fctx_cancelquery(query, NULL, true, false);
+ fctx_done(fctx, eresult, __LINE__);
+ break;
+
case ISC_R_NETUNREACH:
case ISC_R_HOSTUNREACH:
case ISC_R_CONNREFUSED:
fetchctx_t *fctx = NULL;
respctx_t rctx;
- if (eresult == ISC_R_CANCELED) {
+ if (eresult == ISC_R_CANCELED || eresult == ISC_R_EOF) {
return;
}
if (rctx->result == ISC_R_HOSTUNREACH ||
rctx->result == ISC_R_NETUNREACH ||
rctx->result == ISC_R_CONNREFUSED ||
- rctx->result == ISC_R_CANCELED)
+ rctx->result == ISC_R_CANCELED ||
+ rctx->result == ISC_R_SHUTTINGDOWN)
{
rctx->broken_server = rctx->result;
rctx->broken_type = badns_unreachable;
memmove(tmp, algorithms, *algorithms);
}
tmp[len - 1] |= mask;
- /* 'tmp[0]' should contain the length of 'tmp'.
- */
+ /* tmp[0] should contain the length of 'tmp'. */
*tmp = len;
node->data = tmp;
/* Free the older bitfield. */
AM_CPPFLAGS += \
$(LIBISC_CFLAGS) \
$(LIBDNS_CFLAGS) \
+ $(LIBUV_CFLAGS) \
$(KRB5_CFLAGS) \
-DSRCDIR=\"$(abs_srcdir)\" \
-DBUILDDIR=\"$(abs_builddir)\"
LDADD += \
libdnstest.la \
$(LIBISC_LIBS) \
+ $(LIBUV_LIBS) \
$(LIBDNS_LIBS)
check_LTLIBRARIES = libdnstest.la
#define UNIT_TESTING
#include <cmocka.h>
-#include <isc/app.h>
#include <isc/buffer.h>
#include <isc/managers.h>
#include <isc/refcount.h>
#include "dnstest.h"
+uv_sem_t sem;
+
/* Timeouts in miliseconds */
-#define T_INIT 120 * 1000
-#define T_IDLE 120 * 1000
-#define T_KEEPALIVE 120 * 1000
-#define T_ADVERTISED 120 * 1000
-#define T_CONNECT 30 * 1000
+#define T_SERVER_INIT 5000
+#define T_SERVER_IDLE 5000
+#define T_SERVER_KEEPALIVE 5000
+#define T_SERVER_ADVERTISED 5000
+
+#define T_CLIENT_INIT 2000
+#define T_CLIENT_IDLE 2000
+#define T_CLIENT_KEEPALIVE 2000
+#define T_CLIENT_ADVERTISED 2000
+
+#define T_CLIENT_CONNECT 1000
dns_dispatchmgr_t *dispatchmgr = NULL;
dns_dispatchset_t *dset = NULL;
isc_nm_t *connect_nm = NULL;
-static isc_sockaddr_t server_addr;
-static isc_sockaddr_t connect_addr;
+static isc_sockaddr_t udp_server_addr;
+static isc_sockaddr_t udp_connect_addr;
+static isc_sockaddr_t tcp_server_addr;
+static isc_sockaddr_t tcp_connect_addr;
+
+const struct in6_addr in6addr_blackhole = { { { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1 } } };
static int
setup_ephemeral_port(isc_sockaddr_t *addr, sa_family_t family) {
return (fd);
}
+static void
+reset_testdata(void);
+
static int
_setup(void **state) {
isc_result_t result;
uv_os_sock_t sock = -1;
+ int r;
UNUSED(state);
result = dns_test_begin(NULL, true);
assert_int_equal(result, ISC_R_SUCCESS);
- connect_addr = (isc_sockaddr_t){ .length = 0 };
- isc_sockaddr_fromin6(&connect_addr, &in6addr_loopback, 0);
+ udp_connect_addr = (isc_sockaddr_t){ .length = 0 };
+ isc_sockaddr_fromin6(&udp_connect_addr, &in6addr_loopback, 0);
+
+ tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
+ isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
- server_addr = (isc_sockaddr_t){ .length = 0 };
- sock = setup_ephemeral_port(&server_addr, SOCK_DGRAM);
+ udp_server_addr = (isc_sockaddr_t){ .length = 0 };
+ sock = setup_ephemeral_port(&udp_server_addr, SOCK_DGRAM);
+ if (sock < 0) {
+ return (-1);
+ }
+ close(sock);
+
+ tcp_server_addr = (isc_sockaddr_t){ .length = 0 };
+ sock = setup_ephemeral_port(&tcp_server_addr, SOCK_STREAM);
if (sock < 0) {
return (-1);
}
isc_managers_create(dt_mctx, ncpus, 0, 0, &connect_nm, NULL, NULL,
NULL);
- isc_nm_settimeouts(netmgr, T_INIT, T_IDLE, T_KEEPALIVE, T_ADVERTISED);
- isc_nm_settimeouts(connect_nm, T_INIT, T_IDLE, T_KEEPALIVE,
- T_ADVERTISED);
+ isc_nm_settimeouts(netmgr, T_SERVER_INIT, T_SERVER_IDLE,
+ T_SERVER_KEEPALIVE, T_SERVER_ADVERTISED);
+
+ /*
+ * Use shorter client-side timeouts, to ensure that clients
+ * time out before the server.
+ */
+ isc_nm_settimeouts(connect_nm, T_CLIENT_INIT, T_CLIENT_IDLE,
+ T_CLIENT_KEEPALIVE, T_CLIENT_ADVERTISED);
+
+ r = uv_sem_init(&sem, 0);
+ assert_int_equal(r, 0);
+
+ reset_testdata();
return (0);
}
_teardown(void **state) {
UNUSED(state);
+ uv_sem_destroy(&sem);
+
isc_managers_destroy(&connect_nm, NULL, NULL, NULL);
assert_null(connect_nm);
}
isc_sockaddr_any(&any);
- result = dns_dispatch_createudp(dispatchmgr, taskmgr, &any, 0, &disp);
+ result = dns_dispatch_createudp(dispatchmgr, &any, &disp);
if (result != ISC_R_SUCCESS) {
return (result);
}
- result = dns_dispatchset_create(dt_mctx, taskmgr, disp, &dset, ndisps);
+ result = dns_dispatchset_create(dt_mctx, disp, &dset, ndisps);
dns_dispatch_detach(&disp);
return (result);
}
struct {
- isc_nmhandle_t *handle;
atomic_uint_fast32_t responses;
+ atomic_uint_fast32_t result;
} testdata;
static dns_dispatch_t *dispatch = NULL;
static dns_dispentry_t *dispentry = NULL;
static atomic_bool first = ATOMIC_VAR_INIT(true);
+static void
+reset_testdata(void) {
+ atomic_init(&testdata.responses, 0);
+ atomic_init(&testdata.result, ISC_R_UNSET);
+}
+
static void
server_senddone(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) {
UNUSED(handle);
UNUSED(eresult);
UNUSED(cbarg);
+ fprintf(stderr, "%s(..., %s, ...)\n", __func__,
+ isc_result_totext(eresult));
+
return;
}
isc_nm_send(handle, &response, server_senddone, NULL);
}
+static isc_result_t
+accept_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) {
+ UNUSED(handle);
+ UNUSED(cbarg);
+
+ return (eresult);
+}
+
static void
-response(isc_task_t *task, isc_event_t *event) {
- dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event;
- bool exp_true = true;
+noop_nameserver(isc_nmhandle_t *handle, isc_result_t eresult,
+ isc_region_t *region, void *cbarg) {
+ UNUSED(handle);
+ UNUSED(eresult);
+ UNUSED(region);
+ UNUSED(cbarg);
+}
- UNUSED(task);
+static void
+response_getnext(isc_result_t result, isc_region_t *region, void *arg) {
+ UNUSED(region);
+ UNUSED(arg);
atomic_fetch_add_relaxed(&testdata.responses, 1);
- if (atomic_compare_exchange_strong(&first, &exp_true, false)) {
- isc_result_t result = dns_dispatch_getnext(dispentry, &devent);
+
+ if (atomic_compare_exchange_strong(&first, &(bool){ true }, false)) {
+ result = dns_dispatch_getnext(dispentry);
assert_int_equal(result, ISC_R_SUCCESS);
} else {
- dns_dispatch_removeresponse(&dispentry, &devent);
- isc_nmhandle_detach(&testdata.handle);
- isc_app_shutdown();
+ uv_sem_post(&sem);
}
}
static void
-connected(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) {
+response(isc_result_t eresult, isc_region_t *region, void *arg) {
+ UNUSED(region);
+ UNUSED(arg);
+
+ fprintf(stderr, "%s(..., %s, ...)\n", __func__,
+ isc_result_totext(eresult));
+
+ switch (eresult) {
+ case ISC_R_EOF:
+ case ISC_R_CANCELED:
+ case ISC_R_SHUTTINGDOWN:
+ break;
+ default:
+ atomic_fetch_add_relaxed(&testdata.responses, 1);
+ atomic_store_relaxed(&testdata.result, eresult);
+ }
+
+ uv_sem_post(&sem);
+}
+
+static void
+response_timeout(isc_result_t eresult, isc_region_t *region, void *arg) {
+ UNUSED(region);
+ UNUSED(arg);
+
+ fprintf(stderr, "%s(..., %s, ...)\n", __func__,
+ isc_result_totext(eresult));
+
+ atomic_store_relaxed(&testdata.result, eresult);
+
+ uv_sem_post(&sem);
+}
+
+static void
+connected(isc_result_t eresult, isc_region_t *region, void *cbarg) {
isc_region_t *r = (isc_region_t *)cbarg;
UNUSED(eresult);
+ UNUSED(region);
+
+ fprintf(stderr, "%s(..., %s, ...)\n", __func__,
+ isc_result_totext(eresult));
- isc_nmhandle_attach(handle, &testdata.handle);
dns_dispatch_send(dispentry, r, -1);
}
static void
-client_senddone(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) {
- UNUSED(handle);
+client_senddone(isc_result_t eresult, isc_region_t *region, void *cbarg) {
UNUSED(eresult);
+ UNUSED(region);
UNUSED(cbarg);
+ fprintf(stderr, "%s(..., %s, ...)\n", __func__,
+ isc_result_totext(eresult));
+
return;
}
static void
-startit(isc_task_t *task, isc_event_t *event) {
- UNUSED(task);
+timeout_connected(isc_result_t eresult, isc_region_t *region, void *cbarg) {
+ UNUSED(region);
+ UNUSED(cbarg);
+
+ fprintf(stderr, "%s(..., %s, ...)\n", __func__,
+ isc_result_totext(eresult));
+
+ atomic_store_relaxed(&testdata.result, eresult);
+
+ uv_sem_post(&sem);
+}
+
+static void
+dispatch_timeout_tcp_connect(void **state) {
+ isc_result_t result;
+ isc_region_t region;
+ unsigned char rbuf[12] = { 0 };
+ unsigned char message[12] = { 0 };
+ uint16_t id;
+
+ UNUSED(state);
+
+ tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
+ isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_blackhole, 0);
+
+ result = dns_dispatchmgr_create(dt_mctx, connect_nm, &dispatchmgr);
+ assert_int_equal(result, ISC_R_SUCCESS);
+
+ result = dns_dispatch_createtcp(dispatchmgr, &tcp_connect_addr,
+ &tcp_server_addr, -1, &dispatch);
+ assert_int_equal(result, ISC_R_SUCCESS);
+
+ region.base = rbuf;
+ region.length = sizeof(rbuf);
+
+ result = dns_dispatch_addresponse(dispatch, 0, T_CLIENT_CONNECT,
+ &tcp_server_addr, timeout_connected,
+ client_senddone, response, ®ion,
+ &id, &dispentry);
+ assert_int_equal(result, ISC_R_SUCCESS);
+
+ memset(message, 0, sizeof(message));
+ message[0] = (id >> 8) & 0xff;
+ message[1] = id & 0xff;
+
+ region.base = message;
+ region.length = sizeof(message);
+
dns_dispatch_connect(dispentry);
- isc_event_free(&event);
+
+ uv_sem_wait(&sem);
+
+ dns_dispatch_removeresponse(&dispentry);
+
+ dns_dispatch_detach(&dispatch);
+ dns_dispatchmgr_detach(&dispatchmgr);
+
+ /* Skip if the IPv6 is not available or not blackholed */
+
+ result = atomic_load_acquire(&testdata.result);
+ if (result == ISC_R_ADDRNOTAVAIL || result == ISC_R_CONNREFUSED) {
+ skip();
+ return;
+ }
+
+ assert_int_equal(result, ISC_R_TIMEDOUT);
}
-/* test dispatch getnext */
static void
-dispatch_getnext(void **state) {
+dispatch_timeout_tcp_response(void **state __attribute__((unused))) {
isc_result_t result;
isc_region_t region;
+ unsigned char rbuf[12] = { 0 };
+ unsigned char message[12] = { 0 };
+ uint16_t id;
isc_nmsocket_t *sock = NULL;
- isc_task_t *task = NULL;
- unsigned char message[12];
- unsigned char rbuf[12];
+
+ UNUSED(state);
+
+ tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
+ isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
+
+ result = dns_dispatchmgr_create(dt_mctx, connect_nm, &dispatchmgr);
+ assert_int_equal(result, ISC_R_SUCCESS);
+
+ result = dns_dispatch_createtcp(dispatchmgr, &tcp_connect_addr,
+ &tcp_server_addr, -1, &dispatch);
+ assert_int_equal(result, ISC_R_SUCCESS);
+
+ result = isc_nm_listentcpdns(netmgr, &tcp_server_addr, noop_nameserver,
+ NULL, accept_cb, NULL, 0, 0, NULL, &sock);
+ assert_int_equal(result, ISC_R_SUCCESS);
+
+ region.base = rbuf;
+ region.length = sizeof(rbuf);
+
+ result = dns_dispatch_addresponse(
+ dispatch, 0, T_CLIENT_CONNECT, &tcp_server_addr, connected,
+ client_senddone, response_timeout, ®ion, &id, &dispentry);
+ assert_int_equal(result, ISC_R_SUCCESS);
+
+ memset(message, 0, sizeof(message));
+ message[0] = (id >> 8) & 0xff;
+ message[1] = id & 0xff;
+
+ region.base = message;
+ region.length = sizeof(message);
+
+ dns_dispatch_connect(dispentry);
+
+ uv_sem_wait(&sem);
+
+ assert_int_equal(atomic_load_acquire(&testdata.result), ISC_R_TIMEDOUT);
+
+ isc_nm_stoplistening(sock);
+ isc_nmsocket_close(&sock);
+ assert_null(sock);
+
+ dns_dispatch_removeresponse(&dispentry);
+
+ dns_dispatch_detach(&dispatch);
+ dns_dispatchmgr_detach(&dispatchmgr);
+}
+
+static void
+dispatch_tcp_response(void **state __attribute__((unused))) {
+ isc_result_t result;
+ isc_region_t region;
+ unsigned char rbuf[12] = { 0 };
+ unsigned char message[12] = { 0 };
uint16_t id;
+ isc_nmsocket_t *sock = NULL;
UNUSED(state);
- testdata.handle = NULL;
- atomic_init(&testdata.responses, 0);
+ tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
+ isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
+
+ result = dns_dispatchmgr_create(dt_mctx, connect_nm, &dispatchmgr);
+ assert_int_equal(result, ISC_R_SUCCESS);
+
+ result = dns_dispatch_createtcp(dispatchmgr, &tcp_connect_addr,
+ &tcp_server_addr, -1, &dispatch);
+ assert_int_equal(result, ISC_R_SUCCESS);
+
+ result = isc_nm_listentcpdns(netmgr, &tcp_server_addr, nameserver, NULL,
+ accept_cb, NULL, 0, 0, NULL, &sock);
+ assert_int_equal(result, ISC_R_SUCCESS);
+
+ region.base = rbuf;
+ region.length = sizeof(rbuf);
+
+ result = dns_dispatch_addresponse(
+ dispatch, 0, T_CLIENT_CONNECT, &tcp_server_addr, connected,
+ client_senddone, response, ®ion, &id, &dispentry);
+ assert_int_equal(result, ISC_R_SUCCESS);
+
+ memset(message, 0, sizeof(message));
+ message[0] = (id >> 8) & 0xff;
+ message[1] = id & 0xff;
+
+ region.base = message;
+ region.length = sizeof(message);
+
+ dns_dispatch_connect(dispentry);
+
+ uv_sem_wait(&sem);
+
+ assert_in_range(atomic_load_acquire(&testdata.responses), 1, 2);
+ assert_int_equal(atomic_load_acquire(&testdata.result), ISC_R_SUCCESS);
+
+ /* Cleanup */
+
+ isc_nm_stoplistening(sock);
+ isc_nmsocket_close(&sock);
+ assert_null(sock);
+
+ dns_dispatch_removeresponse(&dispentry);
+
+ dns_dispatch_detach(&dispatch);
+ dns_dispatchmgr_detach(&dispatchmgr);
+}
+
+static void
+dispatch_timeout_udp_response(void **state __attribute__((unused))) {
+ isc_result_t result;
+ isc_region_t region;
+ unsigned char rbuf[12] = { 0 };
+ unsigned char message[12] = { 0 };
+ uint16_t id;
+ isc_nmsocket_t *sock = NULL;
+
+ UNUSED(state);
+
+ udp_connect_addr = (isc_sockaddr_t){ .length = 0 };
+ isc_sockaddr_fromin6(&udp_connect_addr, &in6addr_loopback, 0);
- result = isc_task_create(taskmgr, 0, &task);
+ result = dns_dispatchmgr_create(dt_mctx, connect_nm, &dispatchmgr);
assert_int_equal(result, ISC_R_SUCCESS);
+ result = dns_dispatch_createudp(dispatchmgr, &tcp_connect_addr,
+ &dispatch);
+ assert_int_equal(result, ISC_R_SUCCESS);
+
+ result = isc_nm_listenudp(netmgr, &udp_server_addr, noop_nameserver,
+ NULL, 0, &sock);
+ assert_int_equal(result, ISC_R_SUCCESS);
+
+ region.base = rbuf;
+ region.length = sizeof(rbuf);
+
+ result = dns_dispatch_addresponse(
+ dispatch, 0, T_CLIENT_CONNECT, &udp_server_addr, connected,
+ client_senddone, response_timeout, ®ion, &id, &dispentry);
+ assert_int_equal(result, ISC_R_SUCCESS);
+
+ memset(message, 0, sizeof(message));
+ message[0] = (id >> 8) & 0xff;
+ message[1] = id & 0xff;
+
+ region.base = message;
+ region.length = sizeof(message);
+
+ dns_dispatch_connect(dispentry);
+
+ uv_sem_wait(&sem);
+
+ assert_int_equal(atomic_load_acquire(&testdata.result), ISC_R_TIMEDOUT);
+
+ isc_nm_stoplistening(sock);
+ isc_nmsocket_close(&sock);
+ assert_null(sock);
+
+ dns_dispatch_removeresponse(&dispentry);
+
+ dns_dispatch_detach(&dispatch);
+ dns_dispatchmgr_detach(&dispatchmgr);
+}
+
+/* test dispatch getnext */
+static void
+dispatch_getnext(void **state) {
+ isc_result_t result;
+ isc_region_t region;
+ isc_nmsocket_t *sock = NULL;
+ unsigned char message[12] = { 0 };
+ unsigned char rbuf[12] = { 0 };
+ uint16_t id;
+
+ UNUSED(state);
+
result = dns_dispatchmgr_create(dt_mctx, connect_nm, &dispatchmgr);
assert_int_equal(result, ISC_R_SUCCESS);
- result = dns_dispatch_createudp(dispatchmgr, taskmgr, &connect_addr, 0,
+ result = dns_dispatch_createudp(dispatchmgr, &udp_connect_addr,
&dispatch);
assert_int_equal(result, ISC_R_SUCCESS);
/*
* Create a local udp nameserver on the loopback.
*/
- result = isc_nm_listenudp(netmgr, &server_addr, nameserver, NULL, 0,
+ result = isc_nm_listenudp(netmgr, &udp_server_addr, nameserver, NULL, 0,
&sock);
assert_int_equal(result, ISC_R_SUCCESS);
region.base = rbuf;
region.length = sizeof(rbuf);
result = dns_dispatch_addresponse(
- dispatch, 0, 10000, &server_addr, task, connected,
- client_senddone, response, NULL, ®ion, &id, &dispentry);
+ dispatch, 0, T_CLIENT_CONNECT, &udp_server_addr, connected,
+ client_senddone, response_getnext, ®ion, &id, &dispentry);
assert_int_equal(result, ISC_R_SUCCESS);
memset(message, 0, sizeof(message));
region.base = message;
region.length = sizeof(message);
- result = isc_app_onrun(dt_mctx, task, startit, NULL);
- assert_int_equal(result, ISC_R_SUCCESS);
+ dns_dispatch_connect(dispentry);
- result = isc_app_run();
- assert_int_equal(result, ISC_R_SUCCESS);
+ uv_sem_wait(&sem);
assert_int_equal(atomic_load_acquire(&testdata.responses), 2);
+ /* Cleanup */
isc_nm_stoplistening(sock);
isc_nmsocket_close(&sock);
assert_null(sock);
- /*
- * Shutdown nameserver.
- */
- isc_task_detach(&task);
-
- /*
- * Shutdown the dispatch.
- */
+ dns_dispatch_removeresponse(&dispentry);
dns_dispatch_detach(&dispatch);
dns_dispatchmgr_detach(&dispatchmgr);
}
int
main(void) {
const struct CMUnitTest tests[] = {
+ cmocka_unit_test_setup_teardown(dispatch_timeout_tcp_connect,
+ _setup, _teardown),
+ cmocka_unit_test_setup_teardown(dispatch_timeout_tcp_response,
+ _setup, _teardown),
+ cmocka_unit_test_setup_teardown(dispatch_tcp_response, _setup,
+ _teardown),
+ cmocka_unit_test_setup_teardown(dispatch_timeout_udp_response,
+ _setup, _teardown),
cmocka_unit_test_setup_teardown(dispatchset_create, _setup,
_teardown),
cmocka_unit_test_setup_teardown(dispatchset_get, _setup,
isc_taskmgr_t *taskmgr = NULL;
isc_task_t *maintask = NULL;
isc_timermgr_t *timermgr = NULL;
-isc_socketmgr_t *socketmgr = NULL;
dns_zonemgr_t *zonemgr = NULL;
bool app_running = false;
int ncpus;
isc_managers_destroy(netmgr == NULL ? NULL : &netmgr,
taskmgr == NULL ? NULL : &taskmgr,
- timermgr == NULL ? NULL : &timermgr,
- socketmgr == NULL ? NULL : &socketmgr);
+ timermgr == NULL ? NULL : &timermgr, NULL);
if (app_running) {
isc_app_finish();
ncpus = isc_os_ncpus();
isc_managers_create(dt_mctx, ncpus, 0, 0, &netmgr, &taskmgr, &timermgr,
- &socketmgr);
+ NULL);
CHECK(isc_task_create(taskmgr, 0, &maintask));
return (ISC_R_SUCCESS);
isc_result_t result;
REQUIRE(zonemgr == NULL);
- result = dns_zonemgr_create(dt_mctx, taskmgr, timermgr, socketmgr, NULL,
- &zonemgr);
+ result = dns_zonemgr_create(dt_mctx, taskmgr, timermgr, NULL, &zonemgr);
return (result);
}
extern isc_taskmgr_t *taskmgr;
extern isc_task_t *maintask;
extern isc_timermgr_t *timermgr;
-extern isc_socketmgr_t *socketmgr;
extern isc_nm_t *netmgr;
extern dns_zonemgr_t *zonemgr;
extern bool app_running;
assert_int_equal(result, ISC_R_SUCCESS);
isc_sockaddr_any(&local);
- result = dns_dispatch_createudp(dispatchmgr, taskmgr, &local, 0,
- &dispatch);
+ result = dns_dispatch_createudp(dispatchmgr, &local, &dispatch);
assert_int_equal(result, ISC_R_SUCCESS);
return (0);
UNUSED(state);
- result = dns_zonemgr_create(dt_mctx, taskmgr, timermgr, socketmgr, NULL,
+ result = dns_zonemgr_create(dt_mctx, taskmgr, timermgr, NULL,
&myzonemgr);
assert_int_equal(result, ISC_R_SUCCESS);
UNUSED(state);
- result = dns_zonemgr_create(dt_mctx, taskmgr, timermgr, socketmgr, NULL,
+ result = dns_zonemgr_create(dt_mctx, taskmgr, timermgr, NULL,
&myzonemgr);
assert_int_equal(result, ISC_R_SUCCESS);
UNUSED(state);
- result = dns_zonemgr_create(dt_mctx, taskmgr, timermgr, socketmgr, NULL,
+ result = dns_zonemgr_create(dt_mctx, taskmgr, timermgr, NULL,
&myzonemgr);
assert_int_equal(result, ISC_R_SUCCESS);
TIME_NOW(&now);
- result = dns_zonemgr_create(dt_mctx, taskmgr, timermgr, socketmgr, NULL,
+ result = dns_zonemgr_create(dt_mctx, taskmgr, timermgr, NULL,
&myzonemgr);
assert_int_equal(result, ISC_R_SUCCESS);
isc_result_t result;
REQUIRE(zonemgr == NULL);
- result = dns_zonemgr_create(mctx, taskmgr, timermgr, socketmgr, NULL,
- &zonemgr);
+ result = dns_zonemgr_create(mctx, taskmgr, timermgr, NULL, &zonemgr);
return (result);
}