2 Unix SMB/CIFS implementation.
4 Copyright (C) Stefan Metzmacher 2009
6 ** NOTE! The following LGPL license applies to the tsocket
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/>.
26 #endif /* HAVE_CONFIG_H */
28 #include <atalk/tsocket.h>
30 #include "tsocket_internal.h"
32 struct tdgram_sendto_queue_state {
33 /* this structs are owned by the caller */
35 struct tevent_context *ev;
36 struct tdgram_context *dgram;
39 const struct tsocket_address *dst;
44 static void tdgram_sendto_queue_trigger(struct tevent_req *req,
46 static void tdgram_sendto_queue_done(struct tevent_req *subreq);
48 struct tevent_req *tdgram_sendto_queue_send(TALLOC_CTX *mem_ctx,
49 struct tevent_context *ev,
50 struct tdgram_context *dgram,
51 struct tevent_queue *queue,
54 struct tsocket_address *dst)
56 struct tevent_req *req;
57 struct tdgram_sendto_queue_state *state;
60 req = tevent_req_create(mem_ctx, &state,
61 struct tdgram_sendto_queue_state);
66 state->caller.ev = ev;
67 state->caller.dgram = dgram;
68 state->caller.buf = buf;
69 state->caller.len = len;
70 state->caller.dst = dst;
73 ok = tevent_queue_add(queue,
76 tdgram_sendto_queue_trigger,
79 tevent_req_nomem(NULL, req);
86 tevent_req_post(req, ev);
90 static void tdgram_sendto_queue_trigger(struct tevent_req *req,
93 struct tdgram_sendto_queue_state *state = tevent_req_data(req,
94 struct tdgram_sendto_queue_state);
95 struct tevent_req *subreq;
97 subreq = tdgram_sendto_send(state,
103 if (tevent_req_nomem(subreq, req)) {
106 tevent_req_set_callback(subreq, tdgram_sendto_queue_done, req);
109 static void tdgram_sendto_queue_done(struct tevent_req *subreq)
111 struct tevent_req *req = tevent_req_callback_data(subreq,
113 struct tdgram_sendto_queue_state *state = tevent_req_data(req,
114 struct tdgram_sendto_queue_state);
118 ret = tdgram_sendto_recv(subreq, &sys_errno);
121 tevent_req_error(req, sys_errno);
126 tevent_req_done(req);
129 ssize_t tdgram_sendto_queue_recv(struct tevent_req *req, int *perrno)
131 struct tdgram_sendto_queue_state *state = tevent_req_data(req,
132 struct tdgram_sendto_queue_state);
135 ret = tsocket_simple_int_recv(req, perrno);
140 tevent_req_received(req);
144 struct tstream_readv_pdu_state {
145 /* this structs are owned by the caller */
147 struct tevent_context *ev;
148 struct tstream_context *stream;
149 tstream_readv_pdu_next_vector_t next_vector_fn;
150 void *next_vector_private;
154 * Each call to the callback resets iov and count
155 * the callback allocated the iov as child of our state,
156 * that means we are allowed to modify and free it.
158 * we should call the callback every time we filled the given
159 * vector and ask for a new vector. We return if the callback
162 struct iovec *vector;
166 * the total number of bytes we read,
167 * the return value of the _recv function
172 static void tstream_readv_pdu_ask_for_next_vector(struct tevent_req *req);
173 static void tstream_readv_pdu_readv_done(struct tevent_req *subreq);
175 struct tevent_req *tstream_readv_pdu_send(TALLOC_CTX *mem_ctx,
176 struct tevent_context *ev,
177 struct tstream_context *stream,
178 tstream_readv_pdu_next_vector_t next_vector_fn,
179 void *next_vector_private)
181 struct tevent_req *req;
182 struct tstream_readv_pdu_state *state;
184 req = tevent_req_create(mem_ctx, &state,
185 struct tstream_readv_pdu_state);
190 state->caller.ev = ev;
191 state->caller.stream = stream;
192 state->caller.next_vector_fn = next_vector_fn;
193 state->caller.next_vector_private = next_vector_private;
195 state->vector = NULL;
197 state->total_read = 0;
199 tstream_readv_pdu_ask_for_next_vector(req);
200 if (!tevent_req_is_in_progress(req)) {
207 return tevent_req_post(req, ev);
210 static void tstream_readv_pdu_ask_for_next_vector(struct tevent_req *req)
212 struct tstream_readv_pdu_state *state = tevent_req_data(req,
213 struct tstream_readv_pdu_state);
217 struct tevent_req *subreq;
219 TALLOC_FREE(state->vector);
222 ret = state->caller.next_vector_fn(state->caller.stream,
223 state->caller.next_vector_private,
224 state, &state->vector, &state->count);
226 tevent_req_error(req, errno);
230 if (state->count == 0) {
231 tevent_req_done(req);
235 for (i=0; i < state->count; i++) {
236 size_t tmp = to_read;
237 tmp += state->vector[i].iov_len;
240 tevent_req_error(req, EMSGSIZE);
248 * this is invalid the next vector function should have
249 * reported count == 0.
252 tevent_req_error(req, EINVAL);
256 if (state->total_read + to_read < state->total_read) {
257 tevent_req_error(req, EMSGSIZE);
261 subreq = tstream_readv_send(state,
263 state->caller.stream,
266 if (tevent_req_nomem(subreq, req)) {
269 tevent_req_set_callback(subreq, tstream_readv_pdu_readv_done, req);
272 static void tstream_readv_pdu_readv_done(struct tevent_req *subreq)
274 struct tevent_req *req = tevent_req_callback_data(subreq,
276 struct tstream_readv_pdu_state *state = tevent_req_data(req,
277 struct tstream_readv_pdu_state);
281 ret = tstream_readv_recv(subreq, &sys_errno);
283 tevent_req_error(req, sys_errno);
287 state->total_read += ret;
289 /* ask the callback for a new vector we should fill */
290 tstream_readv_pdu_ask_for_next_vector(req);
293 int tstream_readv_pdu_recv(struct tevent_req *req, int *perrno)
295 struct tstream_readv_pdu_state *state = tevent_req_data(req,
296 struct tstream_readv_pdu_state);
299 ret = tsocket_simple_int_recv(req, perrno);
301 ret = state->total_read;
304 tevent_req_received(req);
308 struct tstream_readv_pdu_queue_state {
309 /* this structs are owned by the caller */
311 struct tevent_context *ev;
312 struct tstream_context *stream;
313 tstream_readv_pdu_next_vector_t next_vector_fn;
314 void *next_vector_private;
319 static void tstream_readv_pdu_queue_trigger(struct tevent_req *req,
321 static void tstream_readv_pdu_queue_done(struct tevent_req *subreq);
323 struct tevent_req *tstream_readv_pdu_queue_send(TALLOC_CTX *mem_ctx,
324 struct tevent_context *ev,
325 struct tstream_context *stream,
326 struct tevent_queue *queue,
327 tstream_readv_pdu_next_vector_t next_vector_fn,
328 void *next_vector_private)
330 struct tevent_req *req;
331 struct tstream_readv_pdu_queue_state *state;
334 req = tevent_req_create(mem_ctx, &state,
335 struct tstream_readv_pdu_queue_state);
340 state->caller.ev = ev;
341 state->caller.stream = stream;
342 state->caller.next_vector_fn = next_vector_fn;
343 state->caller.next_vector_private = next_vector_private;
346 ok = tevent_queue_add(queue,
349 tstream_readv_pdu_queue_trigger,
352 tevent_req_nomem(NULL, req);
359 return tevent_req_post(req, ev);
362 static void tstream_readv_pdu_queue_trigger(struct tevent_req *req,
365 struct tstream_readv_pdu_queue_state *state = tevent_req_data(req,
366 struct tstream_readv_pdu_queue_state);
367 struct tevent_req *subreq;
369 subreq = tstream_readv_pdu_send(state,
371 state->caller.stream,
372 state->caller.next_vector_fn,
373 state->caller.next_vector_private);
374 if (tevent_req_nomem(subreq, req)) {
377 tevent_req_set_callback(subreq, tstream_readv_pdu_queue_done ,req);
380 static void tstream_readv_pdu_queue_done(struct tevent_req *subreq)
382 struct tevent_req *req = tevent_req_callback_data(subreq,
384 struct tstream_readv_pdu_queue_state *state = tevent_req_data(req,
385 struct tstream_readv_pdu_queue_state);
389 ret = tstream_readv_pdu_recv(subreq, &sys_errno);
392 tevent_req_error(req, sys_errno);
397 tevent_req_done(req);
400 int tstream_readv_pdu_queue_recv(struct tevent_req *req, int *perrno)
402 struct tstream_readv_pdu_queue_state *state = tevent_req_data(req,
403 struct tstream_readv_pdu_queue_state);
406 ret = tsocket_simple_int_recv(req, perrno);
411 tevent_req_received(req);
415 struct tstream_writev_queue_state {
416 /* this structs are owned by the caller */
418 struct tevent_context *ev;
419 struct tstream_context *stream;
420 const struct iovec *vector;
426 static void tstream_writev_queue_trigger(struct tevent_req *req,
428 static void tstream_writev_queue_done(struct tevent_req *subreq);
430 struct tevent_req *tstream_writev_queue_send(TALLOC_CTX *mem_ctx,
431 struct tevent_context *ev,
432 struct tstream_context *stream,
433 struct tevent_queue *queue,
434 const struct iovec *vector,
437 struct tevent_req *req;
438 struct tstream_writev_queue_state *state;
441 req = tevent_req_create(mem_ctx, &state,
442 struct tstream_writev_queue_state);
447 state->caller.ev = ev;
448 state->caller.stream = stream;
449 state->caller.vector = vector;
450 state->caller.count = count;
453 ok = tevent_queue_add(queue,
456 tstream_writev_queue_trigger,
459 tevent_req_nomem(NULL, req);
466 return tevent_req_post(req, ev);
469 static void tstream_writev_queue_trigger(struct tevent_req *req,
472 struct tstream_writev_queue_state *state = tevent_req_data(req,
473 struct tstream_writev_queue_state);
474 struct tevent_req *subreq;
476 subreq = tstream_writev_send(state,
478 state->caller.stream,
479 state->caller.vector,
480 state->caller.count);
481 if (tevent_req_nomem(subreq, req)) {
484 tevent_req_set_callback(subreq, tstream_writev_queue_done ,req);
487 static void tstream_writev_queue_done(struct tevent_req *subreq)
489 struct tevent_req *req = tevent_req_callback_data(subreq,
491 struct tstream_writev_queue_state *state = tevent_req_data(req,
492 struct tstream_writev_queue_state);
496 ret = tstream_writev_recv(subreq, &sys_errno);
499 tevent_req_error(req, sys_errno);
504 tevent_req_done(req);
507 int tstream_writev_queue_recv(struct tevent_req *req, int *perrno)
509 struct tstream_writev_queue_state *state = tevent_req_data(req,
510 struct tstream_writev_queue_state);
513 ret = tsocket_simple_int_recv(req, perrno);
518 tevent_req_received(req);