⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 request.c

📁 bind-3.2.
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * 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 + -