support multiple simultaneous clients by creating new
client objects in place of busy ones, in preparation for client quotas
This commit is contained in:
@@ -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
|
||||
***/
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user