2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-24 02:58:38 +00:00
bind/lib/isccc/ccmsg.c

211 lines
5.1 KiB
C
Raw Normal View History

/*
2018-03-15 18:32:45 -07:00
* Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
2007-06-18 23:47:57 +00:00
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
2007-06-18 23:47:57 +00:00
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*
2018-03-15 18:32:45 -07:00
* Portions Copyright (C) 2001 Nominum, Inc.
*
2007-08-28 07:20:43 +00:00
* Permission to use, copy, modify, and/or 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.
*
2004-03-05 05:14:21 +00:00
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NOMINUM DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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
2004-03-05 05:14:21 +00:00
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*! \file */
#include <inttypes.h>
#include <isc/mem.h>
#include <isc/result.h>
#include <isc/task.h>
#include <isc/util.h>
#include <isccc/ccmsg.h>
#include <isccc/events.h>
2020-02-13 14:44:37 -08:00
#define CCMSG_MAGIC ISC_MAGIC('C', 'C', 'm', 's')
#define VALID_CCMSG(foo) ISC_MAGIC_VALID(foo, CCMSG_MAGIC)
2020-02-14 08:14:03 +01:00
static void
recv_length(isc_task_t *, isc_event_t *);
static void
recv_message(isc_task_t *, isc_event_t *);
static void
2020-02-13 14:44:37 -08:00
recv_length(isc_task_t *task, isc_event_t *ev_in) {
isc_socketevent_t *ev = (isc_socketevent_t *)ev_in;
isc_event_t *dev = NULL;
2020-02-13 14:44:37 -08:00
isccc_ccmsg_t *ccmsg = ev_in->ev_arg;
isc_region_t region;
isc_result_t result;
INSIST(VALID_CCMSG(ccmsg));
dev = &ccmsg->event;
if (ev->result != ISC_R_SUCCESS) {
ccmsg->result = ev->result;
goto send_and_free;
}
/*
* Success.
*/
ccmsg->size = ntohl(ccmsg->size);
if (ccmsg->size == 0) {
ccmsg->result = ISC_R_UNEXPECTEDEND;
goto send_and_free;
}
if (ccmsg->size > ccmsg->maxsize) {
ccmsg->result = ISC_R_RANGE;
goto send_and_free;
}
region.base = isc_mem_get(ccmsg->mctx, ccmsg->size);
region.length = ccmsg->size;
if (region.base == NULL) {
ccmsg->result = ISC_R_NOMEMORY;
goto send_and_free;
}
isc_buffer_init(&ccmsg->buffer, region.base, region.length);
result = isc_socket_recv(ccmsg->sock, &region, 0, task, recv_message,
ccmsg);
if (result != ISC_R_SUCCESS) {
ccmsg->result = result;
goto send_and_free;
}
isc_event_free(&ev_in);
return;
send_and_free:
isc_task_send(ccmsg->task, &dev);
ccmsg->task = NULL;
isc_event_free(&ev_in);
return;
}
static void
2020-02-13 14:44:37 -08:00
recv_message(isc_task_t *task, isc_event_t *ev_in) {
isc_socketevent_t *ev = (isc_socketevent_t *)ev_in;
isc_event_t *dev = NULL;
2020-02-13 14:44:37 -08:00
isccc_ccmsg_t *ccmsg = ev_in->ev_arg;
UNUSED(task);
INSIST(VALID_CCMSG(ccmsg));
dev = &ccmsg->event;
if (ev->result != ISC_R_SUCCESS) {
ccmsg->result = ev->result;
goto send_and_free;
}
ccmsg->result = ISC_R_SUCCESS;
isc_buffer_add(&ccmsg->buffer, ev->n);
ccmsg->address = ev->address;
send_and_free:
isc_task_send(ccmsg->task, &dev);
ccmsg->task = NULL;
isc_event_free(&ev_in);
}
void
2020-02-13 14:44:37 -08:00
isccc_ccmsg_init(isc_mem_t *mctx, isc_socket_t *sock, isccc_ccmsg_t *ccmsg) {
REQUIRE(mctx != NULL);
REQUIRE(sock != NULL);
REQUIRE(ccmsg != NULL);
*ccmsg = (isccc_ccmsg_t){
.magic = CCMSG_MAGIC,
.maxsize = 0xffffffffU, /* Largest message possible. */
.mctx = mctx,
.sock = sock,
.result = ISC_R_UNEXPECTED /* None yet. */
};
/*
* Should probably initialize the event here, but it can wait.
*/
}
void
2020-02-13 14:44:37 -08:00
isccc_ccmsg_setmaxsize(isccc_ccmsg_t *ccmsg, unsigned int maxsize) {
REQUIRE(VALID_CCMSG(ccmsg));
ccmsg->maxsize = maxsize;
}
isc_result_t
isccc_ccmsg_readmessage(isccc_ccmsg_t *ccmsg, isc_task_t *task,
2020-02-13 14:44:37 -08:00
isc_taskaction_t action, void *arg) {
isc_result_t result;
isc_region_t region;
REQUIRE(VALID_CCMSG(ccmsg));
REQUIRE(task != NULL);
REQUIRE(ccmsg->task == NULL); /* not currently in use */
if (ccmsg->buffer.base != NULL) {
isc_mem_put(ccmsg->mctx, ccmsg->buffer.base,
ccmsg->buffer.length);
ccmsg->buffer.base = NULL;
ccmsg->buffer.length = 0;
}
ccmsg->task = task;
ccmsg->action = action;
ccmsg->arg = arg;
ccmsg->result = ISC_R_UNEXPECTED; /* unknown right now */
ISC_EVENT_INIT(&ccmsg->event, sizeof(isc_event_t), 0, 0,
ISCCC_EVENT_CCMSG, action, arg, ccmsg, NULL, NULL);
region.base = (unsigned char *)&ccmsg->size;
region.length = 4; /* uint32_t */
result = isc_socket_recv(ccmsg->sock, &region, 0, ccmsg->task,
recv_length, ccmsg);
if (result != ISC_R_SUCCESS) {
ccmsg->task = NULL;
}
return (result);
}
void
2020-02-13 14:44:37 -08:00
isccc_ccmsg_cancelread(isccc_ccmsg_t *ccmsg) {
REQUIRE(VALID_CCMSG(ccmsg));
isc_socket_cancel(ccmsg->sock, NULL, ISC_SOCKCANCEL_RECV);
}
void
2020-02-13 14:44:37 -08:00
isccc_ccmsg_invalidate(isccc_ccmsg_t *ccmsg) {
REQUIRE(VALID_CCMSG(ccmsg));
ccmsg->magic = 0;
if (ccmsg->buffer.base != NULL) {
isc_mem_put(ccmsg->mctx, ccmsg->buffer.base,
ccmsg->buffer.length);
ccmsg->buffer.base = NULL;
ccmsg->buffer.length = 0;
}
}