00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
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
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, ®ion, 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;
00146 ccmsg->mctx = mctx;
00147 ccmsg->sock = sock;
00148 ccmsg->task = NULL;
00149 ccmsg->result = ISC_R_UNEXPECTED;
00150
00151
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);
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;
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;
00193 result = isc_socket_recv(ccmsg->sock, ®ion, 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 }