lib/tsocket: add tsocket_connect_send/recv()
[ira/wip.git] / lib / tsocket / tsocket_connect.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    Copyright (C) Stefan Metzmacher 2009
5
6      ** NOTE! The following LGPL license applies to the tevent
7      ** library. This does NOT imply that all of Samba is released
8      ** under the LGPL
9
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.
14
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    Lesser General Public License for more details.
19
20    You should have received a copy of the GNU Lesser General Public
21    License along with this library; if not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "replace.h"
25 #include "system/network.h"
26 #include "tsocket.h"
27 #include "tsocket_internal.h"
28
29 struct tsocket_connect_state {
30         /* this structs are owned by the caller */
31         struct {
32                 struct tsocket_context *sock;
33                 const struct tsocket_address *dst;
34         } caller;
35 };
36
37 static void tsocket_connect_handler(struct tsocket_context *sock,
38                                     void *private_data);
39
40 struct tevent_req *tsocket_connect_send(struct tsocket_context *sock,
41                                         TALLOC_CTX *mem_ctx,
42                                         const struct tsocket_address *dst)
43 {
44         struct tevent_req *req;
45         struct tsocket_connect_state *state;
46         int ret;
47         int err;
48         bool retry;
49         bool dummy;
50
51         req = tevent_req_create(mem_ctx, &state,
52                                 struct tsocket_connect_state);
53         if (!req) {
54                 return NULL;
55         }
56
57         state->caller.sock      = sock;
58         state->caller.dst       = dst;
59
60         ret = tsocket_connect(state->caller.sock,
61                               state->caller.dst);
62         err = tsocket_error_from_errno(ret, errno, &retry);
63         if (retry) {
64                 /* retry later */
65                 goto async;
66         }
67         if (tevent_req_error(req, err)) {
68                 goto post;
69         }
70
71         tevent_req_done(req);
72         goto post;
73
74  async:
75         ret = tsocket_set_readable_handler(state->caller.sock,
76                                            tsocket_connect_handler,
77                                            req);
78         err = tsocket_error_from_errno(ret, errno, &dummy);
79         if (tevent_req_error(req, err)) {
80                 goto post;
81         }
82
83         return req;
84
85  post:
86         return tevent_req_post(req, sock->event.ctx);
87 }
88
89 static void tsocket_connect_handler(struct tsocket_context *sock,
90                                     void *private_data)
91 {
92         struct tevent_req *req = talloc_get_type(private_data,
93                                  struct tevent_req);
94         struct tsocket_connect_state *state = tevent_req_data(req,
95                                               struct tsocket_connect_state);
96         int ret;
97         int err;
98         bool retry;
99
100         ret = tsocket_get_status(state->caller.sock);
101         err = tsocket_error_from_errno(ret, errno, &retry);
102         if (retry) {
103                 /* retry later */
104                 return;
105         }
106         if (tevent_req_error(req, err)) {
107                 return;
108         }
109
110         tevent_req_done(req);
111 }
112
113 int tsocket_connect_recv(struct tevent_req *req, int *perrno)
114 {
115         int ret;
116
117         ret = tsocket_simple_int_recv(req, perrno);
118
119         tevent_req_received(req);
120         return ret;
121 }
122