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
;
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
;
70 ok
= tevent_queue_add(queue
,
73 tdgram_sendto_queue_trigger
,
76 tevent_req_nomem(NULL
, req
);
83 tevent_req_post(req
, ev
);
87 static void tdgram_sendto_queue_trigger(struct tevent_req
*req
,
90 struct tdgram_sendto_queue_state
*state
= tevent_req_data(req
,
91 struct tdgram_sendto_queue_state
);
92 struct tevent_req
*subreq
;
94 subreq
= tdgram_sendto_send(state
,
100 if (tevent_req_nomem(subreq
, req
)) {
103 tevent_req_set_callback(subreq
, tdgram_sendto_queue_done
, req
);
106 static void tdgram_sendto_queue_done(struct tevent_req
*subreq
)
108 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
110 struct tdgram_sendto_queue_state
*state
= tevent_req_data(req
,
111 struct tdgram_sendto_queue_state
);
115 ret
= tdgram_sendto_recv(subreq
, &sys_errno
);
118 tevent_req_error(req
, sys_errno
);
123 tevent_req_done(req
);
126 ssize_t
tdgram_sendto_queue_recv(struct tevent_req
*req
, int *perrno
)
128 struct tdgram_sendto_queue_state
*state
= tevent_req_data(req
,
129 struct tdgram_sendto_queue_state
);
132 ret
= tsocket_simple_int_recv(req
, perrno
);
137 tevent_req_received(req
);
141 struct tstream_readv_pdu_state
{
142 /* this structs are owned by the caller */
144 struct tevent_context
*ev
;
145 struct tstream_context
*stream
;
146 tstream_readv_pdu_next_vector_t next_vector_fn
;
147 void *next_vector_private
;
151 * Each call to the callback resets iov and count
152 * the callback allocated the iov as child of our state,
153 * that means we are allowed to modify and free it.
155 * we should call the callback every time we filled the given
156 * vector and ask for a new vector. We return if the callback
159 struct iovec
*vector
;
163 * the total number of bytes we read,
164 * the return value of the _recv function
169 static void tstream_readv_pdu_ask_for_next_vector(struct tevent_req
*req
);
170 static void tstream_readv_pdu_readv_done(struct tevent_req
*subreq
);
172 struct tevent_req
*tstream_readv_pdu_send(TALLOC_CTX
*mem_ctx
,
173 struct tevent_context
*ev
,
174 struct tstream_context
*stream
,
175 tstream_readv_pdu_next_vector_t next_vector_fn
,
176 void *next_vector_private
)
178 struct tevent_req
*req
;
179 struct tstream_readv_pdu_state
*state
;
181 req
= tevent_req_create(mem_ctx
, &state
,
182 struct tstream_readv_pdu_state
);
187 state
->caller
.ev
= ev
;
188 state
->caller
.stream
= stream
;
189 state
->caller
.next_vector_fn
= next_vector_fn
;
190 state
->caller
.next_vector_private
= next_vector_private
;
192 state
->vector
= NULL
;
194 state
->total_read
= 0;
196 tstream_readv_pdu_ask_for_next_vector(req
);
197 if (!tevent_req_is_in_progress(req
)) {
204 return tevent_req_post(req
, ev
);
207 static void tstream_readv_pdu_ask_for_next_vector(struct tevent_req
*req
)
209 struct tstream_readv_pdu_state
*state
= tevent_req_data(req
,
210 struct tstream_readv_pdu_state
);
214 struct tevent_req
*subreq
;
215 bool optimize
= false;
216 bool save_optimize
= false;
218 if (state
->count
> 0) {
220 * This is not the first time we asked for a vector,
221 * which means parts of the pdu already arrived.
223 * In this case it make sense to enable
224 * a syscall/performance optimization if the
225 * low level tstream implementation supports it.
230 TALLOC_FREE(state
->vector
);
233 ret
= state
->caller
.next_vector_fn(state
->caller
.stream
,
234 state
->caller
.next_vector_private
,
235 state
, &state
->vector
, &state
->count
);
237 tevent_req_error(req
, errno
);
241 if (state
->count
== 0) {
242 tevent_req_done(req
);
246 for (i
=0; i
< state
->count
; i
++) {
247 size_t tmp
= to_read
;
248 tmp
+= state
->vector
[i
].iov_len
;
251 tevent_req_error(req
, EMSGSIZE
);
259 * this is invalid the next vector function should have
260 * reported count == 0.
263 tevent_req_error(req
, EINVAL
);
267 if (state
->total_read
+ to_read
< state
->total_read
) {
268 tevent_req_error(req
, EMSGSIZE
);
274 * If the low level stream is a bsd socket
275 * we will get syscall optimization.
277 * If it is not a bsd socket
278 * tstream_bsd_optimize_readv() just returns.
280 save_optimize
= tstream_bsd_optimize_readv(state
->caller
.stream
,
283 subreq
= tstream_readv_send(state
,
285 state
->caller
.stream
,
289 tstream_bsd_optimize_readv(state
->caller
.stream
,
292 if (tevent_req_nomem(subreq
, req
)) {
295 tevent_req_set_callback(subreq
, tstream_readv_pdu_readv_done
, req
);
298 static void tstream_readv_pdu_readv_done(struct tevent_req
*subreq
)
300 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
302 struct tstream_readv_pdu_state
*state
= tevent_req_data(req
,
303 struct tstream_readv_pdu_state
);
307 ret
= tstream_readv_recv(subreq
, &sys_errno
);
309 tevent_req_error(req
, sys_errno
);
313 state
->total_read
+= ret
;
315 /* ask the callback for a new vector we should fill */
316 tstream_readv_pdu_ask_for_next_vector(req
);
319 int tstream_readv_pdu_recv(struct tevent_req
*req
, int *perrno
)
321 struct tstream_readv_pdu_state
*state
= tevent_req_data(req
,
322 struct tstream_readv_pdu_state
);
325 ret
= tsocket_simple_int_recv(req
, perrno
);
327 ret
= state
->total_read
;
330 tevent_req_received(req
);
334 struct tstream_readv_pdu_queue_state
{
335 /* this structs are owned by the caller */
337 struct tevent_context
*ev
;
338 struct tstream_context
*stream
;
339 tstream_readv_pdu_next_vector_t next_vector_fn
;
340 void *next_vector_private
;
345 static void tstream_readv_pdu_queue_trigger(struct tevent_req
*req
,
347 static void tstream_readv_pdu_queue_done(struct tevent_req
*subreq
);
349 struct tevent_req
*tstream_readv_pdu_queue_send(TALLOC_CTX
*mem_ctx
,
350 struct tevent_context
*ev
,
351 struct tstream_context
*stream
,
352 struct tevent_queue
*queue
,
353 tstream_readv_pdu_next_vector_t next_vector_fn
,
354 void *next_vector_private
)
356 struct tevent_req
*req
;
357 struct tstream_readv_pdu_queue_state
*state
;
360 req
= tevent_req_create(mem_ctx
, &state
,
361 struct tstream_readv_pdu_queue_state
);
366 state
->caller
.ev
= ev
;
367 state
->caller
.stream
= stream
;
368 state
->caller
.next_vector_fn
= next_vector_fn
;
369 state
->caller
.next_vector_private
= next_vector_private
;
372 ok
= tevent_queue_add(queue
,
375 tstream_readv_pdu_queue_trigger
,
378 tevent_req_nomem(NULL
, req
);
385 return tevent_req_post(req
, ev
);
388 static void tstream_readv_pdu_queue_trigger(struct tevent_req
*req
,
391 struct tstream_readv_pdu_queue_state
*state
= tevent_req_data(req
,
392 struct tstream_readv_pdu_queue_state
);
393 struct tevent_req
*subreq
;
395 subreq
= tstream_readv_pdu_send(state
,
397 state
->caller
.stream
,
398 state
->caller
.next_vector_fn
,
399 state
->caller
.next_vector_private
);
400 if (tevent_req_nomem(subreq
, req
)) {
403 tevent_req_set_callback(subreq
, tstream_readv_pdu_queue_done
,req
);
406 static void tstream_readv_pdu_queue_done(struct tevent_req
*subreq
)
408 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
410 struct tstream_readv_pdu_queue_state
*state
= tevent_req_data(req
,
411 struct tstream_readv_pdu_queue_state
);
415 ret
= tstream_readv_pdu_recv(subreq
, &sys_errno
);
418 tevent_req_error(req
, sys_errno
);
423 tevent_req_done(req
);
426 int tstream_readv_pdu_queue_recv(struct tevent_req
*req
, int *perrno
)
428 struct tstream_readv_pdu_queue_state
*state
= tevent_req_data(req
,
429 struct tstream_readv_pdu_queue_state
);
432 ret
= tsocket_simple_int_recv(req
, perrno
);
437 tevent_req_received(req
);
441 struct tstream_writev_queue_state
{
442 /* this structs are owned by the caller */
444 struct tevent_context
*ev
;
445 struct tstream_context
*stream
;
446 const struct iovec
*vector
;
452 static void tstream_writev_queue_trigger(struct tevent_req
*req
,
454 static void tstream_writev_queue_done(struct tevent_req
*subreq
);
456 struct tevent_req
*tstream_writev_queue_send(TALLOC_CTX
*mem_ctx
,
457 struct tevent_context
*ev
,
458 struct tstream_context
*stream
,
459 struct tevent_queue
*queue
,
460 const struct iovec
*vector
,
463 struct tevent_req
*req
;
464 struct tstream_writev_queue_state
*state
;
467 req
= tevent_req_create(mem_ctx
, &state
,
468 struct tstream_writev_queue_state
);
473 state
->caller
.ev
= ev
;
474 state
->caller
.stream
= stream
;
475 state
->caller
.vector
= vector
;
476 state
->caller
.count
= count
;
479 ok
= tevent_queue_add(queue
,
482 tstream_writev_queue_trigger
,
485 tevent_req_nomem(NULL
, req
);
492 return tevent_req_post(req
, ev
);
495 static void tstream_writev_queue_trigger(struct tevent_req
*req
,
498 struct tstream_writev_queue_state
*state
= tevent_req_data(req
,
499 struct tstream_writev_queue_state
);
500 struct tevent_req
*subreq
;
502 subreq
= tstream_writev_send(state
,
504 state
->caller
.stream
,
505 state
->caller
.vector
,
506 state
->caller
.count
);
507 if (tevent_req_nomem(subreq
, req
)) {
510 tevent_req_set_callback(subreq
, tstream_writev_queue_done
,req
);
513 static void tstream_writev_queue_done(struct tevent_req
*subreq
)
515 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
517 struct tstream_writev_queue_state
*state
= tevent_req_data(req
,
518 struct tstream_writev_queue_state
);
522 ret
= tstream_writev_recv(subreq
, &sys_errno
);
525 tevent_req_error(req
, sys_errno
);
530 tevent_req_done(req
);
533 int tstream_writev_queue_recv(struct tevent_req
*req
, int *perrno
)
535 struct tstream_writev_queue_state
*state
= tevent_req_data(req
,
536 struct tstream_writev_queue_state
);
539 ret
= tsocket_simple_int_recv(req
, perrno
);
544 tevent_req_received(req
);