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 (struct sockaddr
*)state
->addr
, state
->addr_len
);
108 if ((state
->sent
== -1) && (errno
== EINTR
)) {
112 if (state
->sent
== -1) {
113 tevent_req_error(req
, errno
);
116 tevent_req_done(req
);
119 ssize_t
sendto_recv(struct tevent_req
*req
, int *perrno
)
121 struct sendto_state
*state
=
122 tevent_req_data(req
, struct sendto_state
);
124 if (tevent_req_is_unix_error(req
, perrno
)) {
130 struct recvfrom_state
{
135 struct sockaddr_storage
*addr
;
140 static void recvfrom_handler(struct tevent_context
*ev
,
141 struct tevent_fd
*fde
,
142 uint16_t flags
, void *private_data
);
144 struct tevent_req
*recvfrom_send(TALLOC_CTX
*mem_ctx
,
145 struct tevent_context
*ev
,
146 int fd
, void *buf
, size_t len
, int flags
,
147 struct sockaddr_storage
*addr
,
150 struct tevent_req
*result
;
151 struct recvfrom_state
*state
;
152 struct tevent_fd
*fde
;
154 result
= tevent_req_create(mem_ctx
, &state
, struct recvfrom_state
);
155 if (result
== NULL
) {
161 state
->flags
= flags
;
163 state
->addr_len
= addr_len
;
165 fde
= tevent_add_fd(ev
, state
, fd
, TEVENT_FD_READ
, recvfrom_handler
,
174 static void recvfrom_handler(struct tevent_context
*ev
,
175 struct tevent_fd
*fde
,
176 uint16_t flags
, void *private_data
)
178 struct tevent_req
*req
= talloc_get_type_abort(
179 private_data
, struct tevent_req
);
180 struct recvfrom_state
*state
=
181 tevent_req_data(req
, struct recvfrom_state
);
183 state
->received
= recvfrom(state
->fd
, state
->buf
, state
->len
,
184 state
->flags
, (struct sockaddr
*)state
->addr
,
186 if ((state
->received
== -1) && (errno
== EINTR
)) {
190 if (state
->received
== 0) {
191 tevent_req_error(req
, EPIPE
);
194 if (state
->received
== -1) {
195 tevent_req_error(req
, errno
);
198 tevent_req_done(req
);
201 ssize_t
recvfrom_recv(struct tevent_req
*req
, int *perrno
)
203 struct recvfrom_state
*state
=
204 tevent_req_data(req
, struct recvfrom_state
);
206 if (tevent_req_is_unix_error(req
, perrno
)) {
209 return state
->received
;
212 struct async_connect_state
{
217 socklen_t address_len
;
218 struct sockaddr_storage address
;
221 static void async_connect_connected(struct tevent_context
*ev
,
222 struct tevent_fd
*fde
, uint16_t flags
,
226 * @brief async version of connect(2)
227 * @param[in] mem_ctx The memory context to hang the result off
228 * @param[in] ev The event context to work from
229 * @param[in] fd The socket to recv from
230 * @param[in] address Where to connect?
231 * @param[in] address_len Length of *address
232 * @retval The async request
234 * This function sets the socket into non-blocking state to be able to call
235 * connect in an async state. This will be reset when the request is finished.
238 struct tevent_req
*async_connect_send(TALLOC_CTX
*mem_ctx
,
239 struct tevent_context
*ev
,
240 int fd
, const struct sockaddr
*address
,
241 socklen_t address_len
)
243 struct tevent_req
*result
;
244 struct async_connect_state
*state
;
245 struct tevent_fd
*fde
;
247 result
= tevent_req_create(
248 mem_ctx
, &state
, struct async_connect_state
);
249 if (result
== NULL
) {
254 * We have to set the socket to nonblocking for async connect(2). Keep
255 * the old sockflags around.
259 state
->sys_errno
= 0;
261 state
->old_sockflags
= fcntl(fd
, F_GETFL
, 0);
262 if (state
->old_sockflags
== -1) {
266 state
->address_len
= address_len
;
267 if (address_len
> sizeof(state
->address
)) {
271 memcpy(&state
->address
, address
, address_len
);
273 set_blocking(fd
, false);
275 state
->result
= connect(fd
, address
, address_len
);
276 if (state
->result
== 0) {
277 tevent_req_done(result
);
282 * A number of error messages show that something good is progressing
283 * and that we have to wait for readability.
285 * If none of them are present, bail out.
288 if (!(errno
== EINPROGRESS
|| errno
== EALREADY
||
292 errno
== EAGAIN
|| errno
== EINTR
)) {
293 state
->sys_errno
= errno
;
297 fde
= tevent_add_fd(ev
, state
, fd
, TEVENT_FD_READ
| TEVENT_FD_WRITE
,
298 async_connect_connected
, result
);
300 state
->sys_errno
= ENOMEM
;
306 tevent_req_error(result
, state
->sys_errno
);
308 fcntl(fd
, F_SETFL
, state
->old_sockflags
);
309 return tevent_req_post(result
, ev
);
313 * fde event handler for connect(2)
314 * @param[in] ev The event context that sent us here
315 * @param[in] fde The file descriptor event associated with the connect
316 * @param[in] flags Indicate read/writeability of the socket
317 * @param[in] priv private data, "struct async_req *" in this case
320 static void async_connect_connected(struct tevent_context
*ev
,
321 struct tevent_fd
*fde
, uint16_t flags
,
324 struct tevent_req
*req
= talloc_get_type_abort(
325 priv
, struct tevent_req
);
326 struct async_connect_state
*state
=
327 tevent_req_data(req
, struct async_connect_state
);
330 * Stevens, Network Programming says that if there's a
331 * successful connect, the socket is only writable. Upon an
332 * error, it's both readable and writable.
334 if ((flags
& (TEVENT_FD_READ
|TEVENT_FD_WRITE
))
335 == (TEVENT_FD_READ
|TEVENT_FD_WRITE
)) {
338 ret
= connect(state
->fd
,
339 (struct sockaddr
*)(void *)&state
->address
,
343 tevent_req_done(req
);
347 if (errno
== EINPROGRESS
) {
348 /* Try again later, leave the fde around */
352 tevent_req_error(req
, errno
);
356 state
->sys_errno
= 0;
357 tevent_req_done(req
);
360 int async_connect_recv(struct tevent_req
*req
, int *perrno
)
362 struct async_connect_state
*state
=
363 tevent_req_data(req
, struct async_connect_state
);
366 fcntl(state
->fd
, F_SETFL
, state
->old_sockflags
);
368 if (tevent_req_is_unix_error(req
, &err
)) {
373 if (state
->sys_errno
== 0) {
377 *perrno
= state
->sys_errno
;
381 struct writev_state
{
382 struct tevent_context
*ev
;
388 bool err_on_readability
;
391 static void writev_trigger(struct tevent_req
*req
, void *private_data
);
392 static void writev_handler(struct tevent_context
*ev
, struct tevent_fd
*fde
,
393 uint16_t flags
, void *private_data
);
395 struct tevent_req
*writev_send(TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
396 struct tevent_queue
*queue
, int fd
,
397 bool err_on_readability
,
398 struct iovec
*iov
, int count
)
400 struct tevent_req
*req
;
401 struct writev_state
*state
;
403 req
= tevent_req_create(mem_ctx
, &state
, struct writev_state
);
409 state
->total_size
= 0;
410 state
->count
= count
;
411 state
->iov
= (struct iovec
*)talloc_memdup(
412 state
, iov
, sizeof(struct iovec
) * count
);
413 if (state
->iov
== NULL
) {
416 state
->flags
= TEVENT_FD_WRITE
|TEVENT_FD_READ
;
417 state
->err_on_readability
= err_on_readability
;
420 struct tevent_fd
*fde
;
421 fde
= tevent_add_fd(state
->ev
, state
, state
->fd
,
422 state
->flags
, writev_handler
, req
);
423 if (tevent_req_nomem(fde
, req
)) {
424 return tevent_req_post(req
, ev
);
429 if (!tevent_queue_add(queue
, ev
, req
, writev_trigger
, NULL
)) {
438 static void writev_trigger(struct tevent_req
*req
, void *private_data
)
440 struct writev_state
*state
= tevent_req_data(req
, struct writev_state
);
441 struct tevent_fd
*fde
;
443 fde
= tevent_add_fd(state
->ev
, state
, state
->fd
, state
->flags
,
444 writev_handler
, req
);
446 tevent_req_error(req
, ENOMEM
);
450 static void writev_handler(struct tevent_context
*ev
, struct tevent_fd
*fde
,
451 uint16_t flags
, void *private_data
)
453 struct tevent_req
*req
= talloc_get_type_abort(
454 private_data
, struct tevent_req
);
455 struct writev_state
*state
=
456 tevent_req_data(req
, struct writev_state
);
457 size_t to_write
, written
;
462 if ((state
->flags
& TEVENT_FD_READ
) && (flags
& TEVENT_FD_READ
)) {
465 if (state
->err_on_readability
) {
466 /* Readable and the caller wants an error on read. */
467 tevent_req_error(req
, EPIPE
);
471 /* Might be an error. Check if there are bytes to read */
472 ret
= ioctl(state
->fd
, FIONREAD
, &value
);
473 /* FIXME - should we also check
474 for ret == 0 and value == 0 here ? */
476 /* There's an error. */
477 tevent_req_error(req
, EPIPE
);
480 /* A request for TEVENT_FD_READ will succeed from now and
481 forevermore until the bytes are read so if there was
482 an error we'll wait until we do read, then get it in
483 the read callback function. Until then, remove TEVENT_FD_READ
484 from the flags we're waiting for. */
485 state
->flags
&= ~TEVENT_FD_READ
;
486 TEVENT_FD_NOT_READABLE(fde
);
488 /* If not writable, we're done. */
489 if (!(flags
& TEVENT_FD_WRITE
)) {
494 for (i
=0; i
<state
->count
; i
++) {
495 to_write
+= state
->iov
[i
].iov_len
;
498 written
= writev(state
->fd
, state
->iov
, state
->count
);
499 if ((written
== -1) && (errno
== EINTR
)) {
504 tevent_req_error(req
, errno
);
508 tevent_req_error(req
, EPIPE
);
511 state
->total_size
+= written
;
513 if (written
== to_write
) {
514 tevent_req_done(req
);
519 * We've written less than we were asked to, drop stuff from
523 while (written
> 0) {
524 if (written
< state
->iov
[0].iov_len
) {
525 state
->iov
[0].iov_base
=
526 (char *)state
->iov
[0].iov_base
+ written
;
527 state
->iov
[0].iov_len
-= written
;
530 written
-= state
->iov
[0].iov_len
;
536 ssize_t
writev_recv(struct tevent_req
*req
, int *perrno
)
538 struct writev_state
*state
=
539 tevent_req_data(req
, struct writev_state
);
541 if (tevent_req_is_unix_error(req
, perrno
)) {
544 return state
->total_size
;
547 struct read_packet_state
{
551 ssize_t (*more
)(uint8_t *buf
, size_t buflen
, void *private_data
);
555 static void read_packet_handler(struct tevent_context
*ev
,
556 struct tevent_fd
*fde
,
557 uint16_t flags
, void *private_data
);
559 struct tevent_req
*read_packet_send(TALLOC_CTX
*mem_ctx
,
560 struct tevent_context
*ev
,
561 int fd
, size_t initial
,
562 ssize_t (*more
)(uint8_t *buf
,
567 struct tevent_req
*result
;
568 struct read_packet_state
*state
;
569 struct tevent_fd
*fde
;
571 result
= tevent_req_create(mem_ctx
, &state
, struct read_packet_state
);
572 if (result
== NULL
) {
578 state
->private_data
= private_data
;
580 state
->buf
= talloc_array(state
, uint8_t, initial
);
581 if (state
->buf
== NULL
) {
585 fde
= tevent_add_fd(ev
, state
, fd
, TEVENT_FD_READ
, read_packet_handler
,
596 static void read_packet_handler(struct tevent_context
*ev
,
597 struct tevent_fd
*fde
,
598 uint16_t flags
, void *private_data
)
600 struct tevent_req
*req
= talloc_get_type_abort(
601 private_data
, struct tevent_req
);
602 struct read_packet_state
*state
=
603 tevent_req_data(req
, struct read_packet_state
);
604 size_t total
= talloc_get_size(state
->buf
);
608 nread
= recv(state
->fd
, state
->buf
+state
->nread
, total
-state
->nread
,
610 if ((nread
== -1) && (errno
== EINTR
)) {
615 tevent_req_error(req
, errno
);
619 tevent_req_error(req
, EPIPE
);
623 state
->nread
+= nread
;
624 if (state
->nread
< total
) {
625 /* Come back later */
630 * We got what was initially requested. See if "more" asks for -- more.
632 if (state
->more
== NULL
) {
633 /* Nobody to ask, this is a async read_data */
634 tevent_req_done(req
);
638 more
= state
->more(state
->buf
, total
, state
->private_data
);
640 /* We got an invalid packet, tell the caller */
641 tevent_req_error(req
, EIO
);
645 /* We're done, full packet received */
646 tevent_req_done(req
);
650 tmp
= talloc_realloc(state
, state
->buf
, uint8_t, total
+more
);
651 if (tevent_req_nomem(tmp
, req
)) {
657 ssize_t
read_packet_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
658 uint8_t **pbuf
, int *perrno
)
660 struct read_packet_state
*state
=
661 tevent_req_data(req
, struct read_packet_state
);
663 if (tevent_req_is_unix_error(req
, perrno
)) {
666 *pbuf
= talloc_move(mem_ctx
, &state
->buf
);
667 return talloc_get_size(*pbuf
);