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/>.
25 #include "system/filesys.h"
27 #include "tsocket_internal.h"
29 struct tdgram_sendto_queue_state
{
30 /* this structs are owned by the caller */
32 struct tevent_context
*ev
;
33 struct tdgram_context
*dgram
;
36 const struct tsocket_address
*dst
;
41 static void tdgram_sendto_queue_trigger(struct tevent_req
*req
,
43 static void tdgram_sendto_queue_done(struct tevent_req
*subreq
);
45 struct tevent_req
*tdgram_sendto_queue_send(TALLOC_CTX
*mem_ctx
,
46 struct tevent_context
*ev
,
47 struct tdgram_context
*dgram
,
48 struct tevent_queue
*queue
,
51 struct tsocket_address
*dst
)
53 struct tevent_req
*req
;
54 struct tdgram_sendto_queue_state
*state
;
55 struct tevent_queue_entry
*e
;
57 req
= tevent_req_create(mem_ctx
, &state
,
58 struct tdgram_sendto_queue_state
);
63 state
->caller
.ev
= ev
;
64 state
->caller
.dgram
= dgram
;
65 state
->caller
.buf
= buf
;
66 state
->caller
.len
= len
;
67 state
->caller
.dst
= dst
;
71 * we use tevent_queue_add_optimize_empty() with allow_direct
72 * in order to optimize for the empty queue case.
74 e
= tevent_queue_add_optimize_empty(
78 tdgram_sendto_queue_trigger
,
80 if (tevent_req_nomem(e
, req
)) {
81 return tevent_req_post(req
, ev
);
83 if (!tevent_req_is_in_progress(req
)) {
84 return 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
;
332 struct tevent_queue_entry
*e
;
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
;
347 * we use tevent_queue_add_optimize_empty() with allow_direct
348 * in order to optimize for the empty queue case.
350 e
= tevent_queue_add_optimize_empty(
354 tstream_readv_pdu_queue_trigger
,
356 if (tevent_req_nomem(e
, req
)) {
357 return tevent_req_post(req
, ev
);
359 if (!tevent_req_is_in_progress(req
)) {
360 return tevent_req_post(req
, ev
);
366 static void tstream_readv_pdu_queue_trigger(struct tevent_req
*req
,
369 struct tstream_readv_pdu_queue_state
*state
= tevent_req_data(req
,
370 struct tstream_readv_pdu_queue_state
);
371 struct tevent_req
*subreq
;
373 subreq
= tstream_readv_pdu_send(state
,
375 state
->caller
.stream
,
376 state
->caller
.next_vector_fn
,
377 state
->caller
.next_vector_private
);
378 if (tevent_req_nomem(subreq
, req
)) {
381 tevent_req_set_callback(subreq
, tstream_readv_pdu_queue_done
,req
);
384 static void tstream_readv_pdu_queue_done(struct tevent_req
*subreq
)
386 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
388 struct tstream_readv_pdu_queue_state
*state
= tevent_req_data(req
,
389 struct tstream_readv_pdu_queue_state
);
393 ret
= tstream_readv_pdu_recv(subreq
, &sys_errno
);
396 tevent_req_error(req
, sys_errno
);
401 tevent_req_done(req
);
404 int tstream_readv_pdu_queue_recv(struct tevent_req
*req
, int *perrno
)
406 struct tstream_readv_pdu_queue_state
*state
= tevent_req_data(req
,
407 struct tstream_readv_pdu_queue_state
);
410 ret
= tsocket_simple_int_recv(req
, perrno
);
415 tevent_req_received(req
);
419 struct tstream_writev_queue_state
{
420 /* this structs are owned by the caller */
422 struct tevent_context
*ev
;
423 struct tstream_context
*stream
;
424 const struct iovec
*vector
;
430 static void tstream_writev_queue_trigger(struct tevent_req
*req
,
432 static void tstream_writev_queue_done(struct tevent_req
*subreq
);
434 struct tevent_req
*tstream_writev_queue_send(TALLOC_CTX
*mem_ctx
,
435 struct tevent_context
*ev
,
436 struct tstream_context
*stream
,
437 struct tevent_queue
*queue
,
438 const struct iovec
*vector
,
441 struct tevent_req
*req
;
442 struct tstream_writev_queue_state
*state
;
443 struct tevent_queue_entry
*e
;
445 req
= tevent_req_create(mem_ctx
, &state
,
446 struct tstream_writev_queue_state
);
451 state
->caller
.ev
= ev
;
452 state
->caller
.stream
= stream
;
453 state
->caller
.vector
= vector
;
454 state
->caller
.count
= count
;
458 * we use tevent_queue_add_optimize_empty() with allow_direct
459 * in order to optimize for the empty queue case.
461 e
= tevent_queue_add_optimize_empty(
465 tstream_writev_queue_trigger
,
467 if (tevent_req_nomem(e
, req
)) {
468 return tevent_req_post(req
, ev
);
470 if (!tevent_req_is_in_progress(req
)) {
471 return tevent_req_post(req
, ev
);
477 static void tstream_writev_queue_trigger(struct tevent_req
*req
,
480 struct tstream_writev_queue_state
*state
= tevent_req_data(req
,
481 struct tstream_writev_queue_state
);
482 struct tevent_req
*subreq
;
484 subreq
= tstream_writev_send(state
,
486 state
->caller
.stream
,
487 state
->caller
.vector
,
488 state
->caller
.count
);
489 if (tevent_req_nomem(subreq
, req
)) {
492 tevent_req_set_callback(subreq
, tstream_writev_queue_done
,req
);
495 static void tstream_writev_queue_done(struct tevent_req
*subreq
)
497 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
499 struct tstream_writev_queue_state
*state
= tevent_req_data(req
,
500 struct tstream_writev_queue_state
);
504 ret
= tstream_writev_recv(subreq
, &sys_errno
);
507 tevent_req_error(req
, sys_errno
);
512 tevent_req_done(req
);
515 int tstream_writev_queue_recv(struct tevent_req
*req
, int *perrno
)
517 struct tstream_writev_queue_state
*state
= tevent_req_data(req
,
518 struct tstream_writev_queue_state
);
521 ret
= tsocket_simple_int_recv(req
, perrno
);
526 tevent_req_received(req
);