Convert async_connect to tevent_req
[jra/samba/.git] / lib / async_req / async_sock.c
1 /*
2    Unix SMB/CIFS implementation.
3    async socket syscalls
4    Copyright (C) Volker Lendecke 2008
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "lib/talloc/talloc.h"
22 #include "lib/tevent/tevent.h"
23 #include "lib/async_req/async_req.h"
24 #include "lib/async_req/async_sock.h"
25 #include "lib/util/tevent_unix.h"
26 #include <fcntl.h>
27
28 #ifndef TALLOC_FREE
29 #define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0)
30 #endif
31
32 /**
33  * Discriminator for async_syscall_state
34  */
35 enum async_syscall_type {
36         ASYNC_SYSCALL_SEND,
37         ASYNC_SYSCALL_SENDALL,
38         ASYNC_SYSCALL_RECV,
39         ASYNC_SYSCALL_RECVALL,
40         ASYNC_SYSCALL_CONNECT
41 };
42
43 /**
44  * Holder for syscall arguments and the result
45  */
46
47 struct async_syscall_state {
48         enum async_syscall_type syscall_type;
49         struct tevent_fd *fde;
50
51         union {
52                 struct param_send {
53                         int fd;
54                         const void *buffer;
55                         size_t length;
56                         int flags;
57                 } param_send;
58                 struct param_sendall {
59                         int fd;
60                         const void *buffer;
61                         size_t length;
62                         int flags;
63                         size_t sent;
64                 } param_sendall;
65                 struct param_recv {
66                         int fd;
67                         void *buffer;
68                         size_t length;
69                         int flags;
70                 } param_recv;
71                 struct param_recvall {
72                         int fd;
73                         void *buffer;
74                         size_t length;
75                         int flags;
76                         size_t received;
77                 } param_recvall;
78                 struct param_connect {
79                         /**
80                          * connect needs to be done on a nonblocking
81                          * socket. Keep the old flags around
82                          */
83                         long old_sockflags;
84                         int fd;
85                         const struct sockaddr *address;
86                         socklen_t address_len;
87                 } param_connect;
88         } param;
89
90         union {
91                 ssize_t result_ssize_t;
92                 size_t result_size_t;
93                 int result_int;
94         } result;
95         int sys_errno;
96 };
97
98 /**
99  * @brief Map async_req states to unix-style errnos
100  * @param[in]  req      The async req to get the state from
101  * @param[out] err      Pointer to take the unix-style errno
102  *
103  * @return true if the async_req is in an error state, false otherwise
104  */
105
106 bool async_req_is_errno(struct async_req *req, int *err)
107 {
108         enum async_req_state state;
109         uint64_t error;
110
111         if (!async_req_is_error(req, &state, &error)) {
112                 return false;
113         }
114
115         switch (state) {
116         case ASYNC_REQ_USER_ERROR:
117                 *err = (int)error;
118                 break;
119         case ASYNC_REQ_TIMED_OUT:
120 #ifdef ETIMEDOUT
121                 *err = ETIMEDOUT;
122 #else
123                 *err = EAGAIN;
124 #endif
125                 break;
126         case ASYNC_REQ_NO_MEMORY:
127                 *err = ENOMEM;
128                 break;
129         default:
130                 *err = EIO;
131                 break;
132         }
133         return true;
134 }
135
136 int async_req_simple_recv_errno(struct async_req *req)
137 {
138         int err;
139
140         if (async_req_is_errno(req, &err)) {
141                 return err;
142         }
143
144         return 0;
145 }
146
147 /**
148  * @brief Create a new async syscall req
149  * @param[in] mem_ctx   The memory context to hang the result off
150  * @param[in] ev        The event context to work from
151  * @param[in] type      Which syscall will this be
152  * @param[in] pstate    Where to put the newly created private_data state
153  * @retval The new request
154  *
155  * This is a helper function to prepare a new struct async_req with an
156  * associated struct async_syscall_state. The async_syscall_state will be put
157  * into the async_req as private_data.
158  */
159
160 static struct async_req *async_syscall_new(TALLOC_CTX *mem_ctx,
161                                            struct tevent_context *ev,
162                                            enum async_syscall_type type,
163                                            struct async_syscall_state **pstate)
164 {
165         struct async_req *result;
166         struct async_syscall_state *state;
167
168         if (!async_req_setup(mem_ctx, &result, &state,
169                              struct async_syscall_state)) {
170                 return NULL;
171         }
172         state->syscall_type = type;
173
174         result->private_data = state;
175
176         *pstate = state;
177
178         return result;
179 }
180
181 /**
182  * @brief Create a new async syscall req based on a fd
183  * @param[in] mem_ctx   The memory context to hang the result off
184  * @param[in] ev        The event context to work from
185  * @param[in] type      Which syscall will this be
186  * @param[in] fd        The file descriptor we work on
187  * @param[in] fde_flags TEVENT_FD_READ/WRITE -- what are we interested in?
188  * @param[in] fde_cb    The callback function for the file descriptor event
189  * @param[in] pstate    Where to put the newly created private_data state
190  * @retval The new request
191  *
192  * This is a helper function to prepare a new struct async_req with an
193  * associated struct async_syscall_state and an associated file descriptor
194  * event.
195  */
196
197 static struct async_req *async_fde_syscall_new(
198         TALLOC_CTX *mem_ctx,
199         struct tevent_context *ev,
200         enum async_syscall_type type,
201         int fd,
202         uint16_t fde_flags,
203         void (*fde_cb)(struct tevent_context *ev,
204                        struct tevent_fd *fde, uint16_t flags,
205                        void *priv),
206         struct async_syscall_state **pstate)
207 {
208         struct async_req *result;
209         struct async_syscall_state *state;
210
211         result = async_syscall_new(mem_ctx, ev, type, &state);
212         if (result == NULL) {
213                 return NULL;
214         }
215
216         state->fde = tevent_add_fd(ev, state, fd, fde_flags, fde_cb, result);
217         if (state->fde == NULL) {
218                 TALLOC_FREE(result);
219                 return NULL;
220         }
221         *pstate = state;
222         return result;
223 }
224
225 /**
226  * Retrieve a ssize_t typed result from an async syscall
227  * @param[in] req       The syscall that has just finished
228  * @param[out] perrno   Where to put the syscall's errno
229  * @retval The return value from the asynchronously called syscall
230  */
231
232 ssize_t async_syscall_result_ssize_t(struct async_req *req, int *perrno)
233 {
234         struct async_syscall_state *state = talloc_get_type_abort(
235                 req->private_data, struct async_syscall_state);
236
237         *perrno = state->sys_errno;
238         return state->result.result_ssize_t;
239 }
240
241 /**
242  * Retrieve a size_t typed result from an async syscall
243  * @param[in] req       The syscall that has just finished
244  * @param[out] perrno   Where to put the syscall's errno
245  * @retval The return value from the asynchronously called syscall
246  */
247
248 size_t async_syscall_result_size_t(struct async_req *req, int *perrno)
249 {
250         struct async_syscall_state *state = talloc_get_type_abort(
251                 req->private_data, struct async_syscall_state);
252
253         *perrno = state->sys_errno;
254         return state->result.result_size_t;
255 }
256
257 /**
258  * Retrieve a int typed result from an async syscall
259  * @param[in] req       The syscall that has just finished
260  * @param[out] perrno   Where to put the syscall's errno
261  * @retval The return value from the asynchronously called syscall
262  */
263
264 int async_syscall_result_int(struct async_req *req, int *perrno)
265 {
266         struct async_syscall_state *state = talloc_get_type_abort(
267                 req->private_data, struct async_syscall_state);
268
269         *perrno = state->sys_errno;
270         return state->result.result_int;
271 }
272
273 /**
274  * fde event handler for the "send" syscall
275  * @param[in] ev        The event context that sent us here
276  * @param[in] fde       The file descriptor event associated with the send
277  * @param[in] flags     Can only be TEVENT_FD_WRITE here
278  * @param[in] priv      private data, "struct async_req *" in this case
279  */
280
281 static void async_send_callback(struct tevent_context *ev,
282                                 struct tevent_fd *fde, uint16_t flags,
283                                 void *priv)
284 {
285         struct async_req *req = talloc_get_type_abort(
286                 priv, struct async_req);
287         struct async_syscall_state *state = talloc_get_type_abort(
288                 req->private_data, struct async_syscall_state);
289         struct param_send *p = &state->param.param_send;
290
291         if (state->syscall_type != ASYNC_SYSCALL_SEND) {
292                 async_req_error(req, EIO);
293                 return;
294         }
295
296         state->result.result_ssize_t = send(p->fd, p->buffer, p->length,
297                                             p->flags);
298         state->sys_errno = errno;
299
300         TALLOC_FREE(state->fde);
301
302         async_req_done(req);
303 }
304
305 /**
306  * Async version of send(2)
307  * @param[in] mem_ctx   The memory context to hang the result off
308  * @param[in] ev        The event context to work from
309  * @param[in] fd        The socket to send to
310  * @param[in] buffer    The buffer to send
311  * @param[in] length    How many bytes to send
312  * @param[in] flags     flags passed to send(2)
313  *
314  * This function is a direct counterpart of send(2)
315  */
316
317 struct async_req *async_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
318                              int fd, const void *buffer, size_t length,
319                              int flags)
320 {
321         struct async_req *result;
322         struct async_syscall_state *state;
323
324         result = async_fde_syscall_new(
325                 mem_ctx, ev, ASYNC_SYSCALL_SEND,
326                 fd, TEVENT_FD_WRITE, async_send_callback,
327                 &state);
328         if (result == NULL) {
329                 return NULL;
330         }
331
332         state->param.param_send.fd = fd;
333         state->param.param_send.buffer = buffer;
334         state->param.param_send.length = length;
335         state->param.param_send.flags = flags;
336
337         return result;
338 }
339
340 /**
341  * fde event handler for the "sendall" syscall group
342  * @param[in] ev        The event context that sent us here
343  * @param[in] fde       The file descriptor event associated with the send
344  * @param[in] flags     Can only be TEVENT_FD_WRITE here
345  * @param[in] priv      private data, "struct async_req *" in this case
346  */
347
348 static void async_sendall_callback(struct tevent_context *ev,
349                                    struct tevent_fd *fde, uint16_t flags,
350                                    void *priv)
351 {
352         struct async_req *req = talloc_get_type_abort(
353                 priv, struct async_req);
354         struct async_syscall_state *state = talloc_get_type_abort(
355                 req->private_data, struct async_syscall_state);
356         struct param_sendall *p = &state->param.param_sendall;
357
358         if (state->syscall_type != ASYNC_SYSCALL_SENDALL) {
359                 async_req_error(req, EIO);
360                 return;
361         }
362
363         state->result.result_ssize_t = send(p->fd,
364                                             (const char *)p->buffer + p->sent,
365                                             p->length - p->sent, p->flags);
366         state->sys_errno = errno;
367
368         if (state->result.result_ssize_t == -1) {
369                 async_req_error(req, state->sys_errno);
370                 return;
371         }
372
373         if (state->result.result_ssize_t == 0) {
374                 async_req_error(req, EOF);
375                 return;
376         }
377
378         p->sent += state->result.result_ssize_t;
379         if (p->sent > p->length) {
380                 async_req_error(req, EIO);
381                 return;
382         }
383
384         if (p->sent == p->length) {
385                 TALLOC_FREE(state->fde);
386                 async_req_done(req);
387         }
388 }
389
390 /**
391  * @brief Send all bytes to a socket
392  * @param[in] mem_ctx   The memory context to hang the result off
393  * @param[in] ev        The event context to work from
394  * @param[in] fd        The socket to send to
395  * @param[in] buffer    The buffer to send
396  * @param[in] length    How many bytes to send
397  * @param[in] flags     flags passed to send(2)
398  *
399  * async_sendall calls send(2) as long as it is necessary to send all of the
400  * "length" bytes
401  */
402
403 struct async_req *sendall_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
404                                int fd, const void *buffer, size_t length,
405                                int flags)
406 {
407         struct async_req *result;
408         struct async_syscall_state *state;
409
410         result = async_fde_syscall_new(
411                 mem_ctx, ev, ASYNC_SYSCALL_SENDALL,
412                 fd, TEVENT_FD_WRITE, async_sendall_callback,
413                 &state);
414         if (result == NULL) {
415                 return NULL;
416         }
417
418         state->param.param_sendall.fd = fd;
419         state->param.param_sendall.buffer = buffer;
420         state->param.param_sendall.length = length;
421         state->param.param_sendall.flags = flags;
422         state->param.param_sendall.sent = 0;
423
424         return result;
425 }
426
427 ssize_t sendall_recv(struct async_req *req, int *perr)
428 {
429         struct async_syscall_state *state = talloc_get_type_abort(
430                 req->private_data, struct async_syscall_state);
431         int err;
432
433         err = async_req_simple_recv_errno(req);
434
435         if (err != 0) {
436                 *perr = err;
437                 return -1;
438         }
439
440         return state->result.result_ssize_t;
441 }
442
443 /**
444  * fde event handler for the "recv" syscall
445  * @param[in] ev        The event context that sent us here
446  * @param[in] fde       The file descriptor event associated with the recv
447  * @param[in] flags     Can only be TEVENT_FD_READ here
448  * @param[in] priv      private data, "struct async_req *" in this case
449  */
450
451 static void async_recv_callback(struct tevent_context *ev,
452                                 struct tevent_fd *fde, uint16_t flags,
453                                 void *priv)
454 {
455         struct async_req *req = talloc_get_type_abort(
456                 priv, struct async_req);
457         struct async_syscall_state *state = talloc_get_type_abort(
458                 req->private_data, struct async_syscall_state);
459         struct param_recv *p = &state->param.param_recv;
460
461         if (state->syscall_type != ASYNC_SYSCALL_RECV) {
462                 async_req_error(req, EIO);
463                 return;
464         }
465
466         state->result.result_ssize_t = recv(p->fd, p->buffer, p->length,
467                                             p->flags);
468         state->sys_errno = errno;
469
470         TALLOC_FREE(state->fde);
471
472         async_req_done(req);
473 }
474
475 /**
476  * Async version of recv(2)
477  * @param[in] mem_ctx   The memory context to hang the result off
478  * @param[in] ev        The event context to work from
479  * @param[in] fd        The socket to recv from
480  * @param[in] buffer    The buffer to recv into
481  * @param[in] length    How many bytes to recv
482  * @param[in] flags     flags passed to recv(2)
483  *
484  * This function is a direct counterpart of recv(2)
485  */
486
487 struct async_req *async_recv(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
488                              int fd, void *buffer, size_t length,
489                              int flags)
490 {
491         struct async_req *result;
492         struct async_syscall_state *state;
493
494         result = async_fde_syscall_new(
495                 mem_ctx, ev, ASYNC_SYSCALL_RECV,
496                 fd, TEVENT_FD_READ, async_recv_callback,
497                 &state);
498
499         if (result == NULL) {
500                 return NULL;
501         }
502
503         state->param.param_recv.fd = fd;
504         state->param.param_recv.buffer = buffer;
505         state->param.param_recv.length = length;
506         state->param.param_recv.flags = flags;
507
508         return result;
509 }
510
511 /**
512  * fde event handler for the "recvall" syscall group
513  * @param[in] ev        The event context that sent us here
514  * @param[in] fde       The file descriptor event associated with the recv
515  * @param[in] flags     Can only be TEVENT_FD_READ here
516  * @param[in] priv      private data, "struct async_req *" in this case
517  */
518
519 static void async_recvall_callback(struct tevent_context *ev,
520                                    struct tevent_fd *fde, uint16_t flags,
521                                    void *priv)
522 {
523         struct async_req *req = talloc_get_type_abort(
524                 priv, struct async_req);
525         struct async_syscall_state *state = talloc_get_type_abort(
526                 req->private_data, struct async_syscall_state);
527         struct param_recvall *p = &state->param.param_recvall;
528
529         if (state->syscall_type != ASYNC_SYSCALL_RECVALL) {
530                 async_req_error(req, EIO);
531                 return;
532         }
533
534         state->result.result_ssize_t = recv(p->fd,
535                                             (char *)p->buffer + p->received,
536                                             p->length - p->received, p->flags);
537         state->sys_errno = errno;
538
539         if (state->result.result_ssize_t == -1) {
540                 async_req_error(req, state->sys_errno);
541                 return;
542         }
543
544         if (state->result.result_ssize_t == 0) {
545                 async_req_error(req, EIO);
546                 return;
547         }
548
549         p->received += state->result.result_ssize_t;
550         if (p->received > p->length) {
551                 async_req_error(req, EIO);
552                 return;
553         }
554
555         if (p->received == p->length) {
556                 TALLOC_FREE(state->fde);
557                 async_req_done(req);
558         }
559 }
560
561 /**
562  * Receive a specified number of bytes from a socket
563  * @param[in] mem_ctx   The memory context to hang the result off
564  * @param[in] ev        The event context to work from
565  * @param[in] fd        The socket to recv from
566  * @param[in] buffer    The buffer to recv into
567  * @param[in] length    How many bytes to recv
568  * @param[in] flags     flags passed to recv(2)
569  *
570  * async_recvall will call recv(2) until "length" bytes are received
571  */
572
573 struct async_req *recvall_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
574                                int fd, void *buffer, size_t length,
575                                int flags)
576 {
577         struct async_req *result;
578         struct async_syscall_state *state;
579
580         result = async_fde_syscall_new(
581                 mem_ctx, ev, ASYNC_SYSCALL_RECVALL,
582                 fd, TEVENT_FD_READ, async_recvall_callback,
583                 &state);
584         if (result == NULL) {
585                 return NULL;
586         }
587
588         state->param.param_recvall.fd = fd;
589         state->param.param_recvall.buffer = buffer;
590         state->param.param_recvall.length = length;
591         state->param.param_recvall.flags = flags;
592         state->param.param_recvall.received = 0;
593
594         return result;
595 }
596
597 ssize_t recvall_recv(struct async_req *req, int *perr)
598 {
599         struct async_syscall_state *state = talloc_get_type_abort(
600                 req->private_data, struct async_syscall_state);
601         int err;
602
603         err = async_req_simple_recv_errno(req);
604
605         if (err != 0) {
606                 *perr = err;
607                 return -1;
608         }
609
610         return state->result.result_ssize_t;
611 }
612
613 struct async_connect_state {
614         int fd;
615         int result;
616         int sys_errno;
617         long old_sockflags;
618 };
619
620 static void async_connect_connected(struct tevent_context *ev,
621                                     struct tevent_fd *fde, uint16_t flags,
622                                     void *priv);
623
624 /**
625  * @brief async version of connect(2)
626  * @param[in] mem_ctx   The memory context to hang the result off
627  * @param[in] ev        The event context to work from
628  * @param[in] fd        The socket to recv from
629  * @param[in] address   Where to connect?
630  * @param[in] address_len Length of *address
631  * @retval The async request
632  *
633  * This function sets the socket into non-blocking state to be able to call
634  * connect in an async state. This will be reset when the request is finished.
635  */
636
637 struct tevent_req *async_connect_send(TALLOC_CTX *mem_ctx,
638                                       struct tevent_context *ev,
639                                       int fd, const struct sockaddr *address,
640                                       socklen_t address_len)
641 {
642         struct tevent_req *result;
643         struct async_connect_state *state;
644         struct tevent_fd *fde;
645
646         result = tevent_req_create(
647                 mem_ctx, &state, struct async_connect_state);
648         if (result == NULL) {
649                 return NULL;
650         }
651
652         /**
653          * We have to set the socket to nonblocking for async connect(2). Keep
654          * the old sockflags around.
655          */
656
657         state->fd = fd;
658         state->sys_errno = 0;
659
660         state->old_sockflags = fcntl(fd, F_GETFL, 0);
661         if (state->old_sockflags == -1) {
662                 goto post_errno;
663         }
664
665         set_blocking(fd, false);
666
667         state->result = connect(fd, address, address_len);
668         if (state->result == 0) {
669                 errno = 0;
670                 goto post_errno;
671         }
672
673         /**
674          * A number of error messages show that something good is progressing
675          * and that we have to wait for readability.
676          *
677          * If none of them are present, bail out.
678          */
679
680         if (!(errno == EINPROGRESS || errno == EALREADY ||
681 #ifdef EISCONN
682               errno == EISCONN ||
683 #endif
684               errno == EAGAIN || errno == EINTR)) {
685                 goto post_errno;
686         }
687
688         fde = tevent_add_fd(ev, state, fd, TEVENT_FD_READ | TEVENT_FD_WRITE,
689                            async_connect_connected, result);
690         if (fde == NULL) {
691                 errno = ENOMEM;
692                 goto post_errno;
693         }
694         return result;
695
696  post_errno:
697         state->sys_errno = errno;
698         fcntl(fd, F_SETFL, state->old_sockflags);
699         if (state->sys_errno == 0) {
700                 tevent_req_done(result);
701         } else {
702                 tevent_req_error(result, state->sys_errno);
703         }
704         return tevent_req_post(result, ev);
705 }
706
707 /**
708  * fde event handler for connect(2)
709  * @param[in] ev        The event context that sent us here
710  * @param[in] fde       The file descriptor event associated with the connect
711  * @param[in] flags     Indicate read/writeability of the socket
712  * @param[in] priv      private data, "struct async_req *" in this case
713  */
714
715 static void async_connect_connected(struct tevent_context *ev,
716                                     struct tevent_fd *fde, uint16_t flags,
717                                     void *priv)
718 {
719         struct tevent_req *req = talloc_get_type_abort(
720                 priv, struct tevent_req);
721         struct async_connect_state *state = talloc_get_type_abort(
722                 req->private_state, struct async_connect_state);
723
724         TALLOC_FREE(fde);
725
726         /*
727          * Stevens, Network Programming says that if there's a
728          * successful connect, the socket is only writable. Upon an
729          * error, it's both readable and writable.
730          */
731         if ((flags & (TEVENT_FD_READ|TEVENT_FD_WRITE))
732             == (TEVENT_FD_READ|TEVENT_FD_WRITE)) {
733                 int sockerr;
734                 socklen_t err_len = sizeof(sockerr);
735
736                 if (getsockopt(state->fd, SOL_SOCKET, SO_ERROR,
737                                (void *)&sockerr, &err_len) == 0) {
738                         errno = sockerr;
739                 }
740
741                 state->sys_errno = errno;
742
743                 DEBUG(10, ("connect returned %s\n", strerror(errno)));
744
745                 fcntl(state->fd, F_SETFL, state->old_sockflags);
746                 tevent_req_error(req, state->sys_errno);
747                 return;
748         }
749
750         state->sys_errno = 0;
751         tevent_req_done(req);
752 }
753
754 int async_connect_recv(struct tevent_req *req, int *perrno)
755 {
756         struct async_connect_state *state = talloc_get_type_abort(
757                 req->private_state, struct async_connect_state);
758         int err;
759
760         fcntl(state->fd, F_SETFL, state->old_sockflags);
761
762         if (tevent_req_is_unix_error(req, &err)) {
763                 *perrno = err;
764                 return -1;
765         }
766
767         if (state->sys_errno == 0) {
768                 return 0;
769         }
770
771         *perrno = state->sys_errno;
772         return -1;
773 }