2 Unix SMB/CIFS implementation.
4 Copyright (C) Stefan Metzmacher 2009
6 ** NOTE! The following LGPL license applies to the tevent
7 ** library. This does NOT imply that all of Samba is released
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 3 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, see <http://www.gnu.org/licenses/>.
25 #include "system/network.h"
27 #include "tsocket_internal.h"
29 struct tsocket_address
*_tsocket_address_create(TALLOC_CTX
*mem_ctx
,
30 const struct tsocket_address_ops
*ops
,
36 void **ppstate
= (void **)pstate
;
37 struct tsocket_address
*addr
;
39 addr
= talloc_zero(mem_ctx
, struct tsocket_address
);
44 addr
->location
= location
;
45 addr
->private_data
= talloc_size(addr
, psize
);
46 if (!addr
->private_data
) {
50 talloc_set_name_const(addr
->private_data
, type
);
52 *ppstate
= addr
->private_data
;
56 char *tsocket_address_string(const struct tsocket_address
*addr
,
60 return talloc_strdup(mem_ctx
, "NULL");
62 return addr
->ops
->string(addr
, mem_ctx
);
65 struct tsocket_address
*_tsocket_address_copy(const struct tsocket_address
*addr
,
69 return addr
->ops
->copy(addr
, mem_ctx
, location
);
72 struct tdgram_context
{
74 const struct tdgram_context_ops
*ops
;
78 struct tdgram_context
*_tdgram_context_create(TALLOC_CTX
*mem_ctx
,
79 const struct tdgram_context_ops
*ops
,
85 struct tdgram_context
*dgram
;
86 void **ppstate
= (void **)pstate
;
89 dgram
= talloc(mem_ctx
, struct tdgram_context
);
93 dgram
->location
= location
;
96 state
= talloc_size(dgram
, psize
);
101 talloc_set_name_const(state
, type
);
103 dgram
->private_data
= state
;
109 void *_tdgram_context_data(struct tdgram_context
*dgram
)
111 return dgram
->private_data
;
114 struct tdgram_recvfrom_state
{
115 const struct tdgram_context_ops
*ops
;
118 struct tsocket_address
*src
;
121 static void tdgram_recvfrom_done(struct tevent_req
*subreq
);
123 struct tevent_req
*tdgram_recvfrom_send(TALLOC_CTX
*mem_ctx
,
124 struct tevent_context
*ev
,
125 struct tdgram_context
*dgram
)
127 struct tevent_req
*req
;
128 struct tdgram_recvfrom_state
*state
;
129 struct tevent_req
*subreq
;
131 req
= tevent_req_create(mem_ctx
, &state
,
132 struct tdgram_recvfrom_state
);
137 state
->ops
= dgram
->ops
;
139 subreq
= state
->ops
->recvfrom_send(state
, ev
, dgram
);
140 if (tevent_req_nomem(subreq
, req
)) {
143 tevent_req_set_callback(subreq
, tdgram_recvfrom_done
, req
);
148 tevent_req_post(req
, ev
);
152 static void tdgram_recvfrom_done(struct tevent_req
*subreq
)
154 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
156 struct tdgram_recvfrom_state
*state
= tevent_req_data(req
,
157 struct tdgram_recvfrom_state
);
161 ret
= state
->ops
->recvfrom_recv(subreq
, &sys_errno
, state
,
162 &state
->buf
, &state
->src
);
164 tevent_req_error(req
, sys_errno
);
170 tevent_req_done(req
);
173 ssize_t
tdgram_recvfrom_recv(struct tevent_req
*req
,
177 struct tsocket_address
**src
)
179 struct tdgram_recvfrom_state
*state
= tevent_req_data(req
,
180 struct tdgram_recvfrom_state
);
183 ret
= tsocket_simple_int_recv(req
, perrno
);
185 *buf
= talloc_move(mem_ctx
, &state
->buf
);
188 *src
= talloc_move(mem_ctx
, &state
->src
);
192 tevent_req_received(req
);
196 struct tdgram_sendto_state
{
197 const struct tdgram_context_ops
*ops
;
201 static void tdgram_sendto_done(struct tevent_req
*subreq
);
203 struct tevent_req
*tdgram_sendto_send(TALLOC_CTX
*mem_ctx
,
204 struct tevent_context
*ev
,
205 struct tdgram_context
*dgram
,
206 const uint8_t *buf
, size_t len
,
207 const struct tsocket_address
*dst
)
209 struct tevent_req
*req
;
210 struct tdgram_sendto_state
*state
;
211 struct tevent_req
*subreq
;
213 req
= tevent_req_create(mem_ctx
, &state
,
214 struct tdgram_sendto_state
);
219 state
->ops
= dgram
->ops
;
223 tevent_req_error(req
, EINVAL
);
227 subreq
= state
->ops
->sendto_send(state
, ev
, dgram
,
229 if (tevent_req_nomem(subreq
, req
)) {
232 tevent_req_set_callback(subreq
, tdgram_sendto_done
, req
);
237 tevent_req_post(req
, ev
);
241 static void tdgram_sendto_done(struct tevent_req
*subreq
)
243 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
245 struct tdgram_sendto_state
*state
= tevent_req_data(req
,
246 struct tdgram_sendto_state
);
250 ret
= state
->ops
->sendto_recv(subreq
, &sys_errno
);
252 tevent_req_error(req
, sys_errno
);
258 tevent_req_done(req
);
261 ssize_t
tdgram_sendto_recv(struct tevent_req
*req
,
264 struct tdgram_sendto_state
*state
= tevent_req_data(req
,
265 struct tdgram_sendto_state
);
268 ret
= tsocket_simple_int_recv(req
, perrno
);
273 tevent_req_received(req
);
277 struct tdgram_disconnect_state
{
278 const struct tdgram_context_ops
*ops
;
281 static void tdgram_disconnect_done(struct tevent_req
*subreq
);
283 struct tevent_req
*tdgram_disconnect_send(TALLOC_CTX
*mem_ctx
,
284 struct tevent_context
*ev
,
285 struct tdgram_context
*dgram
)
287 struct tevent_req
*req
;
288 struct tdgram_disconnect_state
*state
;
289 struct tevent_req
*subreq
;
291 req
= tevent_req_create(mem_ctx
, &state
,
292 struct tdgram_disconnect_state
);
297 state
->ops
= dgram
->ops
;
299 subreq
= state
->ops
->disconnect_send(state
, ev
, dgram
);
300 if (tevent_req_nomem(subreq
, req
)) {
303 tevent_req_set_callback(subreq
, tdgram_disconnect_done
, req
);
308 tevent_req_post(req
, ev
);
312 static void tdgram_disconnect_done(struct tevent_req
*subreq
)
314 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
316 struct tdgram_disconnect_state
*state
= tevent_req_data(req
,
317 struct tdgram_disconnect_state
);
321 ret
= state
->ops
->disconnect_recv(subreq
, &sys_errno
);
323 tevent_req_error(req
, sys_errno
);
327 tevent_req_done(req
);
330 int tdgram_disconnect_recv(struct tevent_req
*req
,
335 ret
= tsocket_simple_int_recv(req
, perrno
);
337 tevent_req_received(req
);
341 struct tdgram_sendto_queue_state
{
342 /* this structs are owned by the caller */
344 struct tevent_context
*ev
;
345 struct tdgram_context
*dgram
;
348 const struct tsocket_address
*dst
;
353 static void tdgram_sendto_queue_trigger(struct tevent_req
*req
,
355 static void tdgram_sendto_queue_done(struct tevent_req
*subreq
);
358 * @brief Queue a dgram blob for sending through the socket
359 * @param[in] mem_ctx The memory context for the result
360 * @param[in] ev The event context the operation should work on
361 * @param[in] dgram The tdgram_context to send the message buffer
362 * @param[in] queue The existing dgram queue
363 * @param[in] buf The message buffer
364 * @param[in] len The message length
365 * @param[in] dst The destination socket address
366 * @retval The async request handle
368 * This function queues a blob for sending to destination through an existing
369 * dgram socket. The async callback is triggered when the whole blob is
370 * delivered to the underlying system socket.
372 * The caller needs to make sure that all non-scalar input parameters hang
373 * arround for the whole lifetime of the request.
375 struct tevent_req
*tdgram_sendto_queue_send(TALLOC_CTX
*mem_ctx
,
376 struct tevent_context
*ev
,
377 struct tdgram_context
*dgram
,
378 struct tevent_queue
*queue
,
381 struct tsocket_address
*dst
)
383 struct tevent_req
*req
;
384 struct tdgram_sendto_queue_state
*state
;
387 req
= tevent_req_create(mem_ctx
, &state
,
388 struct tdgram_sendto_queue_state
);
393 state
->caller
.ev
= ev
;
394 state
->caller
.dgram
= dgram
;
395 state
->caller
.buf
= buf
;
396 state
->caller
.len
= len
;
397 state
->caller
.dst
= dst
;
400 ok
= tevent_queue_add(queue
,
403 tdgram_sendto_queue_trigger
,
406 tevent_req_nomem(NULL
, req
);
413 tevent_req_post(req
, ev
);
417 static void tdgram_sendto_queue_trigger(struct tevent_req
*req
,
420 struct tdgram_sendto_queue_state
*state
= tevent_req_data(req
,
421 struct tdgram_sendto_queue_state
);
422 struct tevent_req
*subreq
;
424 subreq
= tdgram_sendto_send(state
,
430 if (tevent_req_nomem(subreq
, req
)) {
433 tevent_req_set_callback(subreq
, tdgram_sendto_queue_done
, req
);
436 static void tdgram_sendto_queue_done(struct tevent_req
*subreq
)
438 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
440 struct tdgram_sendto_queue_state
*state
= tevent_req_data(req
,
441 struct tdgram_sendto_queue_state
);
445 ret
= tdgram_sendto_recv(subreq
, &sys_errno
);
448 tevent_req_error(req
, sys_errno
);
453 tevent_req_done(req
);
456 ssize_t
tdgram_sendto_queue_recv(struct tevent_req
*req
, int *perrno
)
458 struct tdgram_sendto_queue_state
*state
= tevent_req_data(req
,
459 struct tdgram_sendto_queue_state
);
462 ret
= tsocket_simple_int_recv(req
, perrno
);
467 tevent_req_received(req
);