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