support multiple simultaneous clients by creating new

client objects in place of busy ones, in preparation for client quotas
This commit is contained in:
Andreas Gustafsson
2000-01-07 19:20:25 +00:00
parent 73a1e6a5d1
commit 08d93839d7
2 changed files with 71 additions and 1 deletions

View File

@@ -106,6 +106,13 @@ maybe_free(ns_client_t *client) {
isc_boolean_t need_clientmgr_destroy = ISC_FALSE;
REQUIRE(NS_CLIENT_VALID(client));
/*
* When "shuttingdown" is true, either the task has received
* its shutdown event or no shutdown event has ever been
* set up. Thus, we have no outstanding shutdown
* event at this point.
*/
REQUIRE(client->shuttingdown == ISC_TRUE);
if (client->naccepts > 0)
@@ -224,8 +231,16 @@ ns_client_next(ns_client_t *client, isc_result_t result) {
dns_rdataset_disassociate(client->opt);
dns_message_puttemprdataset(client->message, &client->opt);
}
client->udpsize = 512;
dns_message_reset(client->message, DNS_MESSAGE_INTENTPARSE);
if (client->oneshot) {
/* XXX should put in "idle client pool" instead. */
isc_task_shutdown(client->task);
return;
}
if (client->dispevent != NULL) {
dns_dispatch_freeevent(client->dispatch, client->dispentry,
&client->dispevent);
@@ -672,6 +687,9 @@ client_request(isc_task_t *task, isc_event_t *event) {
}
if (ra == ISC_TRUE)
client->attributes |= NS_CLIENTATTR_RA;
/* XXX conditionally */
(void) ns_client_replace(client);
/*
* Dispatch the request.
@@ -791,6 +809,7 @@ client_create(ns_clientmgr_t *manager, ns_clienttype_t type,
client->udpsize = 512;
client->next = NULL;
dns_name_init(&client->signername, NULL);
client->oneshot = ISC_FALSE;
ISC_LINK_INIT(client, link);
/*
@@ -855,7 +874,7 @@ client_newconn(isc_task_t *task, isc_event_t *event) {
INSIST(client->naccepts == 1);
client->naccepts--;
if (client->shuttingdown) {
maybe_free(client);
} else if (nevent->result == ISC_R_SUCCESS) {
@@ -864,6 +883,15 @@ client_newconn(isc_task_t *task, isc_event_t *event) {
dns_tcpmsg_init(client->mctx, client->tcpsocket,
&client->tcpmsg);
client->tcpmsg_valid = ISC_TRUE;
/*
* Let a new client take our place immediately, before
* we wait for a request packet. If we don't,
* telnetting to port 35 (once per CPU) will
* deny service to legititmate TCP clients.
*/
(void) ns_client_replace(client);
client_read(client);
} else {
/*
@@ -923,6 +951,31 @@ ns_client_unwait(ns_client_t *client) {
maybe_free(client);
}
isc_result_t
ns_client_replace(ns_client_t *client) {
isc_result_t result;
CTRACE("replace");
/* XXX Check quota here. */
if (TCP_CLIENT(client)) {
result = ns_clientmgr_accepttcp(client->manager, client->tcplistener, 1);
} else {
result = ns_clientmgr_addtodispatch(client->manager, 1, client->dispatch);
}
if (result != ISC_R_SUCCESS)
return (result);
/*
* The new client is ready to listen for new requests, so we
* should refrain from doing so.
*/
client->oneshot = ISC_TRUE;
return (ISC_R_SUCCESS);
}
/***
*** Client Manager
***/

View File

@@ -69,6 +69,7 @@ struct ns_client {
isc_stdtime_t now;
dns_name_t signername; /* [T]SIG key name */
dns_name_t * signer; /* NULL if not valid sig */
isc_boolean_t oneshot;
ISC_LINK(struct ns_client) link;
};
@@ -106,9 +107,25 @@ ns_client_shuttingdown(ns_client_t *client);
void
ns_client_wait(ns_client_t *client);
/*
* Increment reference count.
*/
void
ns_client_unwait(ns_client_t *client);
/*
* Decrement reference count.
*/
isc_result_t
ns_client_replace(ns_client_t *client);
/*
* Try to replace the current client with a new one, so that the
* current one can go off and do some lengthy work without
* leaving the dispatch/socket without service.
*
* If doing so would exceed a quota, return ISC_R_QUOTA.
*/
isc_result_t
ns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,