73ff6f28709b89a8fa50f2f00815b5b07c655495
[metze/samba/wip.git] / source3 / lib / 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
22 /**
23  * Discriminator for async_syscall_state
24  */
25 enum async_syscall_type {
26         ASYNC_SYSCALL_SEND,
27         ASYNC_SYSCALL_SENDALL,
28         ASYNC_SYSCALL_RECV,
29         ASYNC_SYSCALL_RECVALL,
30         ASYNC_SYSCALL_CONNECT
31 };
32
33 /**
34  * Holder for syscall arguments and the result
35  */
36
37 struct async_syscall_state {
38         enum async_syscall_type syscall_type;
39         struct fd_event *fde;
40
41         union {
42                 struct param_send {
43                         int fd;
44                         const void *buffer;
45                         size_t length;
46                         int flags;
47                 } param_send;
48                 struct param_sendall {
49                         int fd;
50                         const void *buffer;
51                         size_t length;
52                         int flags;
53                         size_t sent;
54                 } param_sendall;
55                 struct param_recv {
56                         int fd;
57                         void *buffer;
58                         size_t length;
59                         int flags;
60                 } param_recv;
61                 struct param_recvall {
62                         int fd;
63                         void *buffer;
64                         size_t length;
65                         int flags;
66                         size_t received;
67                 } param_recvall;
68                 struct param_connect {
69                         /**
70                          * connect needs to be done on a nonblocking
71                          * socket. Keep the old flags around
72                          */
73                         long old_sockflags;
74                         int fd;
75                         const struct sockaddr *address;
76                         socklen_t address_len;
77                 } param_connect;
78         } param;
79
80         union {
81                 ssize_t result_ssize_t;
82                 size_t result_size_t;
83                 int result_int;
84         } result;
85         int sys_errno;
86 };
87
88 /**
89  * @brief Create a new async syscall req
90  * @param[in] mem_ctx   The memory context to hang the result off
91  * @param[in] ev        The event context to work from
92  * @param[in] type      Which syscall will this be
93  * @param[in] pstate    Where to put the newly created private_data state
94  * @retval The new request
95  *
96  * This is a helper function to prepare a new struct async_req with an
97  * associated struct async_syscall_state. The async_syscall_state will be put
98  * into the async_req as private_data.
99  */
100
101 static struct async_req *async_syscall_new(TALLOC_CTX *mem_ctx,
102                                            struct event_context *ev,
103                                            enum async_syscall_type type,
104                                            struct async_syscall_state **pstate)
105 {
106         struct async_req *result;
107         struct async_syscall_state *state;
108
109         if (!async_req_setup(mem_ctx, &result, &state,
110                              struct async_syscall_state)) {
111                 return NULL;
112         }
113         state->syscall_type = type;
114
115         result->private_data = state;
116
117         *pstate = state;
118
119         return result;
120 }
121
122 /**
123  * @brief Create a new async syscall req based on a fd
124  * @param[in] mem_ctx   The memory context to hang the result off
125  * @param[in] ev        The event context to work from
126  * @param[in] type      Which syscall will this be
127  * @param[in] fd        The file descriptor we work on
128  * @param[in] fde_flags EVENT_FD_READ/WRITE -- what are we interested in?
129  * @param[in] fde_cb    The callback function for the file descriptor event
130  * @param[in] pstate    Where to put the newly created private_data state
131  * @retval The new request
132  *
133  * This is a helper function to prepare a new struct async_req with an
134  * associated struct async_syscall_state and an associated file descriptor
135  * event.
136  */
137
138 static struct async_req *async_fde_syscall_new(
139         TALLOC_CTX *mem_ctx,
140         struct event_context *ev,
141         enum async_syscall_type type,
142         int fd,
143         uint16_t fde_flags,
144         void (*fde_cb)(struct event_context *ev,
145                        struct fd_event *fde, uint16_t flags,
146                        void *priv),
147         struct async_syscall_state **pstate)
148 {
149         struct async_req *result;
150         struct async_syscall_state *state;
151
152         result = async_syscall_new(mem_ctx, ev, type, &state);
153         if (result == NULL) {
154                 return NULL;
155         }
156
157         state->fde = event_add_fd(ev, state, fd, fde_flags, fde_cb, result);
158         if (state->fde == NULL) {
159                 TALLOC_FREE(result);
160                 return NULL;
161         }
162         *pstate = state;
163         return result;
164 }
165
166 /**
167  * Retrieve a ssize_t typed result from an async syscall
168  * @param[in] req       The syscall that has just finished
169  * @param[out] perrno   Where to put the syscall's errno
170  * @retval The return value from the asynchronously called syscall
171  */
172
173 ssize_t async_syscall_result_ssize_t(struct async_req *req, int *perrno)
174 {
175         struct async_syscall_state *state = talloc_get_type_abort(
176                 req->private_data, struct async_syscall_state);
177
178         *perrno = state->sys_errno;
179         return state->result.result_ssize_t;
180 }
181
182 /**
183  * Retrieve a size_t typed result from an async syscall
184  * @param[in] req       The syscall that has just finished
185  * @param[out] perrno   Where to put the syscall's errno
186  * @retval The return value from the asynchronously called syscall
187  */
188
189 size_t async_syscall_result_size_t(struct async_req *req, int *perrno)
190 {
191         struct async_syscall_state *state = talloc_get_type_abort(
192                 req->private_data, struct async_syscall_state);
193
194         *perrno = state->sys_errno;
195         return state->result.result_size_t;
196 }
197
198 /**
199  * Retrieve a int 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 int async_syscall_result_int(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_int;
212 }
213
214 /**
215  * fde event handler for the "send" syscall
216  * @param[in] ev        The event context that sent us here
217  * @param[in] fde       The file descriptor event associated with the send
218  * @param[in] flags     Can only be EVENT_FD_WRITE here
219  * @param[in] priv      private data, "struct async_req *" in this case
220  */
221
222 static void async_send_callback(struct event_context *ev,
223                                 struct fd_event *fde, uint16_t flags,
224                                 void *priv)
225 {
226         struct async_req *req = talloc_get_type_abort(
227                 priv, struct async_req);
228         struct async_syscall_state *state = talloc_get_type_abort(
229                 req->private_data, struct async_syscall_state);
230         struct param_send *p = &state->param.param_send;
231
232         if (state->syscall_type != ASYNC_SYSCALL_SEND) {
233                 async_req_error(req, NT_STATUS_INTERNAL_ERROR);
234                 return;
235         }
236
237         state->result.result_ssize_t = send(p->fd, p->buffer, p->length,
238                                             p->flags);
239         state->sys_errno = errno;
240
241         TALLOC_FREE(state->fde);
242
243         async_req_done(req);
244 }
245
246 /**
247  * Async version of send(2)
248  * @param[in] mem_ctx   The memory context to hang the result off
249  * @param[in] ev        The event context to work from
250  * @param[in] fd        The socket to send to
251  * @param[in] buffer    The buffer to send
252  * @param[in] length    How many bytes to send
253  * @param[in] flags     flags passed to send(2)
254  *
255  * This function is a direct counterpart of send(2)
256  */
257
258 struct async_req *async_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
259                              int fd, const void *buffer, size_t length,
260                              int flags)
261 {
262         struct async_req *result;
263         struct async_syscall_state *state;
264
265         result = async_fde_syscall_new(
266                 mem_ctx, ev, ASYNC_SYSCALL_SEND,
267                 fd, EVENT_FD_WRITE, async_send_callback,
268                 &state);
269         if (result == NULL) {
270                 return NULL;
271         }
272
273         state->param.param_send.fd = fd;
274         state->param.param_send.buffer = buffer;
275         state->param.param_send.length = length;
276         state->param.param_send.flags = flags;
277
278         return result;
279 }
280
281 /**
282  * fde event handler for the "sendall" syscall group
283  * @param[in] ev        The event context that sent us here
284  * @param[in] fde       The file descriptor event associated with the send
285  * @param[in] flags     Can only be EVENT_FD_WRITE here
286  * @param[in] priv      private data, "struct async_req *" in this case
287  */
288
289 static void async_sendall_callback(struct event_context *ev,
290                                    struct fd_event *fde, uint16_t flags,
291                                    void *priv)
292 {
293         struct async_req *req = talloc_get_type_abort(
294                 priv, struct async_req);
295         struct async_syscall_state *state = talloc_get_type_abort(
296                 req->private_data, struct async_syscall_state);
297         struct param_sendall *p = &state->param.param_sendall;
298
299         if (state->syscall_type != ASYNC_SYSCALL_SENDALL) {
300                 async_req_error(req, NT_STATUS_INTERNAL_ERROR);
301                 return;
302         }
303
304         state->result.result_ssize_t = send(p->fd, (char *)p->buffer + p->sent,
305                                             p->length - p->sent, p->flags);
306         state->sys_errno = errno;
307
308         if (state->result.result_ssize_t == -1) {
309                 async_req_error(req, map_nt_error_from_unix(state->sys_errno));
310                 return;
311         }
312
313         if (state->result.result_ssize_t == 0) {
314                 async_req_error(req, NT_STATUS_END_OF_FILE);
315                 return;
316         }
317
318         p->sent += state->result.result_ssize_t;
319         if (p->sent > p->length) {
320                 async_req_error(req, NT_STATUS_INTERNAL_ERROR);
321                 return;
322         }
323
324         if (p->sent == p->length) {
325                 TALLOC_FREE(state->fde);
326                 async_req_done(req);
327         }
328 }
329
330 /**
331  * @brief Send all bytes to a socket
332  * @param[in] mem_ctx   The memory context to hang the result off
333  * @param[in] ev        The event context to work from
334  * @param[in] fd        The socket to send to
335  * @param[in] buffer    The buffer to send
336  * @param[in] length    How many bytes to send
337  * @param[in] flags     flags passed to send(2)
338  *
339  * async_sendall calls send(2) as long as it is necessary to send all of the
340  * "length" bytes
341  */
342
343 struct async_req *sendall_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
344                                int fd, const void *buffer, size_t length,
345                                int flags)
346 {
347         struct async_req *result;
348         struct async_syscall_state *state;
349
350         result = async_fde_syscall_new(
351                 mem_ctx, ev, ASYNC_SYSCALL_SENDALL,
352                 fd, EVENT_FD_WRITE, async_sendall_callback,
353                 &state);
354         if (result == NULL) {
355                 return NULL;
356         }
357
358         state->param.param_sendall.fd = fd;
359         state->param.param_sendall.buffer = buffer;
360         state->param.param_sendall.length = length;
361         state->param.param_sendall.flags = flags;
362         state->param.param_sendall.sent = 0;
363
364         return result;
365 }
366
367 NTSTATUS sendall_recv(struct async_req *req)
368 {
369         return async_req_simple_recv(req);
370 }
371
372 /**
373  * fde event handler for the "recv" syscall
374  * @param[in] ev        The event context that sent us here
375  * @param[in] fde       The file descriptor event associated with the recv
376  * @param[in] flags     Can only be EVENT_FD_READ here
377  * @param[in] priv      private data, "struct async_req *" in this case
378  */
379
380 static void async_recv_callback(struct event_context *ev,
381                                 struct fd_event *fde, uint16_t flags,
382                                 void *priv)
383 {
384         struct async_req *req = talloc_get_type_abort(
385                 priv, struct async_req);
386         struct async_syscall_state *state = talloc_get_type_abort(
387                 req->private_data, struct async_syscall_state);
388         struct param_recv *p = &state->param.param_recv;
389
390         if (state->syscall_type != ASYNC_SYSCALL_RECV) {
391                 async_req_error(req, NT_STATUS_INTERNAL_ERROR);
392                 return;
393         }
394
395         state->result.result_ssize_t = recv(p->fd, p->buffer, p->length,
396                                             p->flags);
397         state->sys_errno = errno;
398
399         TALLOC_FREE(state->fde);
400
401         async_req_done(req);
402 }
403
404 /**
405  * Async version of recv(2)
406  * @param[in] mem_ctx   The memory context to hang the result off
407  * @param[in] ev        The event context to work from
408  * @param[in] fd        The socket to recv from
409  * @param[in] buffer    The buffer to recv into
410  * @param[in] length    How many bytes to recv
411  * @param[in] flags     flags passed to recv(2)
412  *
413  * This function is a direct counterpart of recv(2)
414  */
415
416 struct async_req *async_recv(TALLOC_CTX *mem_ctx, struct event_context *ev,
417                              int fd, void *buffer, size_t length,
418                              int flags)
419 {
420         struct async_req *result;
421         struct async_syscall_state *state;
422
423         result = async_fde_syscall_new(
424                 mem_ctx, ev, ASYNC_SYSCALL_RECV,
425                 fd, EVENT_FD_READ, async_recv_callback,
426                 &state);
427
428         if (result == NULL) {
429                 return NULL;
430         }
431
432         state->param.param_recv.fd = fd;
433         state->param.param_recv.buffer = buffer;
434         state->param.param_recv.length = length;
435         state->param.param_recv.flags = flags;
436
437         return result;
438 }
439
440 /**
441  * fde event handler for the "recvall" syscall group
442  * @param[in] ev        The event context that sent us here
443  * @param[in] fde       The file descriptor event associated with the recv
444  * @param[in] flags     Can only be EVENT_FD_READ here
445  * @param[in] priv      private data, "struct async_req *" in this case
446  */
447
448 static void async_recvall_callback(struct event_context *ev,
449                                    struct fd_event *fde, uint16_t flags,
450                                    void *priv)
451 {
452         struct async_req *req = talloc_get_type_abort(
453                 priv, struct async_req);
454         struct async_syscall_state *state = talloc_get_type_abort(
455                 req->private_data, struct async_syscall_state);
456         struct param_recvall *p = &state->param.param_recvall;
457
458         if (state->syscall_type != ASYNC_SYSCALL_RECVALL) {
459                 async_req_error(req, NT_STATUS_INTERNAL_ERROR);
460                 return;
461         }
462
463         state->result.result_ssize_t = recv(p->fd,
464                                             (char *)p->buffer + p->received,
465                                             p->length - p->received, p->flags);
466         state->sys_errno = errno;
467
468         if (state->result.result_ssize_t == -1) {
469                 async_req_error(req, map_nt_error_from_unix(state->sys_errno));
470                 return;
471         }
472
473         if (state->result.result_ssize_t == 0) {
474                 async_req_error(req, NT_STATUS_END_OF_FILE);
475                 return;
476         }
477
478         p->received += state->result.result_ssize_t;
479         if (p->received > p->length) {
480                 async_req_error(req, NT_STATUS_INTERNAL_ERROR);
481                 return;
482         }
483
484         if (p->received == p->length) {
485                 TALLOC_FREE(state->fde);
486                 async_req_done(req);
487         }
488 }
489
490 /**
491  * Receive a specified number of bytes from a socket
492  * @param[in] mem_ctx   The memory context to hang the result off
493  * @param[in] ev        The event context to work from
494  * @param[in] fd        The socket to recv from
495  * @param[in] buffer    The buffer to recv into
496  * @param[in] length    How many bytes to recv
497  * @param[in] flags     flags passed to recv(2)
498  *
499  * async_recvall will call recv(2) until "length" bytes are received
500  */
501
502 struct async_req *recvall_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
503                                int fd, void *buffer, size_t length,
504                                int flags)
505 {
506         struct async_req *result;
507         struct async_syscall_state *state;
508
509         result = async_fde_syscall_new(
510                 mem_ctx, ev, ASYNC_SYSCALL_RECVALL,
511                 fd, EVENT_FD_READ, async_recvall_callback,
512                 &state);
513         if (result == NULL) {
514                 return NULL;
515         }
516
517         state->param.param_recvall.fd = fd;
518         state->param.param_recvall.buffer = buffer;
519         state->param.param_recvall.length = length;
520         state->param.param_recvall.flags = flags;
521         state->param.param_recvall.received = 0;
522
523         return result;
524 }
525
526 NTSTATUS recvall_recv(struct async_req *req)
527 {
528         return async_req_simple_recv(req);
529 }
530
531 struct async_connect_state {
532         int fd;
533         int result;
534         int sys_errno;
535         long old_sockflags;
536 };
537
538 static void async_connect_connected(struct event_context *ev,
539                                     struct fd_event *fde, uint16_t flags,
540                                     void *priv);
541
542 /**
543  * @brief async version of connect(2)
544  * @param[in] mem_ctx   The memory context to hang the result off
545  * @param[in] ev        The event context to work from
546  * @param[in] fd        The socket to recv from
547  * @param[in] address   Where to connect?
548  * @param[in] address_len Length of *address
549  * @retval The async request
550  *
551  * This function sets the socket into non-blocking state to be able to call
552  * connect in an async state. This will be reset when the request is finished.
553  */
554
555 struct async_req *async_connect_send(TALLOC_CTX *mem_ctx,
556                                      struct event_context *ev,
557                                      int fd, const struct sockaddr *address,
558                                      socklen_t address_len)
559 {
560         struct async_req *result;
561         struct async_connect_state *state;
562         struct fd_event *fde;
563         NTSTATUS status;
564
565         if (!async_req_setup(mem_ctx, &result, &state,
566                              struct async_connect_state)) {
567                 return NULL;
568         }
569
570         /**
571          * We have to set the socket to nonblocking for async connect(2). Keep
572          * the old sockflags around.
573          */
574
575         state->fd = fd;
576         state->sys_errno = 0;
577
578         state->old_sockflags = sys_fcntl_long(fd, F_GETFL, 0);
579         if (state->old_sockflags == -1) {
580                 goto post_errno;
581         }
582
583         set_blocking(fd, false);
584
585         state->result = connect(fd, address, address_len);
586         if (state->result == 0) {
587                 state->sys_errno = 0;
588                 status = NT_STATUS_OK;
589                 goto post_status;
590         }
591
592         /**
593          * A number of error messages show that something good is progressing
594          * and that we have to wait for readability.
595          *
596          * If none of them are present, bail out.
597          */
598
599         if (!(errno == EINPROGRESS || errno == EALREADY ||
600 #ifdef EISCONN
601               errno == EISCONN ||
602 #endif
603               errno == EAGAIN || errno == EINTR)) {
604                 goto post_errno;
605         }
606
607         fde = event_add_fd(ev, state, fd, EVENT_FD_READ | EVENT_FD_WRITE,
608                            async_connect_connected, result);
609         if (fde == NULL) {
610                 status = NT_STATUS_NO_MEMORY;
611                 goto post_status;
612         }
613         return result;
614
615  post_errno:
616         state->sys_errno = errno;
617         status = map_nt_error_from_unix(state->sys_errno);
618  post_status:
619         sys_fcntl_long(fd, F_SETFL, state->old_sockflags);
620         if (!async_post_status(result, ev, status)) {
621                 goto fail;
622         }
623         return result;
624  fail:
625         TALLOC_FREE(result);
626         return NULL;
627 }
628
629 /**
630  * fde event handler for connect(2)
631  * @param[in] ev        The event context that sent us here
632  * @param[in] fde       The file descriptor event associated with the connect
633  * @param[in] flags     Indicate read/writeability of the socket
634  * @param[in] priv      private data, "struct async_req *" in this case
635  */
636
637 static void async_connect_connected(struct event_context *ev,
638                                     struct fd_event *fde, uint16_t flags,
639                                     void *priv)
640 {
641         struct async_req *req = talloc_get_type_abort(
642                 priv, struct async_req);
643         struct async_connect_state *state = talloc_get_type_abort(
644                 req->private_data, struct async_connect_state);
645
646         TALLOC_FREE(fde);
647
648         /*
649          * Stevens, Network Programming says that if there's a
650          * successful connect, the socket is only writable. Upon an
651          * error, it's both readable and writable.
652          */
653         if ((flags & (EVENT_FD_READ|EVENT_FD_WRITE))
654             == (EVENT_FD_READ|EVENT_FD_WRITE)) {
655                 int sockerr;
656                 socklen_t err_len = sizeof(sockerr);
657
658                 if (getsockopt(state->fd, SOL_SOCKET, SO_ERROR,
659                                (void *)&sockerr, &err_len) == 0) {
660                         errno = sockerr;
661                 }
662
663                 state->sys_errno = errno;
664
665                 DEBUG(10, ("connect returned %s\n", strerror(errno)));
666
667                 sys_fcntl_long(state->fd, F_SETFL, state->old_sockflags);
668                 async_req_error(req, map_nt_error_from_unix(state->sys_errno));
669                 return;
670         }
671
672         state->sys_errno = 0;
673         async_req_done(req);
674 }
675
676 NTSTATUS async_connect_recv(struct async_req *req, int *perrno)
677 {
678         struct async_connect_state *state = talloc_get_type_abort(
679                 req->private_data, struct async_connect_state);
680         NTSTATUS status;
681
682         sys_fcntl_long(state->fd, F_SETFL, state->old_sockflags);
683
684         *perrno = state->sys_errno;
685
686         if (async_req_is_error(req, &status)) {
687                 return status;
688         }
689         if (state->sys_errno == 0) {
690                 return NT_STATUS_OK;
691         }
692         return map_nt_error_from_unix(state->sys_errno);
693 }