2 Unix SMB/CIFS implementation.
4 Copyright (C) Volker Lendecke 2008
6 ** NOTE! The following LGPL license applies to the async_sock
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 Library General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "system/network.h"
26 #include "system/filesys.h"
29 #include "lib/async_req/async_sock.h"
31 /* Note: lib/util/ is currently GPL */
32 #include "lib/util/tevent_unix.h"
33 #include "lib/util/samba_util.h"
36 #define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0)
44 const struct sockaddr_storage
*addr
;
49 static void sendto_handler(struct tevent_context
*ev
,
50 struct tevent_fd
*fde
,
51 uint16_t flags
, void *private_data
);
53 struct tevent_req
*sendto_send(TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
54 int fd
, const void *buf
, size_t len
, int flags
,
55 const struct sockaddr_storage
*addr
)
57 struct tevent_req
*result
;
58 struct sendto_state
*state
;
59 struct tevent_fd
*fde
;
61 result
= tevent_req_create(mem_ctx
, &state
, struct sendto_state
);
71 switch (addr
->ss_family
) {
73 state
->addr_len
= sizeof(struct sockaddr_in
);
75 #if defined(HAVE_IPV6)
77 state
->addr_len
= sizeof(struct sockaddr_in6
);
81 state
->addr_len
= sizeof(struct sockaddr_un
);
84 state
->addr_len
= sizeof(struct sockaddr_storage
);
88 fde
= tevent_add_fd(ev
, state
, fd
, TEVENT_FD_WRITE
, sendto_handler
,
97 static void sendto_handler(struct tevent_context
*ev
,
98 struct tevent_fd
*fde
,
99 uint16_t flags
, void *private_data
)
101 struct tevent_req
*req
= talloc_get_type_abort(
102 private_data
, struct tevent_req
);
103 struct sendto_state
*state
=
104 tevent_req_data(req
, struct sendto_state
);
106 state
->sent
= sendto(state
->fd
, state
->buf
, state
->len
, state
->flags
,
107 (const struct sockaddr
*)state
->addr
,
109 if ((state
->sent
== -1) && (errno
== EINTR
)) {
113 if (state
->sent
== -1) {
114 tevent_req_error(req
, errno
);
117 tevent_req_done(req
);
120 ssize_t
sendto_recv(struct tevent_req
*req
, int *perrno
)
122 struct sendto_state
*state
=
123 tevent_req_data(req
, struct sendto_state
);
125 if (tevent_req_is_unix_error(req
, perrno
)) {
131 struct recvfrom_state
{
136 struct sockaddr_storage
*addr
;
141 static void recvfrom_handler(struct tevent_context
*ev
,
142 struct tevent_fd
*fde
,
143 uint16_t flags
, void *private_data
);
145 struct tevent_req
*recvfrom_send(TALLOC_CTX
*mem_ctx
,
146 struct tevent_context
*ev
,
147 int fd
, void *buf
, size_t len
, int flags
,
148 struct sockaddr_storage
*addr
,
151 struct tevent_req
*result
;
152 struct recvfrom_state
*state
;
153 struct tevent_fd
*fde
;
155 result
= tevent_req_create(mem_ctx
, &state
, struct recvfrom_state
);
156 if (result
== NULL
) {
162 state
->flags
= flags
;
164 state
->addr_len
= addr_len
;
166 fde
= tevent_add_fd(ev
, state
, fd
, TEVENT_FD_READ
, recvfrom_handler
,
175 static void recvfrom_handler(struct tevent_context
*ev
,
176 struct tevent_fd
*fde
,
177 uint16_t flags
, void *private_data
)
179 struct tevent_req
*req
= talloc_get_type_abort(
180 private_data
, struct tevent_req
);
181 struct recvfrom_state
*state
=
182 tevent_req_data(req
, struct recvfrom_state
);
184 state
->received
= recvfrom(state
->fd
, state
->buf
, state
->len
,
185 state
->flags
, (struct sockaddr
*)state
->addr
,
187 if ((state
->received
== -1) && (errno
== EINTR
)) {
191 if (state
->received
== 0) {
192 tevent_req_error(req
, EPIPE
);
195 if (state
->received
== -1) {
196 tevent_req_error(req
, errno
);
199 tevent_req_done(req
);
202 ssize_t
recvfrom_recv(struct tevent_req
*req
, int *perrno
)
204 struct recvfrom_state
*state
=
205 tevent_req_data(req
, struct recvfrom_state
);
207 if (tevent_req_is_unix_error(req
, perrno
)) {
210 return state
->received
;
213 struct async_connect_state
{
218 socklen_t address_len
;
219 struct sockaddr_storage address
;
222 static void async_connect_connected(struct tevent_context
*ev
,
223 struct tevent_fd
*fde
, uint16_t flags
,
227 * @brief async version of connect(2)
228 * @param[in] mem_ctx The memory context to hang the result off
229 * @param[in] ev The event context to work from
230 * @param[in] fd The socket to recv from
231 * @param[in] address Where to connect?
232 * @param[in] address_len Length of *address
233 * @retval The async request
235 * This function sets the socket into non-blocking state to be able to call
236 * connect in an async state. This will be reset when the request is finished.
239 struct tevent_req
*async_connect_send(TALLOC_CTX
*mem_ctx
,
240 struct tevent_context
*ev
,
241 int fd
, const struct sockaddr
*address
,
242 socklen_t address_len
)
244 struct tevent_req
*result
;
245 struct async_connect_state
*state
;
246 struct tevent_fd
*fde
;
248 result
= tevent_req_create(
249 mem_ctx
, &state
, struct async_connect_state
);
250 if (result
== NULL
) {
255 * We have to set the socket to nonblocking for async connect(2). Keep
256 * the old sockflags around.
260 state
->sys_errno
= 0;
262 state
->old_sockflags
= fcntl(fd
, F_GETFL
, 0);
263 if (state
->old_sockflags
== -1) {
267 state
->address_len
= address_len
;
268 if (address_len
> sizeof(state
->address
)) {
272 memcpy(&state
->address
, address
, address_len
);
274 set_blocking(fd
, false);
276 state
->result
= connect(fd
, address
, address_len
);
277 if (state
->result
== 0) {
278 tevent_req_done(result
);
283 * A number of error messages show that something good is progressing
284 * and that we have to wait for readability.
286 * If none of them are present, bail out.
289 if (!(errno
== EINPROGRESS
|| errno
== EALREADY
||
293 errno
== EAGAIN
|| errno
== EINTR
)) {
294 state
->sys_errno
= errno
;
298 fde
= tevent_add_fd(ev
, state
, fd
, TEVENT_FD_READ
| TEVENT_FD_WRITE
,
299 async_connect_connected
, result
);
301 state
->sys_errno
= ENOMEM
;
307 tevent_req_error(result
, state
->sys_errno
);
309 fcntl(fd
, F_SETFL
, state
->old_sockflags
);
310 return tevent_req_post(result
, ev
);
314 * fde event handler for connect(2)
315 * @param[in] ev The event context that sent us here
316 * @param[in] fde The file descriptor event associated with the connect
317 * @param[in] flags Indicate read/writeability of the socket
318 * @param[in] priv private data, "struct async_req *" in this case
321 static void async_connect_connected(struct tevent_context
*ev
,
322 struct tevent_fd
*fde
, uint16_t flags
,
325 struct tevent_req
*req
= talloc_get_type_abort(
326 priv
, struct tevent_req
);
327 struct async_connect_state
*state
=
328 tevent_req_data(req
, struct async_connect_state
);
331 ret
= connect(state
->fd
, (struct sockaddr
*)(void *)&state
->address
,
334 state
->sys_errno
= 0;
336 tevent_req_done(req
);
339 if (errno
== EINPROGRESS
) {
340 /* Try again later, leave the fde around */
343 state
->sys_errno
= errno
;
345 tevent_req_error(req
, errno
);
349 int async_connect_recv(struct tevent_req
*req
, int *perrno
)
351 struct async_connect_state
*state
=
352 tevent_req_data(req
, struct async_connect_state
);
355 fcntl(state
->fd
, F_SETFL
, state
->old_sockflags
);
357 if (tevent_req_is_unix_error(req
, &err
)) {
362 if (state
->sys_errno
== 0) {
366 *perrno
= state
->sys_errno
;
370 struct writev_state
{
371 struct tevent_context
*ev
;
377 bool err_on_readability
;
380 static void writev_trigger(struct tevent_req
*req
, void *private_data
);
381 static void writev_handler(struct tevent_context
*ev
, struct tevent_fd
*fde
,
382 uint16_t flags
, void *private_data
);
384 struct tevent_req
*writev_send(TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
385 struct tevent_queue
*queue
, int fd
,
386 bool err_on_readability
,
387 struct iovec
*iov
, int count
)
389 struct tevent_req
*req
;
390 struct writev_state
*state
;
392 req
= tevent_req_create(mem_ctx
, &state
, struct writev_state
);
398 state
->total_size
= 0;
399 state
->count
= count
;
400 state
->iov
= (struct iovec
*)talloc_memdup(
401 state
, iov
, sizeof(struct iovec
) * count
);
402 if (state
->iov
== NULL
) {
405 state
->flags
= TEVENT_FD_WRITE
|TEVENT_FD_READ
;
406 state
->err_on_readability
= err_on_readability
;
409 struct tevent_fd
*fde
;
410 fde
= tevent_add_fd(state
->ev
, state
, state
->fd
,
411 state
->flags
, writev_handler
, req
);
412 if (tevent_req_nomem(fde
, req
)) {
413 return tevent_req_post(req
, ev
);
418 if (!tevent_queue_add(queue
, ev
, req
, writev_trigger
, NULL
)) {
427 static void writev_trigger(struct tevent_req
*req
, void *private_data
)
429 struct writev_state
*state
= tevent_req_data(req
, struct writev_state
);
430 struct tevent_fd
*fde
;
432 fde
= tevent_add_fd(state
->ev
, state
, state
->fd
, state
->flags
,
433 writev_handler
, req
);
435 tevent_req_error(req
, ENOMEM
);
439 static void writev_handler(struct tevent_context
*ev
, struct tevent_fd
*fde
,
440 uint16_t flags
, void *private_data
)
442 struct tevent_req
*req
= talloc_get_type_abort(
443 private_data
, struct tevent_req
);
444 struct writev_state
*state
=
445 tevent_req_data(req
, struct writev_state
);
446 size_t to_write
, written
;
451 if ((state
->flags
& TEVENT_FD_READ
) && (flags
& TEVENT_FD_READ
)) {
454 if (state
->err_on_readability
) {
455 /* Readable and the caller wants an error on read. */
456 tevent_req_error(req
, EPIPE
);
460 /* Might be an error. Check if there are bytes to read */
461 ret
= ioctl(state
->fd
, FIONREAD
, &value
);
462 /* FIXME - should we also check
463 for ret == 0 and value == 0 here ? */
465 /* There's an error. */
466 tevent_req_error(req
, EPIPE
);
469 /* A request for TEVENT_FD_READ will succeed from now and
470 forevermore until the bytes are read so if there was
471 an error we'll wait until we do read, then get it in
472 the read callback function. Until then, remove TEVENT_FD_READ
473 from the flags we're waiting for. */
474 state
->flags
&= ~TEVENT_FD_READ
;
475 TEVENT_FD_NOT_READABLE(fde
);
477 /* If not writable, we're done. */
478 if (!(flags
& TEVENT_FD_WRITE
)) {
483 for (i
=0; i
<state
->count
; i
++) {
484 to_write
+= state
->iov
[i
].iov_len
;
487 written
= writev(state
->fd
, state
->iov
, state
->count
);
488 if ((written
== -1) && (errno
== EINTR
)) {
493 tevent_req_error(req
, errno
);
497 tevent_req_error(req
, EPIPE
);
500 state
->total_size
+= written
;
502 if (written
== to_write
) {
503 tevent_req_done(req
);
508 * We've written less than we were asked to, drop stuff from
512 while (written
> 0) {
513 if (written
< state
->iov
[0].iov_len
) {
514 state
->iov
[0].iov_base
=
515 (char *)state
->iov
[0].iov_base
+ written
;
516 state
->iov
[0].iov_len
-= written
;
519 written
-= state
->iov
[0].iov_len
;
525 ssize_t
writev_recv(struct tevent_req
*req
, int *perrno
)
527 struct writev_state
*state
=
528 tevent_req_data(req
, struct writev_state
);
530 if (tevent_req_is_unix_error(req
, perrno
)) {
533 return state
->total_size
;
536 struct read_packet_state
{
540 ssize_t (*more
)(uint8_t *buf
, size_t buflen
, void *private_data
);
544 static void read_packet_handler(struct tevent_context
*ev
,
545 struct tevent_fd
*fde
,
546 uint16_t flags
, void *private_data
);
548 struct tevent_req
*read_packet_send(TALLOC_CTX
*mem_ctx
,
549 struct tevent_context
*ev
,
550 int fd
, size_t initial
,
551 ssize_t (*more
)(uint8_t *buf
,
556 struct tevent_req
*result
;
557 struct read_packet_state
*state
;
558 struct tevent_fd
*fde
;
560 result
= tevent_req_create(mem_ctx
, &state
, struct read_packet_state
);
561 if (result
== NULL
) {
567 state
->private_data
= private_data
;
569 state
->buf
= talloc_array(state
, uint8_t, initial
);
570 if (state
->buf
== NULL
) {
574 fde
= tevent_add_fd(ev
, state
, fd
, TEVENT_FD_READ
, read_packet_handler
,
585 static void read_packet_handler(struct tevent_context
*ev
,
586 struct tevent_fd
*fde
,
587 uint16_t flags
, void *private_data
)
589 struct tevent_req
*req
= talloc_get_type_abort(
590 private_data
, struct tevent_req
);
591 struct read_packet_state
*state
=
592 tevent_req_data(req
, struct read_packet_state
);
593 size_t total
= talloc_get_size(state
->buf
);
597 nread
= recv(state
->fd
, state
->buf
+state
->nread
, total
-state
->nread
,
599 if ((nread
== -1) && (errno
== ENOTSOCK
)) {
600 nread
= read(state
->fd
, state
->buf
+state
->nread
,
603 if ((nread
== -1) && (errno
== EINTR
)) {
608 tevent_req_error(req
, errno
);
612 tevent_req_error(req
, EPIPE
);
616 state
->nread
+= nread
;
617 if (state
->nread
< total
) {
618 /* Come back later */
623 * We got what was initially requested. See if "more" asks for -- more.
625 if (state
->more
== NULL
) {
626 /* Nobody to ask, this is a async read_data */
627 tevent_req_done(req
);
631 more
= state
->more(state
->buf
, total
, state
->private_data
);
633 /* We got an invalid packet, tell the caller */
634 tevent_req_error(req
, EIO
);
638 /* We're done, full packet received */
639 tevent_req_done(req
);
643 if (total
+ more
< total
) {
644 tevent_req_error(req
, EMSGSIZE
);
648 tmp
= talloc_realloc(state
, state
->buf
, uint8_t, total
+more
);
649 if (tevent_req_nomem(tmp
, req
)) {
655 ssize_t
read_packet_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
656 uint8_t **pbuf
, int *perrno
)
658 struct read_packet_state
*state
=
659 tevent_req_data(req
, struct read_packet_state
);
661 if (tevent_req_is_unix_error(req
, perrno
)) {
664 *pbuf
= talloc_move(mem_ctx
, &state
->buf
);
665 return talloc_get_size(*pbuf
);
668 struct wait_for_read_state
{
669 struct tevent_req
*req
;
670 struct tevent_fd
*fde
;
673 static void wait_for_read_done(struct tevent_context
*ev
,
674 struct tevent_fd
*fde
,
678 struct tevent_req
*wait_for_read_send(TALLOC_CTX
*mem_ctx
,
679 struct tevent_context
*ev
,
682 struct tevent_req
*req
;
683 struct wait_for_read_state
*state
;
685 req
= tevent_req_create(mem_ctx
, &state
, struct wait_for_read_state
);
690 state
->fde
= tevent_add_fd(ev
, state
, fd
, TEVENT_FD_READ
,
691 wait_for_read_done
, state
);
692 if (tevent_req_nomem(state
->fde
, req
)) {
693 return tevent_req_post(req
, ev
);
698 static void wait_for_read_done(struct tevent_context
*ev
,
699 struct tevent_fd
*fde
,
703 struct wait_for_read_state
*state
= talloc_get_type_abort(
704 private_data
, struct wait_for_read_state
);
706 if (flags
& TEVENT_FD_READ
) {
707 TALLOC_FREE(state
->fde
);
708 tevent_req_done(state
->req
);
712 bool wait_for_read_recv(struct tevent_req
*req
, int *perr
)
716 if (tevent_req_is_unix_error(req
, &err
)) {