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
;
390 static void writev_trigger(struct tevent_req
*req
, void *private_data
);
391 static void writev_handler(struct tevent_context
*ev
, struct tevent_fd
*fde
,
392 uint16_t flags
, void *private_data
);
394 struct tevent_req
*writev_send(TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
395 struct tevent_queue
*queue
, int fd
,
396 bool err_on_readability
,
397 struct iovec
*iov
, int count
)
399 struct tevent_req
*req
;
400 struct writev_state
*state
;
402 req
= tevent_req_create(mem_ctx
, &state
, struct writev_state
);
408 state
->total_size
= 0;
409 state
->count
= count
;
410 state
->iov
= (struct iovec
*)talloc_memdup(
411 state
, iov
, sizeof(struct iovec
) * count
);
412 if (state
->iov
== NULL
) {
415 state
->flags
= TEVENT_FD_WRITE
;
416 if (err_on_readability
) {
417 state
->flags
|= TEVENT_FD_READ
;
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
)) {
464 tevent_req_error(req
, EPIPE
);
468 for (i
=0; i
<state
->count
; i
++) {
469 to_write
+= state
->iov
[i
].iov_len
;
472 written
= writev(state
->fd
, state
->iov
, state
->count
);
473 if ((written
== -1) && (errno
== EINTR
)) {
478 tevent_req_error(req
, errno
);
482 tevent_req_error(req
, EPIPE
);
485 state
->total_size
+= written
;
487 if (written
== to_write
) {
488 tevent_req_done(req
);
493 * We've written less than we were asked to, drop stuff from
497 while (written
> 0) {
498 if (written
< state
->iov
[0].iov_len
) {
499 state
->iov
[0].iov_base
=
500 (char *)state
->iov
[0].iov_base
+ written
;
501 state
->iov
[0].iov_len
-= written
;
504 written
-= state
->iov
[0].iov_len
;
510 ssize_t
writev_recv(struct tevent_req
*req
, int *perrno
)
512 struct writev_state
*state
=
513 tevent_req_data(req
, struct writev_state
);
515 if (tevent_req_is_unix_error(req
, perrno
)) {
518 return state
->total_size
;
521 struct read_packet_state
{
525 ssize_t (*more
)(uint8_t *buf
, size_t buflen
, void *private_data
);
529 static void read_packet_handler(struct tevent_context
*ev
,
530 struct tevent_fd
*fde
,
531 uint16_t flags
, void *private_data
);
533 struct tevent_req
*read_packet_send(TALLOC_CTX
*mem_ctx
,
534 struct tevent_context
*ev
,
535 int fd
, size_t initial
,
536 ssize_t (*more
)(uint8_t *buf
,
541 struct tevent_req
*result
;
542 struct read_packet_state
*state
;
543 struct tevent_fd
*fde
;
545 result
= tevent_req_create(mem_ctx
, &state
, struct read_packet_state
);
546 if (result
== NULL
) {
552 state
->private_data
= private_data
;
554 state
->buf
= talloc_array(state
, uint8_t, initial
);
555 if (state
->buf
== NULL
) {
559 fde
= tevent_add_fd(ev
, state
, fd
, TEVENT_FD_READ
, read_packet_handler
,
570 static void read_packet_handler(struct tevent_context
*ev
,
571 struct tevent_fd
*fde
,
572 uint16_t flags
, void *private_data
)
574 struct tevent_req
*req
= talloc_get_type_abort(
575 private_data
, struct tevent_req
);
576 struct read_packet_state
*state
=
577 tevent_req_data(req
, struct read_packet_state
);
578 size_t total
= talloc_get_size(state
->buf
);
582 nread
= recv(state
->fd
, state
->buf
+state
->nread
, total
-state
->nread
,
584 if ((nread
== -1) && (errno
== EINTR
)) {
589 tevent_req_error(req
, errno
);
593 tevent_req_error(req
, EPIPE
);
597 state
->nread
+= nread
;
598 if (state
->nread
< total
) {
599 /* Come back later */
604 * We got what was initially requested. See if "more" asks for -- more.
606 if (state
->more
== NULL
) {
607 /* Nobody to ask, this is a async read_data */
608 tevent_req_done(req
);
612 more
= state
->more(state
->buf
, total
, state
->private_data
);
614 /* We got an invalid packet, tell the caller */
615 tevent_req_error(req
, EIO
);
619 /* We're done, full packet received */
620 tevent_req_done(req
);
624 tmp
= talloc_realloc(state
, state
->buf
, uint8_t, total
+more
);
625 if (tevent_req_nomem(tmp
, req
)) {
631 ssize_t
read_packet_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
632 uint8_t **pbuf
, int *perrno
)
634 struct read_packet_state
*state
=
635 tevent_req_data(req
, struct read_packet_state
);
637 if (tevent_req_is_unix_error(req
, perrno
)) {
640 *pbuf
= talloc_move(mem_ctx
, &state
->buf
);
641 return talloc_get_size(*pbuf
);