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/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 * Stevens, Network Programming says that if there's a
332 * successful connect, the socket is only writable. Upon an
333 * error, it's both readable and writable.
335 if ((flags
& (TEVENT_FD_READ
|TEVENT_FD_WRITE
))
336 == (TEVENT_FD_READ
|TEVENT_FD_WRITE
)) {
339 ret
= connect(state
->fd
,
340 (struct sockaddr
*)(void *)&state
->address
,
344 tevent_req_done(req
);
348 if (errno
== EINPROGRESS
) {
349 /* Try again later, leave the fde around */
353 tevent_req_error(req
, errno
);
357 state
->sys_errno
= 0;
358 tevent_req_done(req
);
361 int async_connect_recv(struct tevent_req
*req
, int *perrno
)
363 struct async_connect_state
*state
=
364 tevent_req_data(req
, struct async_connect_state
);
367 fcntl(state
->fd
, F_SETFL
, state
->old_sockflags
);
369 if (tevent_req_is_unix_error(req
, &err
)) {
374 if (state
->sys_errno
== 0) {
378 *perrno
= state
->sys_errno
;
382 struct writev_state
{
383 struct tevent_context
*ev
;
389 bool err_on_readability
;
392 static void writev_trigger(struct tevent_req
*req
, void *private_data
);
393 static void writev_handler(struct tevent_context
*ev
, struct tevent_fd
*fde
,
394 uint16_t flags
, void *private_data
);
396 struct tevent_req
*writev_send(TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
397 struct tevent_queue
*queue
, int fd
,
398 bool err_on_readability
,
399 struct iovec
*iov
, int count
)
401 struct tevent_req
*req
;
402 struct writev_state
*state
;
404 req
= tevent_req_create(mem_ctx
, &state
, struct writev_state
);
410 state
->total_size
= 0;
411 state
->count
= count
;
412 state
->iov
= (struct iovec
*)talloc_memdup(
413 state
, iov
, sizeof(struct iovec
) * count
);
414 if (state
->iov
== NULL
) {
417 state
->flags
= TEVENT_FD_WRITE
|TEVENT_FD_READ
;
418 state
->err_on_readability
= err_on_readability
;
421 struct tevent_fd
*fde
;
422 fde
= tevent_add_fd(state
->ev
, state
, state
->fd
,
423 state
->flags
, writev_handler
, req
);
424 if (tevent_req_nomem(fde
, req
)) {
425 return tevent_req_post(req
, ev
);
430 if (!tevent_queue_add(queue
, ev
, req
, writev_trigger
, NULL
)) {
439 static void writev_trigger(struct tevent_req
*req
, void *private_data
)
441 struct writev_state
*state
= tevent_req_data(req
, struct writev_state
);
442 struct tevent_fd
*fde
;
444 fde
= tevent_add_fd(state
->ev
, state
, state
->fd
, state
->flags
,
445 writev_handler
, req
);
447 tevent_req_error(req
, ENOMEM
);
451 static void writev_handler(struct tevent_context
*ev
, struct tevent_fd
*fde
,
452 uint16_t flags
, void *private_data
)
454 struct tevent_req
*req
= talloc_get_type_abort(
455 private_data
, struct tevent_req
);
456 struct writev_state
*state
=
457 tevent_req_data(req
, struct writev_state
);
458 size_t to_write
, written
;
463 if ((state
->flags
& TEVENT_FD_READ
) && (flags
& TEVENT_FD_READ
)) {
466 if (state
->err_on_readability
) {
467 /* Readable and the caller wants an error on read. */
468 tevent_req_error(req
, EPIPE
);
472 /* Might be an error. Check if there are bytes to read */
473 ret
= ioctl(state
->fd
, FIONREAD
, &value
);
474 /* FIXME - should we also check
475 for ret == 0 and value == 0 here ? */
477 /* There's an error. */
478 tevent_req_error(req
, EPIPE
);
481 /* A request for TEVENT_FD_READ will succeed from now and
482 forevermore until the bytes are read so if there was
483 an error we'll wait until we do read, then get it in
484 the read callback function. Until then, remove TEVENT_FD_READ
485 from the flags we're waiting for. */
486 state
->flags
&= ~TEVENT_FD_READ
;
487 TEVENT_FD_NOT_READABLE(fde
);
489 /* If not writable, we're done. */
490 if (!(flags
& TEVENT_FD_WRITE
)) {
495 for (i
=0; i
<state
->count
; i
++) {
496 to_write
+= state
->iov
[i
].iov_len
;
499 written
= writev(state
->fd
, state
->iov
, state
->count
);
500 if ((written
== -1) && (errno
== EINTR
)) {
505 tevent_req_error(req
, errno
);
509 tevent_req_error(req
, EPIPE
);
512 state
->total_size
+= written
;
514 if (written
== to_write
) {
515 tevent_req_done(req
);
520 * We've written less than we were asked to, drop stuff from
524 while (written
> 0) {
525 if (written
< state
->iov
[0].iov_len
) {
526 state
->iov
[0].iov_base
=
527 (char *)state
->iov
[0].iov_base
+ written
;
528 state
->iov
[0].iov_len
-= written
;
531 written
-= state
->iov
[0].iov_len
;
537 ssize_t
writev_recv(struct tevent_req
*req
, int *perrno
)
539 struct writev_state
*state
=
540 tevent_req_data(req
, struct writev_state
);
542 if (tevent_req_is_unix_error(req
, perrno
)) {
545 return state
->total_size
;
548 struct read_packet_state
{
552 ssize_t (*more
)(uint8_t *buf
, size_t buflen
, void *private_data
);
556 static void read_packet_handler(struct tevent_context
*ev
,
557 struct tevent_fd
*fde
,
558 uint16_t flags
, void *private_data
);
560 struct tevent_req
*read_packet_send(TALLOC_CTX
*mem_ctx
,
561 struct tevent_context
*ev
,
562 int fd
, size_t initial
,
563 ssize_t (*more
)(uint8_t *buf
,
568 struct tevent_req
*result
;
569 struct read_packet_state
*state
;
570 struct tevent_fd
*fde
;
572 result
= tevent_req_create(mem_ctx
, &state
, struct read_packet_state
);
573 if (result
== NULL
) {
579 state
->private_data
= private_data
;
581 state
->buf
= talloc_array(state
, uint8_t, initial
);
582 if (state
->buf
== NULL
) {
586 fde
= tevent_add_fd(ev
, state
, fd
, TEVENT_FD_READ
, read_packet_handler
,
597 static void read_packet_handler(struct tevent_context
*ev
,
598 struct tevent_fd
*fde
,
599 uint16_t flags
, void *private_data
)
601 struct tevent_req
*req
= talloc_get_type_abort(
602 private_data
, struct tevent_req
);
603 struct read_packet_state
*state
=
604 tevent_req_data(req
, struct read_packet_state
);
605 size_t total
= talloc_get_size(state
->buf
);
609 nread
= recv(state
->fd
, state
->buf
+state
->nread
, total
-state
->nread
,
611 if ((nread
== -1) && (errno
== EINTR
)) {
616 tevent_req_error(req
, errno
);
620 tevent_req_error(req
, EPIPE
);
624 state
->nread
+= nread
;
625 if (state
->nread
< total
) {
626 /* Come back later */
631 * We got what was initially requested. See if "more" asks for -- more.
633 if (state
->more
== NULL
) {
634 /* Nobody to ask, this is a async read_data */
635 tevent_req_done(req
);
639 more
= state
->more(state
->buf
, total
, state
->private_data
);
641 /* We got an invalid packet, tell the caller */
642 tevent_req_error(req
, EIO
);
646 /* We're done, full packet received */
647 tevent_req_done(req
);
651 tmp
= talloc_realloc(state
, state
->buf
, uint8_t, total
+more
);
652 if (tevent_req_nomem(tmp
, req
)) {
658 ssize_t
read_packet_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
659 uint8_t **pbuf
, int *perrno
)
661 struct read_packet_state
*state
=
662 tevent_req_data(req
, struct read_packet_state
);
664 if (tevent_req_is_unix_error(req
, perrno
)) {
667 *pbuf
= talloc_move(mem_ctx
, &state
->buf
);
668 return talloc_get_size(*pbuf
);