ccmsg.c

Go to the documentation of this file.
00001 /*
00002  * Portions Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
00003  * Portions Copyright (C) 2001  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NOMINUM DISCLAIMS ALL
00010  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
00011  * OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY
00012  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00013  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00014  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00015  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00016  *
00017  * Portions Copyright (C) 2001  Nominum, Inc.
00018  *
00019  * Permission to use, copy, modify, and/or distribute this software for any
00020  * purpose with or without fee is hereby granted, provided that the above
00021  * copyright notice and this permission notice appear in all copies.
00022  *
00023  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NOMINUM DISCLAIMS ALL
00024  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
00025  * OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY
00026  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00027  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00028  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00029  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00030  */
00031 
00032 /* $Id: ccmsg.c,v 1.10 2007/08/28 07:20:43 tbox Exp $ */
00033 
00034 /*! \file */
00035 
00036 #include <config.h>
00037 
00038 #include <isc/mem.h>
00039 #include <isc/result.h>
00040 #include <isc/task.h>
00041 #include <isc/util.h>
00042 
00043 #include <isccc/events.h>
00044 #include <isccc/ccmsg.h>
00045 
00046 #define CCMSG_MAGIC             ISC_MAGIC('C', 'C', 'm', 's')
00047 #define VALID_CCMSG(foo)        ISC_MAGIC_VALID(foo, CCMSG_MAGIC)
00048 
00049 static void recv_length(isc_task_t *, isc_event_t *);
00050 static void recv_message(isc_task_t *, isc_event_t *);
00051 
00052 
00053 static void
00054 recv_length(isc_task_t *task, isc_event_t *ev_in) {
00055         isc_socketevent_t *ev = (isc_socketevent_t *)ev_in;
00056         isc_event_t *dev;
00057         isccc_ccmsg_t *ccmsg = ev_in->ev_arg;
00058         isc_region_t region;
00059         isc_result_t result;
00060 
00061         INSIST(VALID_CCMSG(ccmsg));
00062 
00063         dev = &ccmsg->event;
00064 
00065         if (ev->result != ISC_R_SUCCESS) {
00066                 ccmsg->result = ev->result;
00067                 goto send_and_free;
00068         }
00069 
00070         /*
00071          * Success.
00072          */
00073         ccmsg->size = ntohl(ccmsg->size);
00074         if (ccmsg->size == 0) {
00075                 ccmsg->result = ISC_R_UNEXPECTEDEND;
00076                 goto send_and_free;
00077         }
00078         if (ccmsg->size > ccmsg->maxsize) {
00079                 ccmsg->result = ISC_R_RANGE;
00080                 goto send_and_free;
00081         }
00082 
00083         region.base = isc_mem_get(ccmsg->mctx, ccmsg->size);
00084         region.length = ccmsg->size;
00085         if (region.base == NULL) {
00086                 ccmsg->result = ISC_R_NOMEMORY;
00087                 goto send_and_free;
00088         }
00089 
00090         isc_buffer_init(&ccmsg->buffer, region.base, region.length);
00091         result = isc_socket_recv(ccmsg->sock, &region, 0,
00092                                  task, recv_message, ccmsg);
00093         if (result != ISC_R_SUCCESS) {
00094                 ccmsg->result = result;
00095                 goto send_and_free;
00096         }
00097 
00098         isc_event_free(&ev_in);
00099         return;
00100 
00101  send_and_free:
00102         isc_task_send(ccmsg->task, &dev);
00103         ccmsg->task = NULL;
00104         isc_event_free(&ev_in);
00105         return;
00106 }
00107 
00108 static void
00109 recv_message(isc_task_t *task, isc_event_t *ev_in) {
00110         isc_socketevent_t *ev = (isc_socketevent_t *)ev_in;
00111         isc_event_t *dev;
00112         isccc_ccmsg_t *ccmsg = ev_in->ev_arg;
00113 
00114         (void)task;
00115 
00116         INSIST(VALID_CCMSG(ccmsg));
00117 
00118         dev = &ccmsg->event;
00119 
00120         if (ev->result != ISC_R_SUCCESS) {
00121                 ccmsg->result = ev->result;
00122                 goto send_and_free;
00123         }
00124 
00125         ccmsg->result = ISC_R_SUCCESS;
00126         isc_buffer_add(&ccmsg->buffer, ev->n);
00127         ccmsg->address = ev->address;
00128 
00129  send_and_free:
00130         isc_task_send(ccmsg->task, &dev);
00131         ccmsg->task = NULL;
00132         isc_event_free(&ev_in);
00133 }
00134 
00135 void
00136 isccc_ccmsg_init(isc_mem_t *mctx, isc_socket_t *sock, isccc_ccmsg_t *ccmsg) {
00137         REQUIRE(mctx != NULL);
00138         REQUIRE(sock != NULL);
00139         REQUIRE(ccmsg != NULL);
00140 
00141         ccmsg->magic = CCMSG_MAGIC;
00142         ccmsg->size = 0;
00143         ccmsg->buffer.base = NULL;
00144         ccmsg->buffer.length = 0;
00145         ccmsg->maxsize = 4294967295U;   /* Largest message possible. */
00146         ccmsg->mctx = mctx;
00147         ccmsg->sock = sock;
00148         ccmsg->task = NULL;                     /* None yet. */
00149         ccmsg->result = ISC_R_UNEXPECTED;       /* None yet. */
00150         /*
00151          * Should probably initialize the event here, but it can wait.
00152          */
00153 }
00154 
00155 
00156 void
00157 isccc_ccmsg_setmaxsize(isccc_ccmsg_t *ccmsg, unsigned int maxsize) {
00158         REQUIRE(VALID_CCMSG(ccmsg));
00159 
00160         ccmsg->maxsize = maxsize;
00161 }
00162 
00163 
00164 isc_result_t
00165 isccc_ccmsg_readmessage(isccc_ccmsg_t *ccmsg,
00166                        isc_task_t *task, isc_taskaction_t action, void *arg)
00167 {
00168         isc_result_t result;
00169         isc_region_t region;
00170 
00171         REQUIRE(VALID_CCMSG(ccmsg));
00172         REQUIRE(task != NULL);
00173         REQUIRE(ccmsg->task == NULL);  /* not currently in use */
00174 
00175         if (ccmsg->buffer.base != NULL) {
00176                 isc_mem_put(ccmsg->mctx, ccmsg->buffer.base,
00177                             ccmsg->buffer.length);
00178                 ccmsg->buffer.base = NULL;
00179                 ccmsg->buffer.length = 0;
00180         }
00181 
00182         ccmsg->task = task;
00183         ccmsg->action = action;
00184         ccmsg->arg = arg;
00185         ccmsg->result = ISC_R_UNEXPECTED;  /* unknown right now */
00186 
00187         ISC_EVENT_INIT(&ccmsg->event, sizeof(isc_event_t), 0, 0,
00188                        ISCCC_EVENT_CCMSG, action, arg, ccmsg,
00189                        NULL, NULL);
00190 
00191         region.base = (unsigned char *)&ccmsg->size;
00192         region.length = 4;  /* isc_uint32_t */
00193         result = isc_socket_recv(ccmsg->sock, &region, 0,
00194                                  ccmsg->task, recv_length, ccmsg);
00195 
00196         if (result != ISC_R_SUCCESS)
00197                 ccmsg->task = NULL;
00198 
00199         return (result);
00200 }
00201 
00202 void
00203 isccc_ccmsg_cancelread(isccc_ccmsg_t *ccmsg) {
00204         REQUIRE(VALID_CCMSG(ccmsg));
00205 
00206         isc_socket_cancel(ccmsg->sock, NULL, ISC_SOCKCANCEL_RECV);
00207 }
00208 
00209 #if 0
00210 void
00211 isccc_ccmsg_freebuffer(isccc_ccmsg_t *ccmsg) {
00212         REQUIRE(VALID_CCMSG(ccmsg));
00213 
00214         if (ccmsg->buffer.base == NULL)
00215                 return;
00216 
00217         isc_mem_put(ccmsg->mctx, ccmsg->buffer.base, ccmsg->buffer.length);
00218         ccmsg->buffer.base = NULL;
00219         ccmsg->buffer.length = 0;
00220 }
00221 #endif
00222 
00223 void
00224 isccc_ccmsg_invalidate(isccc_ccmsg_t *ccmsg) {
00225         REQUIRE(VALID_CCMSG(ccmsg));
00226 
00227         ccmsg->magic = 0;
00228 
00229         if (ccmsg->buffer.base != NULL) {
00230                 isc_mem_put(ccmsg->mctx, ccmsg->buffer.base,
00231                             ccmsg->buffer.length);
00232                 ccmsg->buffer.base = NULL;
00233                 ccmsg->buffer.length = 0;
00234         }
00235 }

Generated on Tue Apr 28 17:41:06 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha