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