📄 request.c
字号:
goto unlink; } req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: request %p", request); *requestp = request; return (ISC_R_SUCCESS); unlink: LOCK(&requestmgr->lock); ISC_LIST_UNLINK(requestmgr->requests, request, link); UNLOCK(&requestmgr->lock); cleanup: if (tclone != NULL) isc_task_detach(&tclone); req_destroy(request); req_log(ISC_LOG_DEBUG(3), "dns_request_createvia: failed %s", dns_result_totext(result)); return (result);}static isc_result_treq_render(dns_message_t *message, isc_buffer_t **bufferp, unsigned int options, isc_mem_t *mctx){ isc_buffer_t *buf1 = NULL; isc_buffer_t *buf2 = NULL; isc_result_t result; isc_region_t r; isc_boolean_t tcp = ISC_FALSE; dns_compress_t cctx; isc_boolean_t cleanup_cctx = ISC_FALSE; REQUIRE(bufferp != NULL && *bufferp == NULL); req_log(ISC_LOG_DEBUG(3), "request_render"); /* * Create buffer able to hold largest possible message. */ result = isc_buffer_allocate(mctx, &buf1, 65535); if (result != ISC_R_SUCCESS) return (result); result = dns_compress_init(&cctx, -1, mctx); if (result != ISC_R_SUCCESS) return (result); cleanup_cctx = ISC_TRUE; /* * Render message. */ result = dns_message_renderbegin(message, &cctx, buf1); if (result != ISC_R_SUCCESS) goto cleanup; result = dns_message_rendersection(message, DNS_SECTION_QUESTION, 0); if (result != ISC_R_SUCCESS) goto cleanup; result = dns_message_rendersection(message, DNS_SECTION_ANSWER, 0); if (result != ISC_R_SUCCESS) goto cleanup; result = dns_message_rendersection(message, DNS_SECTION_AUTHORITY, 0); if (result != ISC_R_SUCCESS) goto cleanup; result = dns_message_rendersection(message, DNS_SECTION_ADDITIONAL, 0); if (result != ISC_R_SUCCESS) goto cleanup; result = dns_message_renderend(message); if (result != ISC_R_SUCCESS) goto cleanup; dns_compress_invalidate(&cctx); cleanup_cctx = ISC_FALSE; /* * Copy rendered message to exact sized buffer. */ isc_buffer_usedregion(buf1, &r); if ((options & DNS_REQUESTOPT_TCP) != 0) { tcp = ISC_TRUE; } else if (r.length > 512) { result = DNS_R_USETCP; goto cleanup; } result = isc_buffer_allocate(mctx, &buf2, r.length + (tcp ? 2 : 0)); if (result != ISC_R_SUCCESS) goto cleanup; if (tcp) isc_buffer_putuint16(buf2, (isc_uint16_t)r.length); result = isc_buffer_copyregion(buf2, &r); if (result != ISC_R_SUCCESS) goto cleanup; /* * Cleanup and return. */ isc_buffer_free(&buf1); *bufferp = buf2; return (ISC_R_SUCCESS); cleanup: dns_message_renderreset(message); if (buf1 != NULL) isc_buffer_free(&buf1); if (buf2 != NULL) isc_buffer_free(&buf2); if (cleanup_cctx) dns_compress_invalidate(&cctx); return (result);}/* * If this request is no longer waiting for events, * send the completion event. This will ultimately * cause the request to be destroyed. * * Requires: * 'request' is locked by the caller. */static voidsend_if_done(dns_request_t *request, isc_result_t result) { if (!DNS_REQUEST_CONNECTING(request) && !DNS_REQUEST_SENDING(request) && !request->canceling) req_sendevent(request, result);}/* * Handle the control event. */static voiddo_cancel(isc_task_t *task, isc_event_t *event) { dns_request_t *request = event->ev_arg; UNUSED(task); INSIST(event->ev_type == DNS_EVENT_REQUESTCONTROL); LOCK(&request->requestmgr->locks[request->hash]); request->canceling = ISC_FALSE; if (!DNS_REQUEST_CANCELED(request)) req_cancel(request); send_if_done(request, ISC_R_CANCELED); UNLOCK(&request->requestmgr->locks[request->hash]); }isc_result_tdns_request_cancel(dns_request_t *request) { REQUIRE(VALID_REQUEST(request)); req_log(ISC_LOG_DEBUG(3), "dns_request_cancel: request %p", request); REQUIRE(VALID_REQUEST(request)); LOCK(&request->requestmgr->locks[request->hash]); if (!request->canceling && !DNS_REQUEST_CANCELED(request)) { isc_event_t *ev = &request->ctlevent; isc_task_send(request->event->ev_sender, &ev); request->canceling = ISC_TRUE; } UNLOCK(&request->requestmgr->locks[request->hash]); return (ISC_R_SUCCESS);}isc_result_tdns_request_getresponse(dns_request_t *request, dns_message_t *message, unsigned int options){ isc_result_t result; REQUIRE(VALID_REQUEST(request)); REQUIRE(request->answer != NULL); req_log(ISC_LOG_DEBUG(3), "dns_request_getresponse: request %p", request); dns_message_setquerytsig(message, request->tsig); dns_message_settsigkey(message, request->tsigkey); result = dns_message_parse(message, request->answer, options); if (result != ISC_R_SUCCESS) return (result); if (request->tsigkey != NULL) result = dns_tsig_verify(request->answer, message, NULL, NULL); return (result);}isc_boolean_tdns_request_usedtcp(dns_request_t *request) { REQUIRE(VALID_REQUEST(request)); return (ISC_TF((request->flags & DNS_REQUEST_F_TCP) != 0));}voiddns_request_destroy(dns_request_t **requestp) { dns_request_t *request; REQUIRE(requestp != NULL && VALID_REQUEST(*requestp)); request = *requestp; req_log(ISC_LOG_DEBUG(3), "dns_request_destroy: request %p", request); LOCK(&request->requestmgr->lock); LOCK(&request->requestmgr->locks[request->hash]); ISC_LIST_UNLINK(request->requestmgr->requests, request, link); INSIST(!DNS_REQUEST_CONNECTING(request)); INSIST(!DNS_REQUEST_SENDING(request)); UNLOCK(&request->requestmgr->locks[request->hash]); UNLOCK(&request->requestmgr->lock); /* * These should have been cleaned up by req_cancel() before * the completion event was sent. */ INSIST(!ISC_LINK_LINKED(request, link)); INSIST(request->dispentry == NULL); INSIST(request->dispatch == NULL); INSIST(request->timer == NULL); req_destroy(request); *requestp = NULL;}/*** *** Private: request. ***/static voidreq_connected(isc_task_t *task, isc_event_t *event) { isc_socketevent_t *sevent = (isc_socketevent_t *)event; isc_result_t result; dns_request_t *request = event->ev_arg; REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT); REQUIRE(VALID_REQUEST(request)); REQUIRE(DNS_REQUEST_CONNECTING(request)); req_log(ISC_LOG_DEBUG(3), "req_connected: request %p", request); LOCK(&request->requestmgr->locks[request->hash]); request->flags &= ~DNS_REQUEST_F_CONNECTING; if (DNS_REQUEST_CANCELED(request)) { /* * Send delayed event. */ if (DNS_REQUEST_TIMEDOUT(request)) send_if_done(request, ISC_R_TIMEDOUT); else send_if_done(request, ISC_R_CANCELED); } else { dns_dispatch_starttcp(request->dispatch); result = sevent->result; if (result == ISC_R_SUCCESS) result = req_send(request, task, NULL); if (result != ISC_R_SUCCESS) { req_cancel(request); send_if_done(request, ISC_R_CANCELED); } } UNLOCK(&request->requestmgr->locks[request->hash]); isc_event_free(&event);}static voidreq_senddone(isc_task_t *task, isc_event_t *event) { isc_socketevent_t *sevent = (isc_socketevent_t *)event; dns_request_t *request = event->ev_arg; REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE); REQUIRE(VALID_REQUEST(request)); REQUIRE(DNS_REQUEST_SENDING(request)); req_log(ISC_LOG_DEBUG(3), "req_senddone: request %p", request); UNUSED(task); LOCK(&request->requestmgr->locks[request->hash]); request->flags &= ~DNS_REQUEST_F_SENDING; if (DNS_REQUEST_CANCELED(request)) { /* * Send delayed event. */ if (DNS_REQUEST_TIMEDOUT(request)) send_if_done(request, ISC_R_TIMEDOUT); else send_if_done(request, ISC_R_CANCELED); } else if (sevent->result != ISC_R_SUCCESS) { req_cancel(request); send_if_done(request, ISC_R_CANCELED); } UNLOCK(&request->requestmgr->locks[request->hash]); isc_event_free(&event);}static voidreq_response(isc_task_t *task, isc_event_t *event) { isc_result_t result; dns_request_t *request = event->ev_arg; dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event; isc_region_t r; REQUIRE(VALID_REQUEST(request)); REQUIRE(event->ev_type == DNS_EVENT_DISPATCH); UNUSED(task); req_log(ISC_LOG_DEBUG(3), "req_response: request %p: %s", request, dns_result_totext(devent->result)); LOCK(&request->requestmgr->locks[request->hash]); result = devent->result; if (result != ISC_R_SUCCESS) goto done; /* * Copy buffer to request. */ isc_buffer_usedregion(&devent->buffer, &r); result = isc_buffer_allocate(request->mctx, &request->answer, r.length); if (result != ISC_R_SUCCESS) goto done; result = isc_buffer_copyregion(request->answer, &r); if (result != ISC_R_SUCCESS) isc_buffer_free(&request->answer); done: /* * Cleanup. */ dns_dispatch_removeresponse(&request->dispentry, &devent); req_cancel(request); /* * Send completion event. */ send_if_done(request, result); UNLOCK(&request->requestmgr->locks[request->hash]);}static voidreq_timeout(isc_task_t *task, isc_event_t *event) { dns_request_t *request = event->ev_arg; REQUIRE(VALID_REQUEST(request)); req_log(ISC_LOG_DEBUG(3), "req_timeout: request %p", request); UNUSED(task); LOCK(&request->requestmgr->locks[request->hash]); request->flags |= DNS_REQUEST_F_TIMEDOUT; req_cancel(request); send_if_done(request, ISC_R_TIMEDOUT); UNLOCK(&request->requestmgr->locks[request->hash]); isc_event_free(&event);}static voidreq_sendevent(dns_request_t *request, isc_result_t result) { isc_task_t *task; REQUIRE(VALID_REQUEST(request)); req_log(ISC_LOG_DEBUG(3), "req_sendevent: request %p", request); /* * Lock held by caller. */ task = request->event->ev_sender; request->event->ev_sender = request; request->event->result = result; isc_task_sendanddetach(&task, (isc_event_t **)&request->event);}static voidreq_destroy(dns_request_t *request) { isc_mem_t *mctx; REQUIRE(VALID_REQUEST(request)); req_log(ISC_LOG_DEBUG(3), "req_destroy: request %p", request); request->magic = 0; if (request->query != NULL) isc_buffer_free(&request->query); if (request->answer != NULL) isc_buffer_free(&request->answer); if (request->event != NULL) isc_event_free((isc_event_t **)&request->event); if (request->dispentry != NULL) dns_dispatch_removeresponse(&request->dispentry, NULL); if (request->dispatch != NULL) dns_dispatch_detach(&request->dispatch); if (request->timer != NULL) isc_timer_detach(&request->timer); if (request->tsig != NULL) isc_buffer_free(&request->tsig); if (request->tsigkey != NULL) dns_tsigkey_detach(&request->tsigkey); if (request->requestmgr != NULL) requestmgr_detach(&request->requestmgr); mctx = request->mctx; isc_mem_put(mctx, request, sizeof(*request)); isc_mem_detach(&mctx);}/* * Stop the current request. Must be called from the request's task. */static voidreq_cancel(dns_request_t *request) { isc_socket_t *socket; REQUIRE(VALID_REQUEST(request)); req_log(ISC_LOG_DEBUG(3), "req_cancel: request %p", request); /* * Lock held by caller. */ request->flags |= DNS_REQUEST_F_CANCELED; if (request->timer != NULL) isc_timer_detach(&request->timer); if (request->dispentry != NULL) dns_dispatch_removeresponse(&request->dispentry, NULL); if (DNS_REQUEST_CONNECTING(request)) { socket = dns_dispatch_getsocket(request->dispatch); isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_CONNECT); } if (DNS_REQUEST_SENDING(request)) { socket = dns_dispatch_getsocket(request->dispatch); isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_SEND); } dns_dispatch_detach(&request->dispatch);}static voidreq_log(int level, const char *fmt, ...) { va_list ap; va_start(ap, fmt); isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_REQUEST, level, fmt, ap); va_end(ap);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -