2 Unix SMB/CIFS implementation.
4 Copyright (C) Stefan Metzmacher 2009
6 ** NOTE! The following LGPL license applies to the tsocket
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/filesys.h"
27 #include "tsocket_internal.h"
29 int tsocket_simple_int_recv(struct tevent_req
*req
, int *perrno
)
31 enum tevent_req_state state
;
34 if (!tevent_req_is_error(req
, &state
, &error
)) {
39 case TEVENT_REQ_NO_MEMORY
:
42 case TEVENT_REQ_TIMED_OUT
:
45 case TEVENT_REQ_USER_ERROR
:
56 struct tsocket_address
*_tsocket_address_create(TALLOC_CTX
*mem_ctx
,
57 const struct tsocket_address_ops
*ops
,
63 void **ppstate
= (void **)pstate
;
64 struct tsocket_address
*addr
;
66 addr
= talloc_zero(mem_ctx
, struct tsocket_address
);
71 addr
->location
= location
;
72 addr
->private_data
= talloc_size(addr
, psize
);
73 if (!addr
->private_data
) {
77 talloc_set_name_const(addr
->private_data
, type
);
79 *ppstate
= addr
->private_data
;
83 char *tsocket_address_string(const struct tsocket_address
*addr
,
87 return talloc_strdup(mem_ctx
, "NULL");
89 return addr
->ops
->string(addr
, mem_ctx
);
92 struct tsocket_address
*_tsocket_address_copy(const struct tsocket_address
*addr
,
96 return addr
->ops
->copy(addr
, mem_ctx
, location
);
99 struct tdgram_context
{
100 const char *location
;
101 const struct tdgram_context_ops
*ops
;
104 struct tevent_req
*recvfrom_req
;
105 struct tevent_req
*sendto_req
;
108 static int tdgram_context_destructor(struct tdgram_context
*dgram
)
110 if (dgram
->recvfrom_req
) {
111 tevent_req_received(dgram
->recvfrom_req
);
114 if (dgram
->sendto_req
) {
115 tevent_req_received(dgram
->sendto_req
);
121 struct tdgram_context
*_tdgram_context_create(TALLOC_CTX
*mem_ctx
,
122 const struct tdgram_context_ops
*ops
,
126 const char *location
)
128 struct tdgram_context
*dgram
;
129 void **ppstate
= (void **)pstate
;
132 dgram
= talloc(mem_ctx
, struct tdgram_context
);
136 dgram
->location
= location
;
138 dgram
->recvfrom_req
= NULL
;
139 dgram
->sendto_req
= NULL
;
141 state
= talloc_size(dgram
, psize
);
146 talloc_set_name_const(state
, type
);
148 dgram
->private_data
= state
;
150 talloc_set_destructor(dgram
, tdgram_context_destructor
);
156 void *_tdgram_context_data(struct tdgram_context
*dgram
)
158 return dgram
->private_data
;
161 struct tdgram_recvfrom_state
{
162 const struct tdgram_context_ops
*ops
;
163 struct tdgram_context
*dgram
;
166 struct tsocket_address
*src
;
169 static int tdgram_recvfrom_destructor(struct tdgram_recvfrom_state
*state
)
172 state
->dgram
->recvfrom_req
= NULL
;
178 static void tdgram_recvfrom_done(struct tevent_req
*subreq
);
180 struct tevent_req
*tdgram_recvfrom_send(TALLOC_CTX
*mem_ctx
,
181 struct tevent_context
*ev
,
182 struct tdgram_context
*dgram
)
184 struct tevent_req
*req
;
185 struct tdgram_recvfrom_state
*state
;
186 struct tevent_req
*subreq
;
188 req
= tevent_req_create(mem_ctx
, &state
,
189 struct tdgram_recvfrom_state
);
194 state
->ops
= dgram
->ops
;
195 state
->dgram
= dgram
;
200 if (dgram
->recvfrom_req
) {
201 tevent_req_error(req
, EBUSY
);
204 dgram
->recvfrom_req
= req
;
206 talloc_set_destructor(state
, tdgram_recvfrom_destructor
);
208 subreq
= state
->ops
->recvfrom_send(state
, ev
, dgram
);
209 if (tevent_req_nomem(subreq
, req
)) {
212 tevent_req_set_callback(subreq
, tdgram_recvfrom_done
, req
);
217 tevent_req_post(req
, ev
);
221 static void tdgram_recvfrom_done(struct tevent_req
*subreq
)
223 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
225 struct tdgram_recvfrom_state
*state
= tevent_req_data(req
,
226 struct tdgram_recvfrom_state
);
230 ret
= state
->ops
->recvfrom_recv(subreq
, &sys_errno
, state
,
231 &state
->buf
, &state
->src
);
233 tevent_req_error(req
, sys_errno
);
239 tevent_req_done(req
);
242 ssize_t
tdgram_recvfrom_recv(struct tevent_req
*req
,
246 struct tsocket_address
**src
)
248 struct tdgram_recvfrom_state
*state
= tevent_req_data(req
,
249 struct tdgram_recvfrom_state
);
252 ret
= tsocket_simple_int_recv(req
, perrno
);
254 *buf
= talloc_move(mem_ctx
, &state
->buf
);
257 *src
= talloc_move(mem_ctx
, &state
->src
);
261 tevent_req_received(req
);
265 struct tdgram_sendto_state
{
266 const struct tdgram_context_ops
*ops
;
267 struct tdgram_context
*dgram
;
271 static int tdgram_sendto_destructor(struct tdgram_sendto_state
*state
)
274 state
->dgram
->sendto_req
= NULL
;
280 static void tdgram_sendto_done(struct tevent_req
*subreq
);
282 struct tevent_req
*tdgram_sendto_send(TALLOC_CTX
*mem_ctx
,
283 struct tevent_context
*ev
,
284 struct tdgram_context
*dgram
,
285 const uint8_t *buf
, size_t len
,
286 const struct tsocket_address
*dst
)
288 struct tevent_req
*req
;
289 struct tdgram_sendto_state
*state
;
290 struct tevent_req
*subreq
;
292 req
= tevent_req_create(mem_ctx
, &state
,
293 struct tdgram_sendto_state
);
298 state
->ops
= dgram
->ops
;
299 state
->dgram
= dgram
;
303 tevent_req_error(req
, EINVAL
);
307 if (dgram
->sendto_req
) {
308 tevent_req_error(req
, EBUSY
);
311 dgram
->sendto_req
= req
;
313 talloc_set_destructor(state
, tdgram_sendto_destructor
);
315 subreq
= state
->ops
->sendto_send(state
, ev
, dgram
,
317 if (tevent_req_nomem(subreq
, req
)) {
320 tevent_req_set_callback(subreq
, tdgram_sendto_done
, req
);
325 tevent_req_post(req
, ev
);
329 static void tdgram_sendto_done(struct tevent_req
*subreq
)
331 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
333 struct tdgram_sendto_state
*state
= tevent_req_data(req
,
334 struct tdgram_sendto_state
);
338 ret
= state
->ops
->sendto_recv(subreq
, &sys_errno
);
340 tevent_req_error(req
, sys_errno
);
346 tevent_req_done(req
);
349 ssize_t
tdgram_sendto_recv(struct tevent_req
*req
,
352 struct tdgram_sendto_state
*state
= tevent_req_data(req
,
353 struct tdgram_sendto_state
);
356 ret
= tsocket_simple_int_recv(req
, perrno
);
361 tevent_req_received(req
);
365 struct tdgram_disconnect_state
{
366 const struct tdgram_context_ops
*ops
;
369 static void tdgram_disconnect_done(struct tevent_req
*subreq
);
371 struct tevent_req
*tdgram_disconnect_send(TALLOC_CTX
*mem_ctx
,
372 struct tevent_context
*ev
,
373 struct tdgram_context
*dgram
)
375 struct tevent_req
*req
;
376 struct tdgram_disconnect_state
*state
;
377 struct tevent_req
*subreq
;
379 req
= tevent_req_create(mem_ctx
, &state
,
380 struct tdgram_disconnect_state
);
385 state
->ops
= dgram
->ops
;
387 if (dgram
->recvfrom_req
|| dgram
->sendto_req
) {
388 tevent_req_error(req
, EBUSY
);
392 subreq
= state
->ops
->disconnect_send(state
, ev
, dgram
);
393 if (tevent_req_nomem(subreq
, req
)) {
396 tevent_req_set_callback(subreq
, tdgram_disconnect_done
, req
);
401 tevent_req_post(req
, ev
);
405 static void tdgram_disconnect_done(struct tevent_req
*subreq
)
407 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
409 struct tdgram_disconnect_state
*state
= tevent_req_data(req
,
410 struct tdgram_disconnect_state
);
414 ret
= state
->ops
->disconnect_recv(subreq
, &sys_errno
);
416 tevent_req_error(req
, sys_errno
);
420 tevent_req_done(req
);
423 int tdgram_disconnect_recv(struct tevent_req
*req
,
428 ret
= tsocket_simple_int_recv(req
, perrno
);
430 tevent_req_received(req
);
434 struct tstream_context
{
435 const char *location
;
436 const struct tstream_context_ops
*ops
;
439 struct tevent_req
*readv_req
;
440 struct tevent_req
*writev_req
;
443 static int tstream_context_destructor(struct tstream_context
*stream
)
445 if (stream
->readv_req
) {
446 tevent_req_received(stream
->readv_req
);
449 if (stream
->writev_req
) {
450 tevent_req_received(stream
->writev_req
);
456 struct tstream_context
*_tstream_context_create(TALLOC_CTX
*mem_ctx
,
457 const struct tstream_context_ops
*ops
,
461 const char *location
)
463 struct tstream_context
*stream
;
464 void **ppstate
= (void **)pstate
;
467 stream
= talloc(mem_ctx
, struct tstream_context
);
468 if (stream
== NULL
) {
471 stream
->location
= location
;
473 stream
->readv_req
= NULL
;
474 stream
->writev_req
= NULL
;
476 state
= talloc_size(stream
, psize
);
481 talloc_set_name_const(state
, type
);
483 stream
->private_data
= state
;
485 talloc_set_destructor(stream
, tstream_context_destructor
);
491 void *_tstream_context_data(struct tstream_context
*stream
)
493 return stream
->private_data
;
496 ssize_t
tstream_pending_bytes(struct tstream_context
*stream
)
498 return stream
->ops
->pending_bytes(stream
);
501 struct tstream_readv_state
{
502 const struct tstream_context_ops
*ops
;
503 struct tstream_context
*stream
;
507 static int tstream_readv_destructor(struct tstream_readv_state
*state
)
510 state
->stream
->readv_req
= NULL
;
516 static void tstream_readv_done(struct tevent_req
*subreq
);
518 struct tevent_req
*tstream_readv_send(TALLOC_CTX
*mem_ctx
,
519 struct tevent_context
*ev
,
520 struct tstream_context
*stream
,
521 struct iovec
*vector
,
524 struct tevent_req
*req
;
525 struct tstream_readv_state
*state
;
526 struct tevent_req
*subreq
;
530 req
= tevent_req_create(mem_ctx
, &state
,
531 struct tstream_readv_state
);
536 state
->ops
= stream
->ops
;
537 state
->stream
= stream
;
540 /* first check if the input is ok */
542 if (count
> IOV_MAX
) {
543 tevent_req_error(req
, EMSGSIZE
);
548 for (i
=0; i
< count
; i
++) {
550 tmp
+= vector
[i
].iov_len
;
553 tevent_req_error(req
, EMSGSIZE
);
561 tevent_req_error(req
, EINVAL
);
565 if (stream
->readv_req
) {
566 tevent_req_error(req
, EBUSY
);
569 stream
->readv_req
= req
;
571 talloc_set_destructor(state
, tstream_readv_destructor
);
573 subreq
= state
->ops
->readv_send(state
, ev
, stream
, vector
, count
);
574 if (tevent_req_nomem(subreq
, req
)) {
577 tevent_req_set_callback(subreq
, tstream_readv_done
, req
);
582 tevent_req_post(req
, ev
);
586 static void tstream_readv_done(struct tevent_req
*subreq
)
588 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
590 struct tstream_readv_state
*state
= tevent_req_data(req
,
591 struct tstream_readv_state
);
595 ret
= state
->ops
->readv_recv(subreq
, &sys_errno
);
598 tevent_req_error(req
, sys_errno
);
604 tevent_req_done(req
);
607 int tstream_readv_recv(struct tevent_req
*req
,
610 struct tstream_readv_state
*state
= tevent_req_data(req
,
611 struct tstream_readv_state
);
614 ret
= tsocket_simple_int_recv(req
, perrno
);
619 tevent_req_received(req
);
623 struct tstream_writev_state
{
624 const struct tstream_context_ops
*ops
;
625 struct tstream_context
*stream
;
629 static int tstream_writev_destructor(struct tstream_writev_state
*state
)
632 state
->stream
->writev_req
= NULL
;
638 static void tstream_writev_done(struct tevent_req
*subreq
);
640 struct tevent_req
*tstream_writev_send(TALLOC_CTX
*mem_ctx
,
641 struct tevent_context
*ev
,
642 struct tstream_context
*stream
,
643 const struct iovec
*vector
,
646 struct tevent_req
*req
;
647 struct tstream_writev_state
*state
;
648 struct tevent_req
*subreq
;
652 req
= tevent_req_create(mem_ctx
, &state
,
653 struct tstream_writev_state
);
658 state
->ops
= stream
->ops
;
659 state
->stream
= stream
;
662 /* first check if the input is ok */
664 if (count
> IOV_MAX
) {
665 tevent_req_error(req
, EMSGSIZE
);
670 for (i
=0; i
< count
; i
++) {
672 tmp
+= vector
[i
].iov_len
;
674 if (tmp
< to_write
) {
675 tevent_req_error(req
, EMSGSIZE
);
683 tevent_req_error(req
, EINVAL
);
687 if (stream
->writev_req
) {
688 tevent_req_error(req
, EBUSY
);
691 stream
->writev_req
= req
;
693 talloc_set_destructor(state
, tstream_writev_destructor
);
695 subreq
= state
->ops
->writev_send(state
, ev
, stream
, vector
, count
);
696 if (tevent_req_nomem(subreq
, req
)) {
699 tevent_req_set_callback(subreq
, tstream_writev_done
, req
);
704 tevent_req_post(req
, ev
);
708 static void tstream_writev_done(struct tevent_req
*subreq
)
710 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
712 struct tstream_writev_state
*state
= tevent_req_data(req
,
713 struct tstream_writev_state
);
717 ret
= state
->ops
->writev_recv(subreq
, &sys_errno
);
719 tevent_req_error(req
, sys_errno
);
725 tevent_req_done(req
);
728 int tstream_writev_recv(struct tevent_req
*req
,
731 struct tstream_writev_state
*state
= tevent_req_data(req
,
732 struct tstream_writev_state
);
735 ret
= tsocket_simple_int_recv(req
, perrno
);
740 tevent_req_received(req
);
744 struct tstream_disconnect_state
{
745 const struct tstream_context_ops
*ops
;
748 static void tstream_disconnect_done(struct tevent_req
*subreq
);
750 struct tevent_req
*tstream_disconnect_send(TALLOC_CTX
*mem_ctx
,
751 struct tevent_context
*ev
,
752 struct tstream_context
*stream
)
754 struct tevent_req
*req
;
755 struct tstream_disconnect_state
*state
;
756 struct tevent_req
*subreq
;
758 req
= tevent_req_create(mem_ctx
, &state
,
759 struct tstream_disconnect_state
);
764 state
->ops
= stream
->ops
;
766 if (stream
->readv_req
|| stream
->writev_req
) {
767 tevent_req_error(req
, EBUSY
);
771 subreq
= state
->ops
->disconnect_send(state
, ev
, stream
);
772 if (tevent_req_nomem(subreq
, req
)) {
775 tevent_req_set_callback(subreq
, tstream_disconnect_done
, req
);
780 tevent_req_post(req
, ev
);
784 static void tstream_disconnect_done(struct tevent_req
*subreq
)
786 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
788 struct tstream_disconnect_state
*state
= tevent_req_data(req
,
789 struct tstream_disconnect_state
);
793 ret
= state
->ops
->disconnect_recv(subreq
, &sys_errno
);
795 tevent_req_error(req
, sys_errno
);
799 tevent_req_done(req
);
802 int tstream_disconnect_recv(struct tevent_req
*req
,
807 ret
= tsocket_simple_int_recv(req
, perrno
);
809 tevent_req_received(req
);