1135446Strhodes/* 2193149Sdougb * Portions Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") 3135446Strhodes * Portions Copyright (C) 2001 Internet Software Consortium. 4193149Sdougb * 5193149Sdougb * Permission to use, copy, modify, and/or distribute this software for any 6193149Sdougb * purpose with or without fee is hereby granted, provided that the above 7193149Sdougb * copyright notice and this permission notice appear in all copies. 8193149Sdougb * 9193149Sdougb * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NOMINUM DISCLAIMS ALL 10193149Sdougb * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 11193149Sdougb * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY 12193149Sdougb * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13193149Sdougb * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14193149Sdougb * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15193149Sdougb * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16193149Sdougb * 17135446Strhodes * Portions Copyright (C) 2001 Nominum, Inc. 18135446Strhodes * 19193149Sdougb * Permission to use, copy, modify, and/or distribute this software for any 20135446Strhodes * purpose with or without fee is hereby granted, provided that the above 21135446Strhodes * copyright notice and this permission notice appear in all copies. 22135446Strhodes * 23135446Strhodes * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NOMINUM DISCLAIMS ALL 24135446Strhodes * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 25135446Strhodes * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY 26135446Strhodes * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 27135446Strhodes * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 28135446Strhodes * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 29135446Strhodes * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 30135446Strhodes */ 31135446Strhodes 32234010Sdougb/* $Id: ccmsg.c,v 1.10 2007/08/28 07:20:43 tbox Exp $ */ 33135446Strhodes 34170222Sdougb/*! \file */ 35170222Sdougb 36135446Strhodes#include <config.h> 37135446Strhodes 38135446Strhodes#include <isc/mem.h> 39135446Strhodes#include <isc/result.h> 40135446Strhodes#include <isc/task.h> 41135446Strhodes#include <isc/util.h> 42135446Strhodes 43135446Strhodes#include <isccc/events.h> 44135446Strhodes#include <isccc/ccmsg.h> 45135446Strhodes 46135446Strhodes#define CCMSG_MAGIC ISC_MAGIC('C', 'C', 'm', 's') 47135446Strhodes#define VALID_CCMSG(foo) ISC_MAGIC_VALID(foo, CCMSG_MAGIC) 48135446Strhodes 49135446Strhodesstatic void recv_length(isc_task_t *, isc_event_t *); 50135446Strhodesstatic void recv_message(isc_task_t *, isc_event_t *); 51135446Strhodes 52135446Strhodes 53135446Strhodesstatic void 54135446Strhodesrecv_length(isc_task_t *task, isc_event_t *ev_in) { 55135446Strhodes isc_socketevent_t *ev = (isc_socketevent_t *)ev_in; 56135446Strhodes isc_event_t *dev; 57135446Strhodes isccc_ccmsg_t *ccmsg = ev_in->ev_arg; 58135446Strhodes isc_region_t region; 59135446Strhodes isc_result_t result; 60135446Strhodes 61135446Strhodes INSIST(VALID_CCMSG(ccmsg)); 62135446Strhodes 63135446Strhodes dev = &ccmsg->event; 64135446Strhodes 65135446Strhodes if (ev->result != ISC_R_SUCCESS) { 66135446Strhodes ccmsg->result = ev->result; 67135446Strhodes goto send_and_free; 68135446Strhodes } 69135446Strhodes 70135446Strhodes /* 71135446Strhodes * Success. 72135446Strhodes */ 73135446Strhodes ccmsg->size = ntohl(ccmsg->size); 74135446Strhodes if (ccmsg->size == 0) { 75135446Strhodes ccmsg->result = ISC_R_UNEXPECTEDEND; 76135446Strhodes goto send_and_free; 77135446Strhodes } 78135446Strhodes if (ccmsg->size > ccmsg->maxsize) { 79135446Strhodes ccmsg->result = ISC_R_RANGE; 80135446Strhodes goto send_and_free; 81135446Strhodes } 82135446Strhodes 83135446Strhodes region.base = isc_mem_get(ccmsg->mctx, ccmsg->size); 84135446Strhodes region.length = ccmsg->size; 85135446Strhodes if (region.base == NULL) { 86135446Strhodes ccmsg->result = ISC_R_NOMEMORY; 87135446Strhodes goto send_and_free; 88135446Strhodes } 89135446Strhodes 90135446Strhodes isc_buffer_init(&ccmsg->buffer, region.base, region.length); 91135446Strhodes result = isc_socket_recv(ccmsg->sock, ®ion, 0, 92135446Strhodes task, recv_message, ccmsg); 93135446Strhodes if (result != ISC_R_SUCCESS) { 94135446Strhodes ccmsg->result = result; 95135446Strhodes goto send_and_free; 96135446Strhodes } 97135446Strhodes 98135446Strhodes isc_event_free(&ev_in); 99135446Strhodes return; 100135446Strhodes 101135446Strhodes send_and_free: 102135446Strhodes isc_task_send(ccmsg->task, &dev); 103135446Strhodes ccmsg->task = NULL; 104135446Strhodes isc_event_free(&ev_in); 105135446Strhodes return; 106135446Strhodes} 107135446Strhodes 108135446Strhodesstatic void 109135446Strhodesrecv_message(isc_task_t *task, isc_event_t *ev_in) { 110135446Strhodes isc_socketevent_t *ev = (isc_socketevent_t *)ev_in; 111135446Strhodes isc_event_t *dev; 112135446Strhodes isccc_ccmsg_t *ccmsg = ev_in->ev_arg; 113135446Strhodes 114135446Strhodes (void)task; 115135446Strhodes 116135446Strhodes INSIST(VALID_CCMSG(ccmsg)); 117135446Strhodes 118135446Strhodes dev = &ccmsg->event; 119135446Strhodes 120135446Strhodes if (ev->result != ISC_R_SUCCESS) { 121135446Strhodes ccmsg->result = ev->result; 122135446Strhodes goto send_and_free; 123135446Strhodes } 124135446Strhodes 125135446Strhodes ccmsg->result = ISC_R_SUCCESS; 126135446Strhodes isc_buffer_add(&ccmsg->buffer, ev->n); 127135446Strhodes ccmsg->address = ev->address; 128135446Strhodes 129135446Strhodes send_and_free: 130135446Strhodes isc_task_send(ccmsg->task, &dev); 131135446Strhodes ccmsg->task = NULL; 132135446Strhodes isc_event_free(&ev_in); 133135446Strhodes} 134135446Strhodes 135135446Strhodesvoid 136135446Strhodesisccc_ccmsg_init(isc_mem_t *mctx, isc_socket_t *sock, isccc_ccmsg_t *ccmsg) { 137135446Strhodes REQUIRE(mctx != NULL); 138135446Strhodes REQUIRE(sock != NULL); 139135446Strhodes REQUIRE(ccmsg != NULL); 140135446Strhodes 141135446Strhodes ccmsg->magic = CCMSG_MAGIC; 142135446Strhodes ccmsg->size = 0; 143135446Strhodes ccmsg->buffer.base = NULL; 144135446Strhodes ccmsg->buffer.length = 0; 145135446Strhodes ccmsg->maxsize = 4294967295U; /* Largest message possible. */ 146135446Strhodes ccmsg->mctx = mctx; 147135446Strhodes ccmsg->sock = sock; 148135446Strhodes ccmsg->task = NULL; /* None yet. */ 149135446Strhodes ccmsg->result = ISC_R_UNEXPECTED; /* None yet. */ 150135446Strhodes /* 151135446Strhodes * Should probably initialize the event here, but it can wait. 152135446Strhodes */ 153135446Strhodes} 154135446Strhodes 155135446Strhodes 156135446Strhodesvoid 157135446Strhodesisccc_ccmsg_setmaxsize(isccc_ccmsg_t *ccmsg, unsigned int maxsize) { 158135446Strhodes REQUIRE(VALID_CCMSG(ccmsg)); 159135446Strhodes 160135446Strhodes ccmsg->maxsize = maxsize; 161135446Strhodes} 162135446Strhodes 163135446Strhodes 164135446Strhodesisc_result_t 165135446Strhodesisccc_ccmsg_readmessage(isccc_ccmsg_t *ccmsg, 166135446Strhodes isc_task_t *task, isc_taskaction_t action, void *arg) 167135446Strhodes{ 168135446Strhodes isc_result_t result; 169135446Strhodes isc_region_t region; 170135446Strhodes 171135446Strhodes REQUIRE(VALID_CCMSG(ccmsg)); 172135446Strhodes REQUIRE(task != NULL); 173135446Strhodes REQUIRE(ccmsg->task == NULL); /* not currently in use */ 174135446Strhodes 175135446Strhodes if (ccmsg->buffer.base != NULL) { 176135446Strhodes isc_mem_put(ccmsg->mctx, ccmsg->buffer.base, 177135446Strhodes ccmsg->buffer.length); 178135446Strhodes ccmsg->buffer.base = NULL; 179135446Strhodes ccmsg->buffer.length = 0; 180135446Strhodes } 181135446Strhodes 182135446Strhodes ccmsg->task = task; 183135446Strhodes ccmsg->action = action; 184135446Strhodes ccmsg->arg = arg; 185135446Strhodes ccmsg->result = ISC_R_UNEXPECTED; /* unknown right now */ 186135446Strhodes 187135446Strhodes ISC_EVENT_INIT(&ccmsg->event, sizeof(isc_event_t), 0, 0, 188135446Strhodes ISCCC_EVENT_CCMSG, action, arg, ccmsg, 189135446Strhodes NULL, NULL); 190135446Strhodes 191135446Strhodes region.base = (unsigned char *)&ccmsg->size; 192135446Strhodes region.length = 4; /* isc_uint32_t */ 193135446Strhodes result = isc_socket_recv(ccmsg->sock, ®ion, 0, 194135446Strhodes ccmsg->task, recv_length, ccmsg); 195135446Strhodes 196135446Strhodes if (result != ISC_R_SUCCESS) 197135446Strhodes ccmsg->task = NULL; 198135446Strhodes 199135446Strhodes return (result); 200135446Strhodes} 201135446Strhodes 202135446Strhodesvoid 203135446Strhodesisccc_ccmsg_cancelread(isccc_ccmsg_t *ccmsg) { 204135446Strhodes REQUIRE(VALID_CCMSG(ccmsg)); 205135446Strhodes 206135446Strhodes isc_socket_cancel(ccmsg->sock, NULL, ISC_SOCKCANCEL_RECV); 207135446Strhodes} 208135446Strhodes 209135446Strhodes#if 0 210135446Strhodesvoid 211135446Strhodesisccc_ccmsg_freebuffer(isccc_ccmsg_t *ccmsg) { 212135446Strhodes REQUIRE(VALID_CCMSG(ccmsg)); 213135446Strhodes 214135446Strhodes if (ccmsg->buffer.base == NULL) 215135446Strhodes return; 216135446Strhodes 217135446Strhodes isc_mem_put(ccmsg->mctx, ccmsg->buffer.base, ccmsg->buffer.length); 218135446Strhodes ccmsg->buffer.base = NULL; 219135446Strhodes ccmsg->buffer.length = 0; 220135446Strhodes} 221135446Strhodes#endif 222135446Strhodes 223135446Strhodesvoid 224135446Strhodesisccc_ccmsg_invalidate(isccc_ccmsg_t *ccmsg) { 225135446Strhodes REQUIRE(VALID_CCMSG(ccmsg)); 226135446Strhodes 227135446Strhodes ccmsg->magic = 0; 228135446Strhodes 229135446Strhodes if (ccmsg->buffer.base != NULL) { 230135446Strhodes isc_mem_put(ccmsg->mctx, ccmsg->buffer.base, 231135446Strhodes ccmsg->buffer.length); 232135446Strhodes ccmsg->buffer.base = NULL; 233135446Strhodes ccmsg->buffer.length = 0; 234135446Strhodes } 235135446Strhodes} 236