Home | History | Annotate | Line # | Download | only in isccc
ccmsg.c revision 1.6.2.1
      1 /*	$NetBSD: ccmsg.c,v 1.6.2.1 2024/02/25 15:47:30 martin Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * SPDX-License-Identifier: MPL-2.0 AND ISC
      7  *
      8  * This Source Code Form is subject to the terms of the Mozilla Public
      9  * License, v. 2.0. If a copy of the MPL was not distributed with this
     10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
     11  *
     12  * See the COPYRIGHT file distributed with this work for additional
     13  * information regarding copyright ownership.
     14  */
     15 
     16 /*
     17  * Copyright (C) 2001 Nominum, Inc.
     18  *
     19  * Permission to use, copy, modify, and/or distribute this software for any
     20  * purpose with or without fee is hereby granted, provided that the above
     21  * copyright notice and this permission notice appear in all copies.
     22  *
     23  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NOMINUM DISCLAIMS ALL
     24  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
     25  * OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY
     26  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     27  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     28  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     29  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     30  */
     31 
     32 /*! \file */
     33 
     34 #include <inttypes.h>
     35 
     36 #include <isc/mem.h>
     37 #include <isc/netmgr.h>
     38 #include <isc/result.h>
     39 #include <isc/string.h>
     40 #include <isc/util.h>
     41 
     42 #include <isccc/ccmsg.h>
     43 #include <isccc/events.h>
     44 
     45 #define CCMSG_MAGIC	 ISC_MAGIC('C', 'C', 'm', 's')
     46 #define VALID_CCMSG(foo) ISC_MAGIC_VALID(foo, CCMSG_MAGIC)
     47 
     48 static void
     49 recv_data(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
     50 	  void *arg) {
     51 	isccc_ccmsg_t *ccmsg = arg;
     52 	size_t size;
     53 
     54 	INSIST(VALID_CCMSG(ccmsg));
     55 
     56 	switch (eresult) {
     57 	case ISC_R_SHUTTINGDOWN:
     58 	case ISC_R_CANCELED:
     59 	case ISC_R_EOF:
     60 		ccmsg->result = eresult;
     61 		goto done;
     62 	case ISC_R_SUCCESS:
     63 		if (region == NULL) {
     64 			ccmsg->result = ISC_R_EOF;
     65 			goto done;
     66 		}
     67 		ccmsg->result = ISC_R_SUCCESS;
     68 		break;
     69 	default:
     70 		ccmsg->result = eresult;
     71 		goto done;
     72 	}
     73 
     74 	if (!ccmsg->length_received) {
     75 		if (region->length < sizeof(uint32_t)) {
     76 			ccmsg->result = ISC_R_UNEXPECTEDEND;
     77 			goto done;
     78 		}
     79 
     80 		ccmsg->size = ntohl(*(uint32_t *)region->base);
     81 
     82 		if (ccmsg->size == 0) {
     83 			ccmsg->result = ISC_R_UNEXPECTEDEND;
     84 			goto done;
     85 		}
     86 		if (ccmsg->size > ccmsg->maxsize) {
     87 			ccmsg->result = ISC_R_RANGE;
     88 			goto done;
     89 		}
     90 
     91 		isc_region_consume(region, sizeof(uint32_t));
     92 		isc_buffer_allocate(ccmsg->mctx, &ccmsg->buffer, ccmsg->size);
     93 
     94 		ccmsg->length_received = true;
     95 	}
     96 
     97 	/*
     98 	 * If there's no more data, wait for more
     99 	 */
    100 	if (region->length == 0) {
    101 		return;
    102 	}
    103 
    104 	/* We have some data in the buffer, read it */
    105 
    106 	size = ISC_MIN(isc_buffer_availablelength(ccmsg->buffer),
    107 		       region->length);
    108 	isc_buffer_putmem(ccmsg->buffer, region->base, size);
    109 	isc_region_consume(region, size);
    110 
    111 	if (isc_buffer_usedlength(ccmsg->buffer) == ccmsg->size) {
    112 		ccmsg->result = ISC_R_SUCCESS;
    113 		goto done;
    114 	}
    115 
    116 	/* Wait for more data to come */
    117 	return;
    118 
    119 done:
    120 	isc_nm_pauseread(handle);
    121 	ccmsg->cb(handle, ccmsg->result, ccmsg->cbarg);
    122 }
    123 
    124 void
    125 isccc_ccmsg_init(isc_mem_t *mctx, isc_nmhandle_t *handle,
    126 		 isccc_ccmsg_t *ccmsg) {
    127 	REQUIRE(mctx != NULL);
    128 	REQUIRE(handle != NULL);
    129 	REQUIRE(ccmsg != NULL);
    130 
    131 	*ccmsg = (isccc_ccmsg_t){
    132 		.magic = CCMSG_MAGIC,
    133 		.maxsize = 0xffffffffU, /* Largest message possible. */
    134 		.mctx = mctx,
    135 		.handle = handle,
    136 		.result = ISC_R_UNEXPECTED /* None yet. */
    137 	};
    138 }
    139 
    140 void
    141 isccc_ccmsg_setmaxsize(isccc_ccmsg_t *ccmsg, unsigned int maxsize) {
    142 	REQUIRE(VALID_CCMSG(ccmsg));
    143 
    144 	ccmsg->maxsize = maxsize;
    145 }
    146 
    147 void
    148 isccc_ccmsg_readmessage(isccc_ccmsg_t *ccmsg, isc_nm_cb_t cb, void *cbarg) {
    149 	REQUIRE(VALID_CCMSG(ccmsg));
    150 
    151 	if (ccmsg->buffer != NULL) {
    152 		isc_buffer_free(&ccmsg->buffer);
    153 	}
    154 
    155 	ccmsg->cb = cb;
    156 	ccmsg->cbarg = cbarg;
    157 	ccmsg->result = ISC_R_UNEXPECTED; /* unknown right now */
    158 	ccmsg->length_received = false;
    159 
    160 	if (ccmsg->reading) {
    161 		isc_nm_resumeread(ccmsg->handle);
    162 	} else {
    163 		isc_nm_read(ccmsg->handle, recv_data, ccmsg);
    164 		ccmsg->reading = true;
    165 	}
    166 }
    167 
    168 void
    169 isccc_ccmsg_cancelread(isccc_ccmsg_t *ccmsg) {
    170 	REQUIRE(VALID_CCMSG(ccmsg));
    171 
    172 	if (ccmsg->reading) {
    173 		isc_nm_cancelread(ccmsg->handle);
    174 		ccmsg->reading = false;
    175 	}
    176 }
    177 
    178 void
    179 isccc_ccmsg_invalidate(isccc_ccmsg_t *ccmsg) {
    180 	REQUIRE(VALID_CCMSG(ccmsg));
    181 
    182 	ccmsg->magic = 0;
    183 
    184 	if (ccmsg->buffer != NULL) {
    185 		isc_buffer_free(&ccmsg->buffer);
    186 	}
    187 }
    188