s3:build: install libtalloc with full version number instead of only SO version
[Samba.git] / lib / async_req / async_sock.c
blob7ea66f57fedced66f8e7f8cbd202fc979ffd00fc
1 /*
2 Unix SMB/CIFS implementation.
3 async socket syscalls
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
8 ** under the LGPL
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/>.
24 #include "replace.h"
25 #include "system/network.h"
26 #include "system/filesys.h"
27 #include <talloc.h>
28 #include <tevent.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"
35 #ifndef TALLOC_FREE
36 #define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0)
37 #endif
39 struct sendto_state {
40 int fd;
41 const void *buf;
42 size_t len;
43 int flags;
44 const struct sockaddr_storage *addr;
45 socklen_t addr_len;
46 ssize_t sent;
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);
62 if (result == NULL) {
63 return result;
65 state->fd = fd;
66 state->buf = buf;
67 state->len = len;
68 state->flags = flags;
69 state->addr = addr;
71 switch (addr->ss_family) {
72 case AF_INET:
73 state->addr_len = sizeof(struct sockaddr_in);
74 break;
75 #if defined(HAVE_IPV6)
76 case AF_INET6:
77 state->addr_len = sizeof(struct sockaddr_in6);
78 break;
79 #endif
80 case AF_UNIX:
81 state->addr_len = sizeof(struct sockaddr_un);
82 break;
83 default:
84 state->addr_len = sizeof(struct sockaddr_storage);
85 break;
88 fde = tevent_add_fd(ev, state, fd, TEVENT_FD_WRITE, sendto_handler,
89 result);
90 if (fde == NULL) {
91 TALLOC_FREE(result);
92 return NULL;
94 return result;
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)) {
109 /* retry */
110 return;
112 if (state->sent == -1) {
113 tevent_req_error(req, errno);
114 return;
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)) {
125 return -1;
127 return state->sent;
130 struct recvfrom_state {
131 int fd;
132 void *buf;
133 size_t len;
134 int flags;
135 struct sockaddr_storage *addr;
136 socklen_t *addr_len;
137 ssize_t received;
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,
148 socklen_t *addr_len)
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) {
156 return result;
158 state->fd = fd;
159 state->buf = buf;
160 state->len = len;
161 state->flags = flags;
162 state->addr = addr;
163 state->addr_len = addr_len;
165 fde = tevent_add_fd(ev, state, fd, TEVENT_FD_READ, recvfrom_handler,
166 result);
167 if (fde == NULL) {
168 TALLOC_FREE(result);
169 return NULL;
171 return result;
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,
185 state->addr_len);
186 if ((state->received == -1) && (errno == EINTR)) {
187 /* retry */
188 return;
190 if (state->received == 0) {
191 tevent_req_error(req, EPIPE);
192 return;
194 if (state->received == -1) {
195 tevent_req_error(req, errno);
196 return;
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)) {
207 return -1;
209 return state->received;
212 struct async_connect_state {
213 int fd;
214 int result;
215 int sys_errno;
216 long old_sockflags;
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,
223 void *priv);
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) {
250 return NULL;
254 * We have to set the socket to nonblocking for async connect(2). Keep
255 * the old sockflags around.
258 state->fd = fd;
259 state->sys_errno = 0;
261 state->old_sockflags = fcntl(fd, F_GETFL, 0);
262 if (state->old_sockflags == -1) {
263 goto post_errno;
266 state->address_len = address_len;
267 if (address_len > sizeof(state->address)) {
268 errno = EINVAL;
269 goto post_errno;
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);
278 goto done;
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 ||
289 #ifdef EISCONN
290 errno == EISCONN ||
291 #endif
292 errno == EAGAIN || errno == EINTR)) {
293 state->sys_errno = errno;
294 goto post_errno;
297 fde = tevent_add_fd(ev, state, fd, TEVENT_FD_READ | TEVENT_FD_WRITE,
298 async_connect_connected, result);
299 if (fde == NULL) {
300 state->sys_errno = ENOMEM;
301 goto post_errno;
303 return result;
305 post_errno:
306 tevent_req_error(result, state->sys_errno);
307 done:
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,
322 void *priv)
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)) {
336 int ret;
338 ret = connect(state->fd,
339 (struct sockaddr *)(void *)&state->address,
340 state->address_len);
341 if (ret == 0) {
342 TALLOC_FREE(fde);
343 tevent_req_done(req);
344 return;
347 if (errno == EINPROGRESS) {
348 /* Try again later, leave the fde around */
349 return;
351 TALLOC_FREE(fde);
352 tevent_req_error(req, errno);
353 return;
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);
364 int err;
366 fcntl(state->fd, F_SETFL, state->old_sockflags);
368 if (tevent_req_is_unix_error(req, &err)) {
369 *perrno = err;
370 return -1;
373 if (state->sys_errno == 0) {
374 return 0;
377 *perrno = state->sys_errno;
378 return -1;
381 struct writev_state {
382 struct tevent_context *ev;
383 int fd;
384 struct iovec *iov;
385 int count;
386 size_t total_size;
387 uint16_t flags;
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);
403 if (req == NULL) {
404 return NULL;
406 state->ev = ev;
407 state->fd = fd;
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) {
413 goto fail;
415 state->flags = TEVENT_FD_WRITE;
416 if (err_on_readability) {
417 state->flags |= TEVENT_FD_READ;
420 if (queue == NULL) {
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);
427 return req;
430 if (!tevent_queue_add(queue, ev, req, writev_trigger, NULL)) {
431 goto fail;
433 return req;
434 fail:
435 TALLOC_FREE(req);
436 return 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);
446 if (fde == NULL) {
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;
459 int i;
461 to_write = 0;
463 if ((state->flags & TEVENT_FD_READ) && (flags & TEVENT_FD_READ)) {
464 tevent_req_error(req, EPIPE);
465 return;
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)) {
474 /* retry */
475 return;
477 if (written == -1) {
478 tevent_req_error(req, errno);
479 return;
481 if (written == 0) {
482 tevent_req_error(req, EPIPE);
483 return;
485 state->total_size += written;
487 if (written == to_write) {
488 tevent_req_done(req);
489 return;
493 * We've written less than we were asked to, drop stuff from
494 * state->iov.
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;
502 break;
504 written -= state->iov[0].iov_len;
505 state->iov += 1;
506 state->count -= 1;
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)) {
516 return -1;
518 return state->total_size;
521 struct read_packet_state {
522 int fd;
523 uint8_t *buf;
524 size_t nread;
525 ssize_t (*more)(uint8_t *buf, size_t buflen, void *private_data);
526 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,
537 size_t buflen,
538 void *private_data),
539 void *private_data)
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) {
547 return NULL;
549 state->fd = fd;
550 state->nread = 0;
551 state->more = more;
552 state->private_data = private_data;
554 state->buf = talloc_array(state, uint8_t, initial);
555 if (state->buf == NULL) {
556 goto fail;
559 fde = tevent_add_fd(ev, state, fd, TEVENT_FD_READ, read_packet_handler,
560 result);
561 if (fde == NULL) {
562 goto fail;
564 return result;
565 fail:
566 TALLOC_FREE(result);
567 return NULL;
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);
579 ssize_t nread, more;
580 uint8_t *tmp;
582 nread = recv(state->fd, state->buf+state->nread, total-state->nread,
584 if ((nread == -1) && (errno == EINTR)) {
585 /* retry */
586 return;
588 if (nread == -1) {
589 tevent_req_error(req, errno);
590 return;
592 if (nread == 0) {
593 tevent_req_error(req, EPIPE);
594 return;
597 state->nread += nread;
598 if (state->nread < total) {
599 /* Come back later */
600 return;
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);
609 return;
612 more = state->more(state->buf, total, state->private_data);
613 if (more == -1) {
614 /* We got an invalid packet, tell the caller */
615 tevent_req_error(req, EIO);
616 return;
618 if (more == 0) {
619 /* We're done, full packet received */
620 tevent_req_done(req);
621 return;
624 tmp = talloc_realloc(state, state->buf, uint8_t, total+more);
625 if (tevent_req_nomem(tmp, req)) {
626 return;
628 state->buf = tmp;
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)) {
638 return -1;
640 *pbuf = talloc_move(mem_ctx, &state->buf);
641 return talloc_get_size(*pbuf);