s3-swat: Fix typo.
[Samba.git] / lib / async_req / async_sock.c
blob2c90b6dd17b0dc0a506666e1ea380a45da6893f5
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;
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);
404 if (req == NULL) {
405 return NULL;
407 state->ev = ev;
408 state->fd = fd;
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) {
414 goto fail;
416 state->flags = TEVENT_FD_WRITE|TEVENT_FD_READ;
417 state->err_on_readability = err_on_readability;
419 if (queue == NULL) {
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);
426 return req;
429 if (!tevent_queue_add(queue, ev, req, writev_trigger, NULL)) {
430 goto fail;
432 return req;
433 fail:
434 TALLOC_FREE(req);
435 return 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);
445 if (fde == NULL) {
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;
458 int i;
460 to_write = 0;
462 if ((state->flags & TEVENT_FD_READ) && (flags & TEVENT_FD_READ)) {
463 int ret, value;
465 if (state->err_on_readability) {
466 /* Readable and the caller wants an error on read. */
467 tevent_req_error(req, EPIPE);
468 return;
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 ? */
475 if (ret == -1) {
476 /* There's an error. */
477 tevent_req_error(req, EPIPE);
478 return;
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)) {
490 return;
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)) {
500 /* retry */
501 return;
503 if (written == -1) {
504 tevent_req_error(req, errno);
505 return;
507 if (written == 0) {
508 tevent_req_error(req, EPIPE);
509 return;
511 state->total_size += written;
513 if (written == to_write) {
514 tevent_req_done(req);
515 return;
519 * We've written less than we were asked to, drop stuff from
520 * state->iov.
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;
528 break;
530 written -= state->iov[0].iov_len;
531 state->iov += 1;
532 state->count -= 1;
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)) {
542 return -1;
544 return state->total_size;
547 struct read_packet_state {
548 int fd;
549 uint8_t *buf;
550 size_t nread;
551 ssize_t (*more)(uint8_t *buf, size_t buflen, void *private_data);
552 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,
563 size_t buflen,
564 void *private_data),
565 void *private_data)
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) {
573 return NULL;
575 state->fd = fd;
576 state->nread = 0;
577 state->more = more;
578 state->private_data = private_data;
580 state->buf = talloc_array(state, uint8_t, initial);
581 if (state->buf == NULL) {
582 goto fail;
585 fde = tevent_add_fd(ev, state, fd, TEVENT_FD_READ, read_packet_handler,
586 result);
587 if (fde == NULL) {
588 goto fail;
590 return result;
591 fail:
592 TALLOC_FREE(result);
593 return NULL;
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);
605 ssize_t nread, more;
606 uint8_t *tmp;
608 nread = recv(state->fd, state->buf+state->nread, total-state->nread,
610 if ((nread == -1) && (errno == EINTR)) {
611 /* retry */
612 return;
614 if (nread == -1) {
615 tevent_req_error(req, errno);
616 return;
618 if (nread == 0) {
619 tevent_req_error(req, EPIPE);
620 return;
623 state->nread += nread;
624 if (state->nread < total) {
625 /* Come back later */
626 return;
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);
635 return;
638 more = state->more(state->buf, total, state->private_data);
639 if (more == -1) {
640 /* We got an invalid packet, tell the caller */
641 tevent_req_error(req, EIO);
642 return;
644 if (more == 0) {
645 /* We're done, full packet received */
646 tevent_req_done(req);
647 return;
650 tmp = talloc_realloc(state, state->buf, uint8_t, total+more);
651 if (tevent_req_nomem(tmp, req)) {
652 return;
654 state->buf = tmp;
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)) {
664 return -1;
666 *pbuf = talloc_move(mem_ctx, &state->buf);
667 return talloc_get_size(*pbuf);