2 Unix SMB/CIFS implementation.
4 implements a non-blocking connect operation that is aware of the samba4
7 Copyright (C) Andrew Tridgell 2005
8 Copyright (C) Volker Lendecke 2005
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program 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
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "lib/socket/socket.h"
26 #include "lib/events/events.h"
27 #include "libcli/composite/composite.h"
30 struct connect_state
{
31 struct socket_context
*sock
;
32 const struct socket_address
*my_address
;
33 const struct socket_address
*server_address
;
37 static void socket_connect_handler(struct tevent_context
*ev
,
38 struct tevent_fd
*fde
,
39 uint16_t flags
, void *private_data
);
42 call the real socket_connect() call, and setup event handler
44 static void socket_send_connect(struct composite_context
*result
)
46 struct tevent_fd
*fde
;
47 struct connect_state
*state
= talloc_get_type(result
->private_data
,
48 struct connect_state
);
50 result
->status
= socket_connect(state
->sock
,
52 state
->server_address
,
54 if (NT_STATUS_IS_ERR(result
->status
) &&
55 !NT_STATUS_EQUAL(result
->status
,
56 NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
57 composite_error(result
, result
->status
);
61 fde
= tevent_add_fd(result
->event_ctx
, result
,
62 socket_get_fd(state
->sock
),
63 TEVENT_FD_READ
|TEVENT_FD_WRITE
,
64 socket_connect_handler
, result
);
65 composite_nomem(fde
, result
);
70 send a socket connect, potentially doing some name resolution first
72 struct composite_context
*socket_connect_send(struct socket_context
*sock
,
73 struct socket_address
*my_address
,
74 struct socket_address
*server_address
,
76 struct tevent_context
*event_ctx
)
78 struct composite_context
*result
;
79 struct connect_state
*state
;
81 result
= composite_create(sock
, event_ctx
);
82 if (result
== NULL
) return NULL
;
84 state
= talloc_zero(result
, struct connect_state
);
85 if (composite_nomem(state
, result
)) return result
;
86 result
->private_data
= state
;
88 state
->sock
= talloc_reference(state
, sock
);
89 if (composite_nomem(state
->sock
, result
)) return result
;
92 void *ref
= talloc_reference(state
, my_address
);
93 if (composite_nomem(ref
, result
)) {
96 state
->my_address
= my_address
;
100 void *ref
= talloc_reference(state
, server_address
);
101 if (composite_nomem(ref
, result
)) {
104 state
->server_address
= server_address
;
107 state
->flags
= flags
;
109 set_blocking(socket_get_fd(sock
), false);
111 socket_send_connect(result
);
117 handle write events on connect completion
119 static void socket_connect_handler(struct tevent_context
*ev
,
120 struct tevent_fd
*fde
,
121 uint16_t flags
, void *private_data
)
123 struct composite_context
*result
=
124 talloc_get_type(private_data
, struct composite_context
);
125 struct connect_state
*state
= talloc_get_type(result
->private_data
,
126 struct connect_state
);
128 result
->status
= socket_connect_complete(state
->sock
, state
->flags
);
129 if (!composite_is_ok(result
)) return;
131 composite_done(result
);
135 wait for a socket_connect_send() to finish
137 NTSTATUS
socket_connect_recv(struct composite_context
*result
)
139 NTSTATUS status
= composite_wait(result
);
146 like socket_connect() but takes an event context, doing a semi-async connect
148 NTSTATUS
socket_connect_ev(struct socket_context
*sock
,
149 struct socket_address
*my_address
,
150 struct socket_address
*server_address
,
152 struct tevent_context
*ev
)
154 struct composite_context
*ctx
;
155 ctx
= socket_connect_send(sock
, my_address
,
156 server_address
, flags
, ev
);
157 return socket_connect_recv(ctx
);