📄 request.c
字号:
/* * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. *//* $Id: request.c,v 1.64.2.1 2001/08/31 02:07:11 marka Exp $ */#include <config.h>#include <isc/magic.h>#include <isc/mem.h>#include <isc/task.h>#include <isc/timer.h>#include <isc/util.h>#include <dns/acl.h>#include <dns/compress.h>#include <dns/dispatch.h>#include <dns/events.h>#include <dns/log.h>#include <dns/message.h>#include <dns/rdata.h>#include <dns/rdatastruct.h>#include <dns/request.h>#include <dns/result.h>#include <dns/tsig.h>#define REQUESTMGR_MAGIC ISC_MAGIC('R', 'q', 'u', 'M')#define VALID_REQUESTMGR(mgr) ISC_MAGIC_VALID(mgr, REQUESTMGR_MAGIC)#define REQUEST_MAGIC ISC_MAGIC('R', 'q', 'u', '!')#define VALID_REQUEST(request) ISC_MAGIC_VALID(request, REQUEST_MAGIC)typedef ISC_LIST(dns_request_t) dns_requestlist_t;#define DNS_REQUEST_NLOCKS 7struct dns_requestmgr { unsigned int magic; isc_mutex_t lock; isc_mem_t *mctx; /* locked */ isc_int32_t eref; isc_int32_t iref; isc_timermgr_t *timermgr; isc_socketmgr_t *socketmgr; isc_taskmgr_t *taskmgr; dns_dispatchmgr_t *dispatchmgr; dns_dispatch_t *dispatchv4; dns_dispatch_t *dispatchv6; isc_boolean_t exiting; isc_eventlist_t whenshutdown; unsigned int hash; isc_mutex_t locks[DNS_REQUEST_NLOCKS]; dns_requestlist_t requests;};struct dns_request { unsigned int magic; unsigned int hash; isc_mem_t *mctx; isc_int32_t flags; ISC_LINK(dns_request_t) link; isc_buffer_t *query; isc_buffer_t *answer; dns_requestevent_t *event; dns_dispatch_t *dispatch; dns_dispentry_t *dispentry; isc_timer_t *timer; dns_requestmgr_t *requestmgr; isc_buffer_t *tsig; dns_tsigkey_t *tsigkey; isc_event_t ctlevent; isc_boolean_t canceling; /* ctlevent outstanding */};#define DNS_REQUEST_F_CONNECTING 0x0001#define DNS_REQUEST_F_SENDING 0x0002#define DNS_REQUEST_F_CANCELED 0x0004 /* ctlevent received, or otherwise synchronously canceled */#define DNS_REQUEST_F_TIMEDOUT 0x0008 /* cancelled due to a timeout */#define DNS_REQUEST_F_TCP 0x0010 /* This request used TCP */#define DNS_REQUEST_CANCELED(r) \ (((r)->flags & DNS_REQUEST_F_CANCELED) != 0)#define DNS_REQUEST_CONNECTING(r) \ (((r)->flags & DNS_REQUEST_F_CONNECTING) != 0)#define DNS_REQUEST_SENDING(r) \ (((r)->flags & DNS_REQUEST_F_SENDING) != 0)#define DNS_REQUEST_TIMEDOUT(r) \ (((r)->flags & DNS_REQUEST_F_TIMEDOUT) != 0)/*** *** Forward ***/static void mgr_destroy(dns_requestmgr_t *requestmgr);static void mgr_shutdown(dns_requestmgr_t *requestmgr);static unsigned int mgr_gethash(dns_requestmgr_t *requestmgr);static void send_shutdown_events(dns_requestmgr_t *requestmgr);static isc_result_t req_render(dns_message_t *message, isc_buffer_t **buffer, unsigned int options, isc_mem_t *mctx);static void req_senddone(isc_task_t *task, isc_event_t *event);static void req_response(isc_task_t *task, isc_event_t *event);static void req_timeout(isc_task_t *task, isc_event_t *event);static void req_connected(isc_task_t *task, isc_event_t *event);static void req_sendevent(dns_request_t *request, isc_result_t result);static void req_cancel(dns_request_t *request);static void req_destroy(dns_request_t *request);static void req_log(int level, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);static void do_cancel(isc_task_t *task, isc_event_t *event);/*** *** Public ***/isc_result_tdns_requestmgr_create(isc_mem_t *mctx, isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr, isc_taskmgr_t *taskmgr, dns_dispatchmgr_t *dispatchmgr, dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6, dns_requestmgr_t **requestmgrp){ dns_requestmgr_t *requestmgr; isc_socket_t *socket; isc_result_t result; int i; req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create"); REQUIRE(requestmgrp != NULL && *requestmgrp == NULL); REQUIRE(timermgr != NULL); REQUIRE(socketmgr != NULL); REQUIRE(taskmgr != NULL); REQUIRE(dispatchmgr != NULL); if (dispatchv4 != NULL) { socket = dns_dispatch_getsocket(dispatchv4); REQUIRE(isc_socket_gettype(socket) == isc_sockettype_udp); } if (dispatchv6 != NULL) { socket = dns_dispatch_getsocket(dispatchv6); REQUIRE(isc_socket_gettype(socket) == isc_sockettype_udp); } requestmgr = isc_mem_get(mctx, sizeof(*requestmgr)); if (requestmgr == NULL) return (ISC_R_NOMEMORY); result = isc_mutex_init(&requestmgr->lock); if (result != ISC_R_SUCCESS) { isc_mem_put(mctx, requestmgr, sizeof(*requestmgr)); return (result); } for (i = 0; i < DNS_REQUEST_NLOCKS; i++) { result = isc_mutex_init(&requestmgr->locks[i]); if (result != ISC_R_SUCCESS) { while (--i >= 0) DESTROYLOCK(&requestmgr->locks[i]); DESTROYLOCK(&requestmgr->lock); isc_mem_put(mctx, requestmgr, sizeof(*requestmgr)); return (result); } } requestmgr->timermgr = timermgr; requestmgr->socketmgr = socketmgr; requestmgr->taskmgr = taskmgr; requestmgr->dispatchmgr = dispatchmgr; requestmgr->dispatchv4 = NULL; if (dispatchv4 != NULL) dns_dispatch_attach(dispatchv4, &requestmgr->dispatchv4); requestmgr->dispatchv6 = NULL; if (dispatchv6 != NULL) dns_dispatch_attach(dispatchv6, &requestmgr->dispatchv6); requestmgr->mctx = NULL; isc_mem_attach(mctx, &requestmgr->mctx); requestmgr->eref = 1; /* implict attach */ requestmgr->iref = 0; ISC_LIST_INIT(requestmgr->whenshutdown); ISC_LIST_INIT(requestmgr->requests); requestmgr->exiting = ISC_FALSE; requestmgr->hash = 0; requestmgr->magic = REQUESTMGR_MAGIC; req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create: %p", requestmgr); *requestmgrp = requestmgr; return (ISC_R_SUCCESS);}voiddns_requestmgr_whenshutdown(dns_requestmgr_t *requestmgr, isc_task_t *task, isc_event_t **eventp){ isc_task_t *clone; isc_event_t *event; req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_whenshutdown"); REQUIRE(VALID_REQUESTMGR(requestmgr)); REQUIRE(eventp != NULL); event = *eventp; *eventp = NULL; LOCK(&requestmgr->lock); if (requestmgr->exiting) { /* * We're already shutdown. Send the event. */ event->ev_sender = requestmgr; isc_task_send(task, &event); } else { clone = NULL; isc_task_attach(task, &clone); event->ev_sender = clone; ISC_LIST_APPEND(requestmgr->whenshutdown, event, ev_link); } UNLOCK(&requestmgr->lock);}voiddns_requestmgr_shutdown(dns_requestmgr_t *requestmgr) { REQUIRE(VALID_REQUESTMGR(requestmgr)); req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_shutdown: %p", requestmgr); LOCK(&requestmgr->lock); mgr_shutdown(requestmgr); UNLOCK(&requestmgr->lock);}static voidmgr_shutdown(dns_requestmgr_t *requestmgr) { dns_request_t *request; /* * Caller holds lock. */ if (!requestmgr->exiting) { requestmgr->exiting = ISC_TRUE; for (request = ISC_LIST_HEAD(requestmgr->requests); request != NULL; request = ISC_LIST_NEXT(request, link)) { dns_request_cancel(request); } if (requestmgr->iref == 0) { INSIST(ISC_LIST_EMPTY(requestmgr->requests)); send_shutdown_events(requestmgr); } }}static voidrequestmgr_attach(dns_requestmgr_t *source, dns_requestmgr_t **targetp) { /* * Locked by caller. */ REQUIRE(VALID_REQUESTMGR(source)); REQUIRE(targetp != NULL && *targetp == NULL); REQUIRE(!source->exiting); source->iref++; *targetp = source; req_log(ISC_LOG_DEBUG(3), "requestmgr_attach: %p: eref %d iref %d", source, source->eref, source->iref);}static voidrequestmgr_detach(dns_requestmgr_t **requestmgrp) { dns_requestmgr_t *requestmgr; isc_boolean_t need_destroy = ISC_FALSE; REQUIRE(requestmgrp != NULL); requestmgr = *requestmgrp; REQUIRE(VALID_REQUESTMGR(requestmgr)); *requestmgrp = NULL; LOCK(&requestmgr->lock); INSIST(requestmgr->iref > 0); requestmgr->iref--; req_log(ISC_LOG_DEBUG(3), "requestmgr_detach: %p: eref %d iref %d", requestmgr, requestmgr->eref, requestmgr->iref); if (requestmgr->iref == 0 && requestmgr->exiting) { INSIST(ISC_LIST_HEAD(requestmgr->requests) == NULL); send_shutdown_events(requestmgr); if (requestmgr->eref == 0) need_destroy = ISC_TRUE; } UNLOCK(&requestmgr->lock); if (need_destroy) mgr_destroy(requestmgr);}voiddns_requestmgr_attach(dns_requestmgr_t *source, dns_requestmgr_t **targetp) { REQUIRE(VALID_REQUESTMGR(source)); REQUIRE(targetp != NULL && *targetp == NULL); REQUIRE(!source->exiting); LOCK(&source->lock); source->eref++; *targetp = source; UNLOCK(&source->lock); req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_attach: %p: eref %d iref %d", source, source->eref, source->iref);}voiddns_requestmgr_detach(dns_requestmgr_t **requestmgrp) { dns_requestmgr_t *requestmgr; isc_boolean_t need_destroy = ISC_FALSE; REQUIRE(requestmgrp != NULL); requestmgr = *requestmgrp; REQUIRE(VALID_REQUESTMGR(requestmgr)); LOCK(&requestmgr->lock); INSIST(requestmgr->eref > 0); requestmgr->eref--; req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_detach: %p: eref %d iref %d", requestmgr, requestmgr->eref, requestmgr->iref); if (requestmgr->eref == 0 && requestmgr->iref == 0) { INSIST(requestmgr->exiting && ISC_LIST_HEAD(requestmgr->requests) == NULL); need_destroy = ISC_TRUE; } UNLOCK(&requestmgr->lock); if (need_destroy) mgr_destroy(requestmgr); *requestmgrp = NULL;}static voidsend_shutdown_events(dns_requestmgr_t *requestmgr) { isc_event_t *event, *next_event; isc_task_t *etask; req_log(ISC_LOG_DEBUG(3), "send_shutdown_events: %p", requestmgr); /* * Caller must be holding the manager lock. */ for (event = ISC_LIST_HEAD(requestmgr->whenshutdown); event != NULL; event = next_event) { next_event = ISC_LIST_NEXT(event, ev_link); ISC_LIST_UNLINK(requestmgr->whenshutdown, event, ev_link); etask = event->ev_sender; event->ev_sender = requestmgr; isc_task_sendanddetach(&etask, &event); }}static voidmgr_destroy(dns_requestmgr_t *requestmgr) { int i; isc_mem_t *mctx; req_log(ISC_LOG_DEBUG(3), "mgr_destroy"); REQUIRE(requestmgr->eref == 0); REQUIRE(requestmgr->iref == 0); DESTROYLOCK(&requestmgr->lock); for (i = 0; i < DNS_REQUEST_NLOCKS; i++) DESTROYLOCK(&requestmgr->locks[i]); if (requestmgr->dispatchv4 != NULL) dns_dispatch_detach(&requestmgr->dispatchv4); if (requestmgr->dispatchv6 != NULL) dns_dispatch_detach(&requestmgr->dispatchv6); requestmgr->magic = 0; mctx = requestmgr->mctx; isc_mem_put(mctx, requestmgr, sizeof *requestmgr); isc_mem_detach(&mctx);}static unsigned intmgr_gethash(dns_requestmgr_t *requestmgr) { req_log(ISC_LOG_DEBUG(3), "mgr_gethash"); /* * Locked by caller. */ requestmgr->hash++; return (requestmgr->hash % DNS_REQUEST_NLOCKS);}static inline isc_result_treq_send(dns_request_t *request, isc_task_t *task, isc_sockaddr_t *address) { isc_region_t r; isc_socket_t *socket; isc_result_t result; req_log(ISC_LOG_DEBUG(3), "req_send: request %p", request); REQUIRE(VALID_REQUEST(request)); socket = dns_dispatch_getsocket(request->dispatch); isc_buffer_usedregion(request->query, &r); result = isc_socket_sendto(socket, &r, task, req_senddone, request, address, NULL); if (result == ISC_R_SUCCESS) request->flags |= DNS_REQUEST_F_SENDING; return (result);}static isc_result_tnew_request(isc_mem_t *mctx, dns_request_t **requestp) { dns_request_t *request; request = isc_mem_get(mctx, sizeof(*request)); if (request == NULL) return (ISC_R_NOMEMORY); /* * Zero structure. */ request->magic = 0; request->mctx = NULL; request->flags = 0; ISC_LINK_INIT(request, link); request->query = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -