0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * Copyright (C) 2000, 2001, 2004, 2005, 2007, 2015, 2016 Internet Systems Consortium, Inc. ("ISC")
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * License, v. 2.0. If a copy of the MPL was not distributed with this
0c27b3fe77ac1d5094ba3521e8142d9e7973133fMark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
ec5347e2c775f027573ce5648b910361aa926c01Automatic Updater/* $Id: lwdclient.c,v 1.22 2007/06/18 23:47:18 tbox Exp $ */
4e96d1fc0646de4d879e7a0bc1e7aba449a67596Michael Graff#define SHUTTINGDOWN(cm) ((cm->flags & NS_LWDCLIENTMGR_FLAGSHUTTINGDOWN) != 0)
4e96d1fc0646de4d879e7a0bc1e7aba449a67596Michael Grafflwdclientmgr_shutdown_callback(isc_task_t *task, isc_event_t *ev);
9a6bbb206efa528373c31928ebd0b7216c747a13Brian Wellingtonns_lwdclient_log(int level, const char *format, ...) {
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellington DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ADB,
783055c0a61eba5f3a828d1b138155bae575eb14Brian Wellingtonns_lwdclientmgr_create(ns_lwreslistener_t *listener, unsigned int nclients,
4e96d1fc0646de4d879e7a0bc1e7aba449a67596Michael Graff unsigned int i;
4e96d1fc0646de4d879e7a0bc1e7aba449a67596Michael Graff cm = isc_mem_get(lwresd->mctx, sizeof(ns_lwdclientmgr_t));
783055c0a61eba5f3a828d1b138155bae575eb14Brian Wellington ns_lwreslistener_attach(listener, &cm->listener);
783055c0a61eba5f3a828d1b138155bae575eb14Brian Wellington isc_socket_attach(listener->sock, &cm->sock);
563878539af45d41143701a6d299e9b226937f5bMark Andrews result = lwres_context_create(&cm->lwctx, cm->mctx,
f1b68725503ff3e46001eee5a1751e29a43a09d1Andreas Gustafsson for (i = 0; i < nclients; i++) {
4e96d1fc0646de4d879e7a0bc1e7aba449a67596Michael Graff client = isc_mem_get(lwresd->mctx, sizeof(ns_lwdclient_t));
4e96d1fc0646de4d879e7a0bc1e7aba449a67596Michael Graff ns_lwdclient_log(50, "created client %p, manager %p",
4e96d1fc0646de4d879e7a0bc1e7aba449a67596Michael Graff * If we could create no clients, clean up and return.
783055c0a61eba5f3a828d1b138155bae575eb14Brian Wellington result = isc_task_create(taskmgr, 0, &cm->task);
4e96d1fc0646de4d879e7a0bc1e7aba449a67596Michael Graff * This MUST be last, since there is no way to cancel an onshutdown...
783055c0a61eba5f3a828d1b138155bae575eb14Brian Wellington result = isc_task_onshutdown(cm->task, lwdclientmgr_shutdown_callback,
2f734e0a7e518c89c2b2b179714b8885b7626b3aAndreas Gustafsson isc_mem_put(lwresd->mctx, client, sizeof(*client));
2f734e0a7e518c89c2b2b179714b8885b7626b3aAndreas Gustafsson isc_mem_put(lwresd->mctx, cm, sizeof(*cm));
563878539af45d41143701a6d299e9b226937f5bMark Andrews * Run through the idle list and free the clients there. Idle
4e96d1fc0646de4d879e7a0bc1e7aba449a67596Michael Graff * clients do not have a recv running nor do they have any finds
4e96d1fc0646de4d879e7a0bc1e7aba449a67596Michael Graff * or similar running.
4e96d1fc0646de4d879e7a0bc1e7aba449a67596Michael Graff ns_lwdclient_log(50, "destroying client %p, manager %p",
2f734e0a7e518c89c2b2b179714b8885b7626b3aAndreas Gustafsson isc_mem_put(cm->mctx, client, sizeof(*client));
4e96d1fc0646de4d879e7a0bc1e7aba449a67596Michael Graff ns_lwdclient_log(50, "destroying manager %p", cm);
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellington lwres_buffer_init(&b, client->buffer, client->recvlength);
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellington result = lwres_lwpacket_parseheader(&b, &client->pkt);
9a6bbb206efa528373c31928ebd0b7216c747a13Brian Wellington ns_lwdclient_log(50, "invalid packet header received");
9a6bbb206efa528373c31928ebd0b7216c747a13Brian Wellington ns_lwdclient_log(50, "opcode %08x", client->pkt.opcode);
9a6bbb206efa528373c31928ebd0b7216c747a13Brian Wellington ns_lwdclient_log(50, "unknown opcode %08x", client->pkt.opcode);
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellington * Drop the packet.
9a6bbb206efa528373c31928ebd0b7216c747a13Brian Wellington ns_lwdclient_log(50, "restarting client %p...", client);
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellingtonns_lwdclient_recv(isc_task_t *task, isc_event_t *ev) {
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellington isc_socketevent_t *dev = (isc_socketevent_t *)ev;
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellington INSIST(dev->region.base == client->buffer);
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellington INSIST((cm->flags & NS_LWDCLIENTMGR_FLAGRECVPENDING) != 0);
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellington cm->flags &= ~NS_LWDCLIENTMGR_FLAGRECVPENDING;
9a6bbb206efa528373c31928ebd0b7216c747a13Brian Wellington "event received: task %p, length %u, result %u (%s)",
50980039820700108f1f5eef1e42aa998a44f087Brian Wellington if ((dev->attributes & ISC_SOCKEVENTATTR_PKTINFO) != 0) {
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson "could not start lwres "
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson "client handler: %s",
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellington * This function will start a new recv() on a socket for this client manager.
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellingtonns_lwdclient_startrecv(ns_lwdclientmgr_t *cm) {
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellington * If a recv is already running, don't bother.
563878539af45d41143701a6d299e9b226937f5bMark Andrews if ((cm->flags & NS_LWDCLIENTMGR_FLAGRECVPENDING) != 0) {
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellington * If we have no idle slots, just return success.
563878539af45d41143701a6d299e9b226937f5bMark Andrews * Set the flag to say there is a recv pending. If isc_socket_recv
563878539af45d41143701a6d299e9b226937f5bMark Andrews * fails we will clear the flag otherwise it will be cleared by
563878539af45d41143701a6d299e9b226937f5bMark Andrews * ns_lwdclient_recv.
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellington * Issue the recv. If it fails, return that it did.
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellington result = isc_socket_recv(cm->sock, &r, 0, cm->task, ns_lwdclient_recv,
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellington * Remove the client from the idle list, and put it on the running
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellington ISC_LIST_APPEND(cm->running, client, link);
4e96d1fc0646de4d879e7a0bc1e7aba449a67596Michael Grafflwdclientmgr_shutdown_callback(isc_task_t *task, isc_event_t *ev) {
4e96d1fc0646de4d879e7a0bc1e7aba449a67596Michael Graff ns_lwdclient_log(50, "got shutdown event, task %p, lwdclientmgr %p",
4e96d1fc0646de4d879e7a0bc1e7aba449a67596Michael Graff * run through the idle list and free the clients there. Idle
4e96d1fc0646de4d879e7a0bc1e7aba449a67596Michael Graff * clients do not have a recv running nor do they have any finds
4e96d1fc0646de4d879e7a0bc1e7aba449a67596Michael Graff * or similar running.
4e96d1fc0646de4d879e7a0bc1e7aba449a67596Michael Graff ns_lwdclient_log(50, "destroying client %p, manager %p",
2f734e0a7e518c89c2b2b179714b8885b7626b3aAndreas Gustafsson isc_mem_put(cm->mctx, client, sizeof(*client));
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellington * Cancel any pending I/O.
4e96d1fc0646de4d879e7a0bc1e7aba449a67596Michael Graff isc_socket_cancel(cm->sock, task, ISC_SOCKCANCEL_ALL);
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellington * Run through the running client list and kill off any finds
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellington * in progress.
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellington cm->flags |= NS_LWDCLIENTMGR_FLAGSHUTTINGDOWN;
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellington * Do all the crap needed to move a client from the run queue to the idle
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellingtonns_lwdclient_stateidle(ns_lwdclient_t *client) {
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellington ISC_LIST_UNLINK(cm->running, client, link);
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson "could not start lwres "
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson "client handler: %s",
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellingtonns_lwdclient_send(isc_task_t *task, isc_event_t *ev) {
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellington isc_socketevent_t *dev = (isc_socketevent_t *)ev;
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellington INSIST(client->sendbuf == dev->region.base);
9a6bbb206efa528373c31928ebd0b7216c747a13Brian Wellington ns_lwdclient_log(50, "task %p for client %p got send-done event",
878d3073b13833ee1a50dfeabf8e400b6fdfc754Brian Wellington lwres_context_freemem(cm->lwctx, client->sendbuf,
50980039820700108f1f5eef1e42aa998a44f087Brian Wellingtonns_lwdclient_sendreply(ns_lwdclient_t *client, isc_region_t *r) {
50980039820700108f1f5eef1e42aa998a44f087Brian Wellington return (isc_socket_sendto(cm->sock, r, cm->task, ns_lwdclient_send,