2 Unix SMB/CIFS implementation.
4 Copyright (C) Stefan Metzmacher 2009
6 ** NOTE! The following LGPL license applies to the tevent
7 ** library. This does NOT imply that all of Samba is released
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.
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.
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/>.
25 #include "system/network.h"
27 #include "tsocket_internal.h"
29 struct tsocket_sendto_state {
30 /* this structs are owned by the caller */
32 struct tsocket_context *sock;
35 const struct tsocket_address *dst;
41 static int tsocket_sendto_state_destructor(struct tsocket_sendto_state *state)
43 if (state->caller.sock) {
44 tsocket_set_writeable_handler(state->caller.sock, NULL, NULL);
46 ZERO_STRUCT(state->caller);
51 static void tsocket_sendto_handler(struct tsocket_context *sock,
54 struct tevent_req *tsocket_sendto_send(struct tsocket_context *sock,
58 const struct tsocket_address *dst)
60 struct tevent_req *req;
61 struct tsocket_sendto_state *state;
66 req = tevent_req_create(mem_ctx, &state,
67 struct tsocket_sendto_state);
72 state->caller.sock = sock;
73 state->caller.buf = buf;
74 state->caller.len = len;
75 state->caller.dst = dst;
79 * this is a fast path, not waiting for the
80 * socket to become explicit writeable gains
81 * about 10%-20% performance in benchmark tests.
83 tsocket_sendto_handler(sock, req);
84 if (!tevent_req_is_in_progress(req)) {
88 talloc_set_destructor(state, tsocket_sendto_state_destructor);
90 ret = tsocket_set_writeable_handler(sock,
91 tsocket_sendto_handler,
93 err = tsocket_error_from_errno(ret, errno, &dummy);
94 if (tevent_req_error(req, err)) {
101 return tevent_req_post(req, sock->event.ctx);
104 static void tsocket_sendto_handler(struct tsocket_context *sock,
107 struct tevent_req *req = talloc_get_type(private_data,
109 struct tsocket_sendto_state *state = tevent_req_data(req,
110 struct tsocket_sendto_state);
115 ret = tsocket_sendto(state->caller.sock,
119 err = tsocket_error_from_errno(ret, errno, &retry);
124 if (tevent_req_error(req, err)) {
130 tevent_req_done(req);
133 ssize_t tsocket_sendto_recv(struct tevent_req *req, int *perrno)
135 struct tsocket_sendto_state *state = tevent_req_data(req,
136 struct tsocket_sendto_state);
139 ret = tsocket_simple_int_recv(req, perrno);
144 tevent_req_received(req);
148 struct tsocket_sendto_queue_state {
149 /* this structs are owned by the caller */
151 struct tsocket_context *sock;
154 const struct tsocket_address *dst;
159 static void tsocket_sendto_queue_trigger(struct tevent_req *req,
161 static void tsocket_sendto_queue_done(struct tevent_req *subreq);
164 * @brief Queue a dgram blob for sending through the socket
165 * @param[in] mem_ctx The memory context for the result
166 * @param[in] sock The socket to send the message buffer
167 * @param[in] queue The existing dgram queue
168 * @param[in] buf The message buffer
169 * @param[in] len The message length
170 * @param[in] dst The destination socket address
171 * @retval The async request handle
173 * This function queues a blob for sending to destination through an existing
174 * dgram socket. The async callback is triggered when the whole blob is
175 * delivered to the underlying system socket.
177 * The caller needs to make sure that all non-scalar input parameters hang
178 * arround for the whole lifetime of the request.
180 struct tevent_req *tsocket_sendto_queue_send(TALLOC_CTX *mem_ctx,
181 struct tsocket_context *sock,
182 struct tevent_queue *queue,
185 struct tsocket_address *dst)
187 struct tevent_req *req;
188 struct tsocket_sendto_queue_state *state;
191 req = tevent_req_create(mem_ctx, &state,
192 struct tsocket_sendto_queue_state);
197 state->caller.sock = sock;
198 state->caller.buf = buf;
199 state->caller.len = len;
200 state->caller.dst = dst;
203 ok = tevent_queue_add(queue,
206 tsocket_sendto_queue_trigger,
209 tevent_req_nomem(NULL, req);
216 return tevent_req_post(req, sock->event.ctx);
219 static void tsocket_sendto_queue_trigger(struct tevent_req *req,
222 struct tsocket_sendto_queue_state *state = tevent_req_data(req,
223 struct tsocket_sendto_queue_state);
224 struct tevent_req *subreq;
226 subreq = tsocket_sendto_send(state->caller.sock,
231 if (tevent_req_nomem(subreq, req)) {
234 tevent_req_set_callback(subreq, tsocket_sendto_queue_done ,req);
237 static void tsocket_sendto_queue_done(struct tevent_req *subreq)
239 struct tevent_req *req = tevent_req_callback_data(subreq,
241 struct tsocket_sendto_queue_state *state = tevent_req_data(req,
242 struct tsocket_sendto_queue_state);
246 ret = tsocket_sendto_recv(subreq, &sys_errno);
249 tevent_req_error(req, sys_errno);
254 tevent_req_done(req);
257 ssize_t tsocket_sendto_queue_recv(struct tevent_req *req, int *perrno)
259 struct tsocket_sendto_queue_state *state = tevent_req_data(req,
260 struct tsocket_sendto_queue_state);
263 ret = tsocket_simple_int_recv(req, perrno);
268 tevent_req_received(req);