Home | History | Annotate | Line # | Download | only in isccc
ccmsg.c revision 1.3
      1  1.2  christos /*	$NetBSD: ccmsg.c,v 1.3 2019/01/09 16:55:18 christos Exp $	*/
      2  1.1  christos 
      3  1.1  christos /*
      4  1.1  christos  * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  1.1  christos  *
      6  1.1  christos  * This Source Code Form is subject to the terms of the Mozilla Public
      7  1.1  christos  * License, v. 2.0. If a copy of the MPL was not distributed with this
      8  1.1  christos  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
      9  1.1  christos  *
     10  1.1  christos  * See the COPYRIGHT file distributed with this work for additional
     11  1.1  christos  * information regarding copyright ownership.
     12  1.1  christos  *
     13  1.1  christos  * Portions Copyright (C) 2001 Nominum, Inc.
     14  1.1  christos  *
     15  1.1  christos  * Permission to use, copy, modify, and/or distribute this software for any
     16  1.1  christos  * purpose with or without fee is hereby granted, provided that the above
     17  1.1  christos  * copyright notice and this permission notice appear in all copies.
     18  1.1  christos  *
     19  1.1  christos  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NOMINUM DISCLAIMS ALL
     20  1.1  christos  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
     21  1.1  christos  * OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY
     22  1.1  christos  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     23  1.1  christos  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     24  1.1  christos  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     25  1.1  christos  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     26  1.1  christos  */
     27  1.1  christos 
     28  1.1  christos 
     29  1.1  christos /*! \file */
     30  1.1  christos 
     31  1.1  christos #include <config.h>
     32  1.1  christos 
     33  1.3  christos #include <inttypes.h>
     34  1.3  christos 
     35  1.1  christos #include <isc/mem.h>
     36  1.1  christos #include <isc/result.h>
     37  1.1  christos #include <isc/task.h>
     38  1.1  christos #include <isc/util.h>
     39  1.1  christos 
     40  1.1  christos #include <isccc/events.h>
     41  1.1  christos #include <isccc/ccmsg.h>
     42  1.1  christos 
     43  1.1  christos #define CCMSG_MAGIC		ISC_MAGIC('C', 'C', 'm', 's')
     44  1.1  christos #define VALID_CCMSG(foo)	ISC_MAGIC_VALID(foo, CCMSG_MAGIC)
     45  1.1  christos 
     46  1.1  christos static void recv_length(isc_task_t *, isc_event_t *);
     47  1.1  christos static void recv_message(isc_task_t *, isc_event_t *);
     48  1.1  christos 
     49  1.1  christos 
     50  1.1  christos static void
     51  1.1  christos recv_length(isc_task_t *task, isc_event_t *ev_in) {
     52  1.1  christos 	isc_socketevent_t *ev = (isc_socketevent_t *)ev_in;
     53  1.1  christos 	isc_event_t *dev;
     54  1.1  christos 	isccc_ccmsg_t *ccmsg = ev_in->ev_arg;
     55  1.1  christos 	isc_region_t region;
     56  1.1  christos 	isc_result_t result;
     57  1.1  christos 
     58  1.1  christos 	INSIST(VALID_CCMSG(ccmsg));
     59  1.1  christos 
     60  1.1  christos 	dev = &ccmsg->event;
     61  1.1  christos 
     62  1.1  christos 	if (ev->result != ISC_R_SUCCESS) {
     63  1.1  christos 		ccmsg->result = ev->result;
     64  1.1  christos 		goto send_and_free;
     65  1.1  christos 	}
     66  1.1  christos 
     67  1.1  christos 	/*
     68  1.1  christos 	 * Success.
     69  1.1  christos 	 */
     70  1.1  christos 	ccmsg->size = ntohl(ccmsg->size);
     71  1.1  christos 	if (ccmsg->size == 0) {
     72  1.1  christos 		ccmsg->result = ISC_R_UNEXPECTEDEND;
     73  1.1  christos 		goto send_and_free;
     74  1.1  christos 	}
     75  1.1  christos 	if (ccmsg->size > ccmsg->maxsize) {
     76  1.1  christos 		ccmsg->result = ISC_R_RANGE;
     77  1.1  christos 		goto send_and_free;
     78  1.1  christos 	}
     79  1.1  christos 
     80  1.1  christos 	region.base = isc_mem_get(ccmsg->mctx, ccmsg->size);
     81  1.1  christos 	region.length = ccmsg->size;
     82  1.1  christos 	if (region.base == NULL) {
     83  1.1  christos 		ccmsg->result = ISC_R_NOMEMORY;
     84  1.1  christos 		goto send_and_free;
     85  1.1  christos 	}
     86  1.1  christos 
     87  1.1  christos 	isc_buffer_init(&ccmsg->buffer, region.base, region.length);
     88  1.1  christos 	result = isc_socket_recv(ccmsg->sock, &region, 0,
     89  1.1  christos 				 task, recv_message, ccmsg);
     90  1.1  christos 	if (result != ISC_R_SUCCESS) {
     91  1.1  christos 		ccmsg->result = result;
     92  1.1  christos 		goto send_and_free;
     93  1.1  christos 	}
     94  1.1  christos 
     95  1.1  christos 	isc_event_free(&ev_in);
     96  1.1  christos 	return;
     97  1.1  christos 
     98  1.1  christos  send_and_free:
     99  1.1  christos 	isc_task_send(ccmsg->task, &dev);
    100  1.1  christos 	ccmsg->task = NULL;
    101  1.1  christos 	isc_event_free(&ev_in);
    102  1.1  christos 	return;
    103  1.1  christos }
    104  1.1  christos 
    105  1.1  christos static void
    106  1.1  christos recv_message(isc_task_t *task, isc_event_t *ev_in) {
    107  1.1  christos 	isc_socketevent_t *ev = (isc_socketevent_t *)ev_in;
    108  1.1  christos 	isc_event_t *dev;
    109  1.1  christos 	isccc_ccmsg_t *ccmsg = ev_in->ev_arg;
    110  1.1  christos 
    111  1.1  christos 	(void)task;
    112  1.1  christos 
    113  1.1  christos 	INSIST(VALID_CCMSG(ccmsg));
    114  1.1  christos 
    115  1.1  christos 	dev = &ccmsg->event;
    116  1.1  christos 
    117  1.1  christos 	if (ev->result != ISC_R_SUCCESS) {
    118  1.1  christos 		ccmsg->result = ev->result;
    119  1.1  christos 		goto send_and_free;
    120  1.1  christos 	}
    121  1.1  christos 
    122  1.1  christos 	ccmsg->result = ISC_R_SUCCESS;
    123  1.1  christos 	isc_buffer_add(&ccmsg->buffer, ev->n);
    124  1.1  christos 	ccmsg->address = ev->address;
    125  1.1  christos 
    126  1.1  christos  send_and_free:
    127  1.1  christos 	isc_task_send(ccmsg->task, &dev);
    128  1.1  christos 	ccmsg->task = NULL;
    129  1.1  christos 	isc_event_free(&ev_in);
    130  1.1  christos }
    131  1.1  christos 
    132  1.1  christos void
    133  1.1  christos isccc_ccmsg_init(isc_mem_t *mctx, isc_socket_t *sock, isccc_ccmsg_t *ccmsg) {
    134  1.1  christos 	REQUIRE(mctx != NULL);
    135  1.1  christos 	REQUIRE(sock != NULL);
    136  1.1  christos 	REQUIRE(ccmsg != NULL);
    137  1.1  christos 
    138  1.1  christos 	ccmsg->magic = CCMSG_MAGIC;
    139  1.1  christos 	ccmsg->size = 0;
    140  1.1  christos 	ccmsg->buffer.base = NULL;
    141  1.1  christos 	ccmsg->buffer.length = 0;
    142  1.1  christos 	ccmsg->maxsize = 4294967295U;	/* Largest message possible. */
    143  1.1  christos 	ccmsg->mctx = mctx;
    144  1.1  christos 	ccmsg->sock = sock;
    145  1.1  christos 	ccmsg->task = NULL;			/* None yet. */
    146  1.1  christos 	ccmsg->result = ISC_R_UNEXPECTED;	/* None yet. */
    147  1.1  christos 	/*
    148  1.1  christos 	 * Should probably initialize the event here, but it can wait.
    149  1.1  christos 	 */
    150  1.1  christos }
    151  1.1  christos 
    152  1.1  christos 
    153  1.1  christos void
    154  1.1  christos isccc_ccmsg_setmaxsize(isccc_ccmsg_t *ccmsg, unsigned int maxsize) {
    155  1.1  christos 	REQUIRE(VALID_CCMSG(ccmsg));
    156  1.1  christos 
    157  1.1  christos 	ccmsg->maxsize = maxsize;
    158  1.1  christos }
    159  1.1  christos 
    160  1.1  christos 
    161  1.1  christos isc_result_t
    162  1.1  christos isccc_ccmsg_readmessage(isccc_ccmsg_t *ccmsg,
    163  1.1  christos 		       isc_task_t *task, isc_taskaction_t action, void *arg)
    164  1.1  christos {
    165  1.1  christos 	isc_result_t result;
    166  1.1  christos 	isc_region_t region;
    167  1.1  christos 
    168  1.1  christos 	REQUIRE(VALID_CCMSG(ccmsg));
    169  1.1  christos 	REQUIRE(task != NULL);
    170  1.1  christos 	REQUIRE(ccmsg->task == NULL);  /* not currently in use */
    171  1.1  christos 
    172  1.1  christos 	if (ccmsg->buffer.base != NULL) {
    173  1.1  christos 		isc_mem_put(ccmsg->mctx, ccmsg->buffer.base,
    174  1.1  christos 			    ccmsg->buffer.length);
    175  1.1  christos 		ccmsg->buffer.base = NULL;
    176  1.1  christos 		ccmsg->buffer.length = 0;
    177  1.1  christos 	}
    178  1.1  christos 
    179  1.1  christos 	ccmsg->task = task;
    180  1.1  christos 	ccmsg->action = action;
    181  1.1  christos 	ccmsg->arg = arg;
    182  1.1  christos 	ccmsg->result = ISC_R_UNEXPECTED;  /* unknown right now */
    183  1.1  christos 
    184  1.1  christos 	ISC_EVENT_INIT(&ccmsg->event, sizeof(isc_event_t), 0, 0,
    185  1.1  christos 		       ISCCC_EVENT_CCMSG, action, arg, ccmsg,
    186  1.1  christos 		       NULL, NULL);
    187  1.1  christos 
    188  1.1  christos 	region.base = (unsigned char *)&ccmsg->size;
    189  1.3  christos 	region.length = 4;  /* uint32_t */
    190  1.1  christos 	result = isc_socket_recv(ccmsg->sock, &region, 0,
    191  1.1  christos 				 ccmsg->task, recv_length, ccmsg);
    192  1.1  christos 
    193  1.1  christos 	if (result != ISC_R_SUCCESS)
    194  1.1  christos 		ccmsg->task = NULL;
    195  1.1  christos 
    196  1.1  christos 	return (result);
    197  1.1  christos }
    198  1.1  christos 
    199  1.1  christos void
    200  1.1  christos isccc_ccmsg_cancelread(isccc_ccmsg_t *ccmsg) {
    201  1.1  christos 	REQUIRE(VALID_CCMSG(ccmsg));
    202  1.1  christos 
    203  1.1  christos 	isc_socket_cancel(ccmsg->sock, NULL, ISC_SOCKCANCEL_RECV);
    204  1.1  christos }
    205  1.1  christos 
    206  1.1  christos #if 0
    207  1.1  christos void
    208  1.1  christos isccc_ccmsg_freebuffer(isccc_ccmsg_t *ccmsg) {
    209  1.1  christos 	REQUIRE(VALID_CCMSG(ccmsg));
    210  1.1  christos 
    211  1.1  christos 	if (ccmsg->buffer.base == NULL)
    212  1.1  christos 		return;
    213  1.1  christos 
    214  1.1  christos 	isc_mem_put(ccmsg->mctx, ccmsg->buffer.base, ccmsg->buffer.length);
    215  1.1  christos 	ccmsg->buffer.base = NULL;
    216  1.1  christos 	ccmsg->buffer.length = 0;
    217  1.1  christos }
    218  1.1  christos #endif
    219  1.1  christos 
    220  1.1  christos void
    221  1.1  christos isccc_ccmsg_invalidate(isccc_ccmsg_t *ccmsg) {
    222  1.1  christos 	REQUIRE(VALID_CCMSG(ccmsg));
    223  1.1  christos 
    224  1.1  christos 	ccmsg->magic = 0;
    225  1.1  christos 
    226  1.1  christos 	if (ccmsg->buffer.base != NULL) {
    227  1.1  christos 		isc_mem_put(ccmsg->mctx, ccmsg->buffer.base,
    228  1.1  christos 			    ccmsg->buffer.length);
    229  1.1  christos 		ccmsg->buffer.base = NULL;
    230  1.1  christos 		ccmsg->buffer.length = 0;
    231  1.1  christos 	}
    232  1.1  christos }
    233