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 static int tsocket_context_destructor(struct tsocket_context
*sock
)
31 tsocket_disconnect(sock
);
35 struct tsocket_context
*_tsocket_context_create(TALLOC_CTX
*mem_ctx
,
36 const struct tsocket_context_ops
*ops
,
42 void **ppstate
= (void **)pstate
;
43 struct tsocket_context
*sock
;
45 sock
= talloc_zero(mem_ctx
, struct tsocket_context
);
50 sock
->location
= location
;
51 sock
->private_data
= talloc_size(sock
, psize
);
52 if (!sock
->private_data
) {
56 talloc_set_name_const(sock
->private_data
, type
);
58 talloc_set_destructor(sock
, tsocket_context_destructor
);
60 *ppstate
= sock
->private_data
;
64 int tsocket_set_event_context(struct tsocket_context
*sock
,
65 struct tevent_context
*ev
)
67 return sock
->ops
->set_event_context(sock
, ev
);
70 int tsocket_set_readable_handler(struct tsocket_context
*sock
,
71 tsocket_event_handler_t handler
,
74 return sock
->ops
->set_read_handler(sock
, handler
, private_data
);
77 int tsocket_set_writeable_handler(struct tsocket_context
*sock
,
78 tsocket_event_handler_t handler
,
81 return sock
->ops
->set_write_handler(sock
, handler
, private_data
);
84 int tsocket_connect(struct tsocket_context
*sock
,
85 const struct tsocket_address
*remote_addr
)
87 return sock
->ops
->connect_to(sock
, remote_addr
);
90 int tsocket_listen(struct tsocket_context
*sock
,
93 return sock
->ops
->listen_on(sock
, queue_size
);
96 int _tsocket_accept(struct tsocket_context
*sock
,
98 struct tsocket_context
**new_sock
,
101 return sock
->ops
->accept_new(sock
, mem_ctx
, new_sock
, location
);
104 ssize_t
tsocket_pending(struct tsocket_context
*sock
)
106 return sock
->ops
->pending_data(sock
);
109 int tsocket_readv(struct tsocket_context
*sock
,
110 const struct iovec
*vector
, size_t count
)
112 return sock
->ops
->readv_data(sock
, vector
, count
);
115 int tsocket_writev(struct tsocket_context
*sock
,
116 const struct iovec
*vector
, size_t count
)
118 return sock
->ops
->writev_data(sock
, vector
, count
);
121 int tsocket_get_status(const struct tsocket_context
*sock
)
123 return sock
->ops
->get_status(sock
);
126 int _tsocket_get_local_address(const struct tsocket_context
*sock
,
128 struct tsocket_address
**local_addr
,
129 const char *location
)
131 return sock
->ops
->get_local_address(sock
, mem_ctx
,
132 local_addr
, location
);
135 int _tsocket_get_remote_address(const struct tsocket_context
*sock
,
137 struct tsocket_address
**remote_addr
,
138 const char *location
)
140 return sock
->ops
->get_remote_address(sock
, mem_ctx
,
141 remote_addr
, location
);
144 int tsocket_get_option(const struct tsocket_context
*sock
,
149 return sock
->ops
->get_option(sock
, option
, mem_ctx
, value
);
152 int tsocket_set_option(const struct tsocket_context
*sock
,
157 return sock
->ops
->set_option(sock
, option
, force
, value
);
160 void tsocket_disconnect(struct tsocket_context
*sock
)
162 sock
->ops
->disconnect(sock
);
165 struct tsocket_address
*_tsocket_address_create(TALLOC_CTX
*mem_ctx
,
166 const struct tsocket_address_ops
*ops
,
170 const char *location
)
172 void **ppstate
= (void **)pstate
;
173 struct tsocket_address
*addr
;
175 addr
= talloc_zero(mem_ctx
, struct tsocket_address
);
180 addr
->location
= location
;
181 addr
->private_data
= talloc_size(addr
, psize
);
182 if (!addr
->private_data
) {
186 talloc_set_name_const(addr
->private_data
, type
);
188 *ppstate
= addr
->private_data
;
192 char *tsocket_address_string(const struct tsocket_address
*addr
,
196 return talloc_strdup(mem_ctx
, "NULL");
198 return addr
->ops
->string(addr
, mem_ctx
);
201 struct tsocket_address
*_tsocket_address_copy(const struct tsocket_address
*addr
,
203 const char *location
)
205 return addr
->ops
->copy(addr
, mem_ctx
, location
);
208 int _tsocket_address_create_socket(const struct tsocket_address
*addr
,
209 enum tsocket_type type
,
211 struct tsocket_context
**sock
,
212 const char *location
)
214 return addr
->ops
->create_socket(addr
, type
, mem_ctx
, sock
, location
);
217 struct tdgram_context
{
218 const char *location
;
219 const struct tdgram_context_ops
*ops
;
223 struct tdgram_context
*_tdgram_context_create(TALLOC_CTX
*mem_ctx
,
224 const struct tdgram_context_ops
*ops
,
228 const char *location
)
230 struct tdgram_context
*dgram
;
231 void **ppstate
= (void **)pstate
;
234 dgram
= talloc(mem_ctx
, struct tdgram_context
);
238 dgram
->location
= location
;
241 state
= talloc_size(dgram
, psize
);
246 talloc_set_name_const(state
, type
);
248 dgram
->private_data
= state
;
254 void *_tdgram_context_data(struct tdgram_context
*dgram
)
256 return dgram
->private_data
;
259 struct tdgram_recvfrom_state
{
260 const struct tdgram_context_ops
*ops
;
263 struct tsocket_address
*src
;
266 static void tdgram_recvfrom_done(struct tevent_req
*subreq
);
268 struct tevent_req
*tdgram_recvfrom_send(TALLOC_CTX
*mem_ctx
,
269 struct tevent_context
*ev
,
270 struct tdgram_context
*dgram
)
272 struct tevent_req
*req
;
273 struct tdgram_recvfrom_state
*state
;
274 struct tevent_req
*subreq
;
276 req
= tevent_req_create(mem_ctx
, &state
,
277 struct tdgram_recvfrom_state
);
282 state
->ops
= dgram
->ops
;
284 subreq
= state
->ops
->recvfrom_send(state
, ev
, dgram
);
285 if (tevent_req_nomem(subreq
, req
)) {
288 tevent_req_set_callback(subreq
, tdgram_recvfrom_done
, req
);
293 tevent_req_post(req
, ev
);
297 static void tdgram_recvfrom_done(struct tevent_req
*subreq
)
299 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
301 struct tdgram_recvfrom_state
*state
= tevent_req_data(req
,
302 struct tdgram_recvfrom_state
);
306 ret
= state
->ops
->recvfrom_recv(subreq
, &sys_errno
, state
,
307 &state
->buf
, &state
->src
);
309 tevent_req_error(req
, sys_errno
);
315 tevent_req_done(req
);
318 ssize_t
tdgram_recvfrom_recv(struct tevent_req
*req
,
322 struct tsocket_address
**src
)
324 struct tdgram_recvfrom_state
*state
= tevent_req_data(req
,
325 struct tdgram_recvfrom_state
);
328 ret
= tsocket_simple_int_recv(req
, perrno
);
330 *buf
= talloc_move(mem_ctx
, &state
->buf
);
333 *src
= talloc_move(mem_ctx
, &state
->src
);
337 tevent_req_received(req
);
341 struct tdgram_sendto_state
{
342 const struct tdgram_context_ops
*ops
;
346 static void tdgram_sendto_done(struct tevent_req
*subreq
);
348 struct tevent_req
*tdgram_sendto_send(TALLOC_CTX
*mem_ctx
,
349 struct tevent_context
*ev
,
350 struct tdgram_context
*dgram
,
351 const uint8_t *buf
, size_t len
,
352 const struct tsocket_address
*dst
)
354 struct tevent_req
*req
;
355 struct tdgram_sendto_state
*state
;
356 struct tevent_req
*subreq
;
358 req
= tevent_req_create(mem_ctx
, &state
,
359 struct tdgram_sendto_state
);
364 state
->ops
= dgram
->ops
;
367 subreq
= state
->ops
->sendto_send(state
, ev
, dgram
,
369 if (tevent_req_nomem(subreq
, req
)) {
372 tevent_req_set_callback(subreq
, tdgram_sendto_done
, req
);
377 tevent_req_post(req
, ev
);
381 static void tdgram_sendto_done(struct tevent_req
*subreq
)
383 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
385 struct tdgram_sendto_state
*state
= tevent_req_data(req
,
386 struct tdgram_sendto_state
);
390 ret
= state
->ops
->sendto_recv(subreq
, &sys_errno
);
392 tevent_req_error(req
, sys_errno
);
398 tevent_req_done(req
);
401 ssize_t
tdgram_sendto_recv(struct tevent_req
*req
,
404 struct tdgram_sendto_state
*state
= tevent_req_data(req
,
405 struct tdgram_sendto_state
);
408 ret
= tsocket_simple_int_recv(req
, perrno
);
413 tevent_req_received(req
);
417 struct tdgram_disconnect_state
{
418 const struct tdgram_context_ops
*ops
;
421 static void tdgram_disconnect_done(struct tevent_req
*subreq
);
423 struct tevent_req
*tdgram_disconnect_send(TALLOC_CTX
*mem_ctx
,
424 struct tevent_context
*ev
,
425 struct tdgram_context
*dgram
)
427 struct tevent_req
*req
;
428 struct tdgram_disconnect_state
*state
;
429 struct tevent_req
*subreq
;
431 req
= tevent_req_create(mem_ctx
, &state
,
432 struct tdgram_disconnect_state
);
437 state
->ops
= dgram
->ops
;
439 subreq
= state
->ops
->disconnect_send(state
, ev
, dgram
);
440 if (tevent_req_nomem(subreq
, req
)) {
443 tevent_req_set_callback(subreq
, tdgram_disconnect_done
, req
);
448 tevent_req_post(req
, ev
);
452 static void tdgram_disconnect_done(struct tevent_req
*subreq
)
454 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
456 struct tdgram_disconnect_state
*state
= tevent_req_data(req
,
457 struct tdgram_disconnect_state
);
461 ret
= state
->ops
->disconnect_recv(subreq
, &sys_errno
);
463 tevent_req_error(req
, sys_errno
);
467 tevent_req_done(req
);
470 int tdgram_disconnect_recv(struct tevent_req
*req
,
475 ret
= tsocket_simple_int_recv(req
, perrno
);
477 tevent_req_received(req
);
481 struct tdgram_sendto_queue_state
{
482 /* this structs are owned by the caller */
484 struct tevent_context
*ev
;
485 struct tdgram_context
*dgram
;
488 const struct tsocket_address
*dst
;
493 static void tdgram_sendto_queue_trigger(struct tevent_req
*req
,
495 static void tdgram_sendto_queue_done(struct tevent_req
*subreq
);
498 * @brief Queue a dgram blob for sending through the socket
499 * @param[in] mem_ctx The memory context for the result
500 * @param[in] ev The event context the operation should work on
501 * @param[in] dgram The tdgram_context to send the message buffer
502 * @param[in] queue The existing dgram queue
503 * @param[in] buf The message buffer
504 * @param[in] len The message length
505 * @param[in] dst The destination socket address
506 * @retval The async request handle
508 * This function queues a blob for sending to destination through an existing
509 * dgram socket. The async callback is triggered when the whole blob is
510 * delivered to the underlying system socket.
512 * The caller needs to make sure that all non-scalar input parameters hang
513 * arround for the whole lifetime of the request.
515 struct tevent_req
*tdgram_sendto_queue_send(TALLOC_CTX
*mem_ctx
,
516 struct tevent_context
*ev
,
517 struct tdgram_context
*dgram
,
518 struct tevent_queue
*queue
,
521 struct tsocket_address
*dst
)
523 struct tevent_req
*req
;
524 struct tdgram_sendto_queue_state
*state
;
527 req
= tevent_req_create(mem_ctx
, &state
,
528 struct tdgram_sendto_queue_state
);
533 state
->caller
.ev
= ev
;
534 state
->caller
.dgram
= dgram
;
535 state
->caller
.buf
= buf
;
536 state
->caller
.len
= len
;
537 state
->caller
.dst
= dst
;
540 ok
= tevent_queue_add(queue
,
543 tdgram_sendto_queue_trigger
,
546 tevent_req_nomem(NULL
, req
);
553 tevent_req_post(req
, ev
);
557 static void tdgram_sendto_queue_trigger(struct tevent_req
*req
,
560 struct tdgram_sendto_queue_state
*state
= tevent_req_data(req
,
561 struct tdgram_sendto_queue_state
);
562 struct tevent_req
*subreq
;
564 subreq
= tdgram_sendto_send(state
,
570 if (tevent_req_nomem(subreq
, req
)) {
573 tevent_req_set_callback(subreq
, tdgram_sendto_queue_done
, req
);
576 static void tdgram_sendto_queue_done(struct tevent_req
*subreq
)
578 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
580 struct tdgram_sendto_queue_state
*state
= tevent_req_data(req
,
581 struct tdgram_sendto_queue_state
);
585 ret
= tdgram_sendto_recv(subreq
, &sys_errno
);
588 tevent_req_error(req
, sys_errno
);
593 tevent_req_done(req
);
596 ssize_t
tdgram_sendto_queue_recv(struct tevent_req
*req
, int *perrno
)
598 struct tdgram_sendto_queue_state
*state
= tevent_req_data(req
,
599 struct tdgram_sendto_queue_state
);
602 ret
= tsocket_simple_int_recv(req
, perrno
);
607 tevent_req_received(req
);