Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Copyright (C) Stefan Metzmacher 2009
5 :
6 : ** NOTE! The following LGPL license applies to the tsocket
7 : ** library. This does NOT imply that all of Samba is released
8 : ** under the LGPL
9 :
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.
14 :
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.
19 :
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/>.
22 : */
23 :
24 : #include "replace.h"
25 : #include "system/filesys.h"
26 : #include "tsocket.h"
27 : #include "tsocket_internal.h"
28 :
29 60116010 : int tsocket_simple_int_recv(struct tevent_req *req, int *perrno)
30 : {
31 370285 : enum tevent_req_state state;
32 370285 : uint64_t error;
33 :
34 60116010 : if (!tevent_req_is_error(req, &state, &error)) {
35 59087990 : return 0;
36 : }
37 :
38 667569 : switch (state) {
39 6 : case TEVENT_REQ_NO_MEMORY:
40 6 : *perrno = ENOMEM;
41 6 : return -1;
42 2 : case TEVENT_REQ_TIMED_OUT:
43 2 : *perrno = ETIMEDOUT;
44 2 : return -1;
45 667561 : case TEVENT_REQ_USER_ERROR:
46 667561 : *perrno = (int)error;
47 667561 : return -1;
48 0 : default:
49 0 : break;
50 : }
51 :
52 0 : *perrno = EIO;
53 0 : return -1;
54 : }
55 :
56 1132607 : struct tsocket_address *_tsocket_address_create(TALLOC_CTX *mem_ctx,
57 : const struct tsocket_address_ops *ops,
58 : void *pstate,
59 : size_t psize,
60 : const char *type,
61 : const char *location)
62 : {
63 1132607 : void **ppstate = (void **)pstate;
64 23346 : struct tsocket_address *addr;
65 :
66 1132607 : addr = talloc_zero(mem_ctx, struct tsocket_address);
67 1132607 : if (!addr) {
68 0 : return NULL;
69 : }
70 1132607 : addr->ops = ops;
71 1132607 : addr->location = location;
72 1132607 : addr->private_data = talloc_size(addr, psize);
73 1132607 : if (!addr->private_data) {
74 0 : talloc_free(addr);
75 0 : return NULL;
76 : }
77 1132607 : talloc_set_name_const(addr->private_data, type);
78 :
79 1132607 : *ppstate = addr->private_data;
80 1132607 : return addr;
81 : }
82 :
83 891051 : char *tsocket_address_string(const struct tsocket_address *addr,
84 : TALLOC_CTX *mem_ctx)
85 : {
86 891051 : if (!addr) {
87 0 : return talloc_strdup(mem_ctx, "NULL");
88 : }
89 891051 : return addr->ops->string(addr, mem_ctx);
90 : }
91 :
92 387137 : struct tsocket_address *_tsocket_address_copy(const struct tsocket_address *addr,
93 : TALLOC_CTX *mem_ctx,
94 : const char *location)
95 : {
96 387137 : return addr->ops->copy(addr, mem_ctx, location);
97 : }
98 :
99 : struct tdgram_context {
100 : const char *location;
101 : const struct tdgram_context_ops *ops;
102 : void *private_data;
103 :
104 : struct tevent_req *recvfrom_req;
105 : struct tevent_req *sendto_req;
106 : };
107 :
108 6711 : static int tdgram_context_destructor(struct tdgram_context *dgram)
109 : {
110 6711 : if (dgram->recvfrom_req) {
111 0 : tevent_req_received(dgram->recvfrom_req);
112 : }
113 :
114 6711 : if (dgram->sendto_req) {
115 0 : tevent_req_received(dgram->sendto_req);
116 : }
117 :
118 6711 : return 0;
119 : }
120 :
121 6168 : struct tdgram_context *_tdgram_context_create(TALLOC_CTX *mem_ctx,
122 : const struct tdgram_context_ops *ops,
123 : void *pstate,
124 : size_t psize,
125 : const char *type,
126 : const char *location)
127 : {
128 68 : struct tdgram_context *dgram;
129 6168 : void **ppstate = (void **)pstate;
130 68 : void *state;
131 :
132 6168 : dgram = talloc(mem_ctx, struct tdgram_context);
133 6168 : if (dgram == NULL) {
134 0 : return NULL;
135 : }
136 6168 : dgram->location = location;
137 6168 : dgram->ops = ops;
138 6168 : dgram->recvfrom_req = NULL;
139 6168 : dgram->sendto_req = NULL;
140 :
141 6168 : state = talloc_size(dgram, psize);
142 6168 : if (state == NULL) {
143 0 : talloc_free(dgram);
144 0 : return NULL;
145 : }
146 6168 : talloc_set_name_const(state, type);
147 :
148 6168 : dgram->private_data = state;
149 :
150 6168 : talloc_set_destructor(dgram, tdgram_context_destructor);
151 :
152 6168 : *ppstate = state;
153 6168 : return dgram;
154 : }
155 :
156 235614 : void *_tdgram_context_data(struct tdgram_context *dgram)
157 : {
158 235614 : return dgram->private_data;
159 : }
160 :
161 : struct tdgram_recvfrom_state {
162 : const struct tdgram_context_ops *ops;
163 : struct tdgram_context *dgram;
164 : uint8_t *buf;
165 : size_t len;
166 : struct tsocket_address *src;
167 : };
168 :
169 39043 : static int tdgram_recvfrom_destructor(struct tdgram_recvfrom_state *state)
170 : {
171 39043 : if (state->dgram) {
172 39043 : state->dgram->recvfrom_req = NULL;
173 : }
174 :
175 39043 : return 0;
176 : }
177 :
178 : static void tdgram_recvfrom_done(struct tevent_req *subreq);
179 :
180 38500 : struct tevent_req *tdgram_recvfrom_send(TALLOC_CTX *mem_ctx,
181 : struct tevent_context *ev,
182 : struct tdgram_context *dgram)
183 : {
184 1274 : struct tevent_req *req;
185 1274 : struct tdgram_recvfrom_state *state;
186 1274 : struct tevent_req *subreq;
187 :
188 38500 : req = tevent_req_create(mem_ctx, &state,
189 : struct tdgram_recvfrom_state);
190 38500 : if (req == NULL) {
191 0 : return NULL;
192 : }
193 :
194 38500 : state->ops = dgram->ops;
195 38500 : state->dgram = dgram;
196 38500 : state->buf = NULL;
197 38500 : state->len = 0;
198 38500 : state->src = NULL;
199 :
200 38500 : if (dgram->recvfrom_req) {
201 0 : tevent_req_error(req, EBUSY);
202 0 : goto post;
203 : }
204 38500 : dgram->recvfrom_req = req;
205 :
206 38500 : talloc_set_destructor(state, tdgram_recvfrom_destructor);
207 :
208 38500 : subreq = state->ops->recvfrom_send(state, ev, dgram);
209 38500 : if (tevent_req_nomem(subreq, req)) {
210 0 : goto post;
211 : }
212 38500 : tevent_req_set_callback(subreq, tdgram_recvfrom_done, req);
213 :
214 38500 : return req;
215 :
216 0 : post:
217 0 : tevent_req_post(req, ev);
218 0 : return req;
219 : }
220 :
221 37086 : static void tdgram_recvfrom_done(struct tevent_req *subreq)
222 : {
223 37086 : struct tevent_req *req = tevent_req_callback_data(subreq,
224 : struct tevent_req);
225 37086 : struct tdgram_recvfrom_state *state = tevent_req_data(req,
226 : struct tdgram_recvfrom_state);
227 1242 : ssize_t ret;
228 1242 : int sys_errno;
229 :
230 37086 : ret = state->ops->recvfrom_recv(subreq, &sys_errno, state,
231 : &state->buf, &state->src);
232 37086 : if (ret == -1) {
233 6 : tevent_req_error(req, sys_errno);
234 6 : return;
235 : }
236 :
237 37080 : state->len = ret;
238 :
239 37080 : tevent_req_done(req);
240 : }
241 :
242 37086 : ssize_t tdgram_recvfrom_recv(struct tevent_req *req,
243 : int *perrno,
244 : TALLOC_CTX *mem_ctx,
245 : uint8_t **buf,
246 : struct tsocket_address **src)
247 : {
248 37086 : struct tdgram_recvfrom_state *state = tevent_req_data(req,
249 : struct tdgram_recvfrom_state);
250 1242 : ssize_t ret;
251 :
252 37086 : ret = tsocket_simple_int_recv(req, perrno);
253 37086 : if (ret == 0) {
254 37080 : *buf = talloc_move(mem_ctx, &state->buf);
255 37080 : ret = state->len;
256 37080 : if (src) {
257 34705 : *src = talloc_move(mem_ctx, &state->src);
258 : }
259 : }
260 :
261 37086 : tevent_req_received(req);
262 37086 : return ret;
263 : }
264 :
265 : struct tdgram_sendto_state {
266 : const struct tdgram_context_ops *ops;
267 : struct tdgram_context *dgram;
268 : ssize_t ret;
269 : };
270 :
271 37509 : static int tdgram_sendto_destructor(struct tdgram_sendto_state *state)
272 : {
273 37509 : if (state->dgram) {
274 37509 : state->dgram->sendto_req = NULL;
275 : }
276 :
277 37509 : return 0;
278 : }
279 :
280 : static void tdgram_sendto_done(struct tevent_req *subreq);
281 :
282 37509 : struct tevent_req *tdgram_sendto_send(TALLOC_CTX *mem_ctx,
283 : struct tevent_context *ev,
284 : struct tdgram_context *dgram,
285 : const uint8_t *buf, size_t len,
286 : const struct tsocket_address *dst)
287 : {
288 1242 : struct tevent_req *req;
289 1242 : struct tdgram_sendto_state *state;
290 1242 : struct tevent_req *subreq;
291 :
292 37509 : req = tevent_req_create(mem_ctx, &state,
293 : struct tdgram_sendto_state);
294 37509 : if (req == NULL) {
295 0 : return NULL;
296 : }
297 :
298 37509 : state->ops = dgram->ops;
299 37509 : state->dgram = dgram;
300 37509 : state->ret = -1;
301 :
302 37509 : if (len == 0) {
303 0 : tevent_req_error(req, EINVAL);
304 0 : goto post;
305 : }
306 :
307 37509 : if (dgram->sendto_req) {
308 0 : tevent_req_error(req, EBUSY);
309 0 : goto post;
310 : }
311 37509 : dgram->sendto_req = req;
312 :
313 37509 : talloc_set_destructor(state, tdgram_sendto_destructor);
314 :
315 37509 : subreq = state->ops->sendto_send(state, ev, dgram,
316 : buf, len, dst);
317 37509 : if (tevent_req_nomem(subreq, req)) {
318 0 : goto post;
319 : }
320 37509 : tevent_req_set_callback(subreq, tdgram_sendto_done, req);
321 :
322 37509 : return req;
323 :
324 0 : post:
325 0 : tevent_req_post(req, ev);
326 0 : return req;
327 : }
328 :
329 37509 : static void tdgram_sendto_done(struct tevent_req *subreq)
330 : {
331 37509 : struct tevent_req *req = tevent_req_callback_data(subreq,
332 : struct tevent_req);
333 37509 : struct tdgram_sendto_state *state = tevent_req_data(req,
334 : struct tdgram_sendto_state);
335 1242 : ssize_t ret;
336 1242 : int sys_errno;
337 :
338 37509 : ret = state->ops->sendto_recv(subreq, &sys_errno);
339 37509 : if (ret == -1) {
340 53 : tevent_req_error(req, sys_errno);
341 53 : return;
342 : }
343 :
344 37456 : state->ret = ret;
345 :
346 37456 : tevent_req_done(req);
347 : }
348 :
349 37509 : ssize_t tdgram_sendto_recv(struct tevent_req *req,
350 : int *perrno)
351 : {
352 37509 : struct tdgram_sendto_state *state = tevent_req_data(req,
353 : struct tdgram_sendto_state);
354 1242 : ssize_t ret;
355 :
356 37509 : ret = tsocket_simple_int_recv(req, perrno);
357 37509 : if (ret == 0) {
358 37456 : ret = state->ret;
359 : }
360 :
361 37509 : tevent_req_received(req);
362 37509 : return ret;
363 : }
364 :
365 : struct tdgram_disconnect_state {
366 : const struct tdgram_context_ops *ops;
367 : };
368 :
369 : static void tdgram_disconnect_done(struct tevent_req *subreq);
370 :
371 0 : struct tevent_req *tdgram_disconnect_send(TALLOC_CTX *mem_ctx,
372 : struct tevent_context *ev,
373 : struct tdgram_context *dgram)
374 : {
375 0 : struct tevent_req *req;
376 0 : struct tdgram_disconnect_state *state;
377 0 : struct tevent_req *subreq;
378 :
379 0 : req = tevent_req_create(mem_ctx, &state,
380 : struct tdgram_disconnect_state);
381 0 : if (req == NULL) {
382 0 : return NULL;
383 : }
384 :
385 0 : state->ops = dgram->ops;
386 :
387 0 : if (dgram->recvfrom_req || dgram->sendto_req) {
388 0 : tevent_req_error(req, EBUSY);
389 0 : goto post;
390 : }
391 :
392 0 : subreq = state->ops->disconnect_send(state, ev, dgram);
393 0 : if (tevent_req_nomem(subreq, req)) {
394 0 : goto post;
395 : }
396 0 : tevent_req_set_callback(subreq, tdgram_disconnect_done, req);
397 :
398 0 : return req;
399 :
400 0 : post:
401 0 : tevent_req_post(req, ev);
402 0 : return req;
403 : }
404 :
405 0 : static void tdgram_disconnect_done(struct tevent_req *subreq)
406 : {
407 0 : struct tevent_req *req = tevent_req_callback_data(subreq,
408 : struct tevent_req);
409 0 : struct tdgram_disconnect_state *state = tevent_req_data(req,
410 : struct tdgram_disconnect_state);
411 0 : int ret;
412 0 : int sys_errno;
413 :
414 0 : ret = state->ops->disconnect_recv(subreq, &sys_errno);
415 0 : if (ret == -1) {
416 0 : tevent_req_error(req, sys_errno);
417 0 : return;
418 : }
419 :
420 0 : tevent_req_done(req);
421 : }
422 :
423 0 : int tdgram_disconnect_recv(struct tevent_req *req,
424 : int *perrno)
425 : {
426 0 : int ret;
427 :
428 0 : ret = tsocket_simple_int_recv(req, perrno);
429 :
430 0 : tevent_req_received(req);
431 0 : return ret;
432 : }
433 :
434 : struct tstream_context {
435 : const char *location;
436 : const struct tstream_context_ops *ops;
437 : void *private_data;
438 :
439 : struct tevent_req *readv_req;
440 : struct tevent_req *writev_req;
441 : };
442 :
443 510568 : static int tstream_context_destructor(struct tstream_context *stream)
444 : {
445 510568 : if (stream->readv_req) {
446 0 : tevent_req_received(stream->readv_req);
447 : }
448 :
449 510568 : if (stream->writev_req) {
450 66 : tevent_req_received(stream->writev_req);
451 : }
452 :
453 510568 : return 0;
454 : }
455 :
456 508409 : struct tstream_context *_tstream_context_create(TALLOC_CTX *mem_ctx,
457 : const struct tstream_context_ops *ops,
458 : void *pstate,
459 : size_t psize,
460 : const char *type,
461 : const char *location)
462 : {
463 6354 : struct tstream_context *stream;
464 508409 : void **ppstate = (void **)pstate;
465 6354 : void *state;
466 :
467 508409 : stream = talloc(mem_ctx, struct tstream_context);
468 508409 : if (stream == NULL) {
469 0 : return NULL;
470 : }
471 508409 : stream->location = location;
472 508409 : stream->ops = ops;
473 508409 : stream->readv_req = NULL;
474 508409 : stream->writev_req = NULL;
475 :
476 508409 : state = talloc_size(stream, psize);
477 508409 : if (state == NULL) {
478 0 : talloc_free(stream);
479 0 : return NULL;
480 : }
481 508409 : talloc_set_name_const(state, type);
482 :
483 508409 : stream->private_data = state;
484 :
485 508409 : talloc_set_destructor(stream, tstream_context_destructor);
486 :
487 508409 : *ppstate = state;
488 508409 : return stream;
489 : }
490 :
491 109395591 : void *_tstream_context_data(struct tstream_context *stream)
492 : {
493 109395591 : return stream->private_data;
494 : }
495 :
496 1438541 : ssize_t tstream_pending_bytes(struct tstream_context *stream)
497 : {
498 1438541 : return stream->ops->pending_bytes(stream);
499 : }
500 :
501 : struct tstream_readv_state {
502 : const struct tstream_context_ops *ops;
503 : struct tstream_context *stream;
504 : int ret;
505 : };
506 :
507 17443710 : static int tstream_readv_destructor(struct tstream_readv_state *state)
508 : {
509 17443710 : if (state->stream) {
510 17443710 : state->stream->readv_req = NULL;
511 : }
512 :
513 17443710 : return 0;
514 : }
515 :
516 : static void tstream_readv_done(struct tevent_req *subreq);
517 :
518 17441297 : struct tevent_req *tstream_readv_send(TALLOC_CTX *mem_ctx,
519 : struct tevent_context *ev,
520 : struct tstream_context *stream,
521 : struct iovec *vector,
522 : size_t count)
523 : {
524 96128 : struct tevent_req *req;
525 96128 : struct tstream_readv_state *state;
526 96128 : struct tevent_req *subreq;
527 17441297 : int to_read = 0;
528 96128 : size_t i;
529 :
530 17441297 : req = tevent_req_create(mem_ctx, &state,
531 : struct tstream_readv_state);
532 17441297 : if (req == NULL) {
533 0 : return NULL;
534 : }
535 :
536 17441297 : state->ops = stream->ops;
537 17441297 : state->stream = stream;
538 17441297 : state->ret = -1;
539 :
540 : /* first check if the input is ok */
541 : #ifdef IOV_MAX
542 17441297 : if (count > IOV_MAX) {
543 0 : tevent_req_error(req, EMSGSIZE);
544 0 : goto post;
545 : }
546 : #endif
547 :
548 36567221 : for (i=0; i < count; i++) {
549 19125924 : int tmp = to_read;
550 19125924 : tmp += vector[i].iov_len;
551 :
552 19125924 : if (tmp < to_read) {
553 0 : tevent_req_error(req, EMSGSIZE);
554 0 : goto post;
555 : }
556 :
557 19125924 : to_read = tmp;
558 : }
559 :
560 17441297 : if (to_read == 0) {
561 0 : tevent_req_error(req, EINVAL);
562 0 : goto post;
563 : }
564 :
565 17441297 : if (stream->readv_req) {
566 0 : tevent_req_error(req, EBUSY);
567 0 : goto post;
568 : }
569 17441297 : stream->readv_req = req;
570 :
571 17441297 : talloc_set_destructor(state, tstream_readv_destructor);
572 :
573 17441297 : subreq = state->ops->readv_send(state, ev, stream, vector, count);
574 17441297 : if (tevent_req_nomem(subreq, req)) {
575 0 : goto post;
576 : }
577 17441297 : tevent_req_set_callback(subreq, tstream_readv_done, req);
578 :
579 17441297 : return req;
580 :
581 0 : post:
582 0 : tevent_req_post(req, ev);
583 0 : return req;
584 : }
585 :
586 17440496 : static void tstream_readv_done(struct tevent_req *subreq)
587 : {
588 17440496 : struct tevent_req *req = tevent_req_callback_data(subreq,
589 : struct tevent_req);
590 17440496 : struct tstream_readv_state *state = tevent_req_data(req,
591 : struct tstream_readv_state);
592 96103 : ssize_t ret;
593 96103 : int sys_errno;
594 :
595 17440496 : ret = state->ops->readv_recv(subreq, &sys_errno);
596 17440496 : TALLOC_FREE(subreq);
597 17440496 : if (ret == -1) {
598 239424 : tevent_req_error(req, sys_errno);
599 238956 : return;
600 : }
601 :
602 17201072 : state->ret = ret;
603 :
604 17201072 : tevent_req_done(req);
605 : }
606 :
607 17440496 : int tstream_readv_recv(struct tevent_req *req,
608 : int *perrno)
609 : {
610 17440496 : struct tstream_readv_state *state = tevent_req_data(req,
611 : struct tstream_readv_state);
612 96103 : int ret;
613 :
614 17440496 : ret = tsocket_simple_int_recv(req, perrno);
615 17440496 : if (ret == 0) {
616 17201072 : ret = state->ret;
617 : }
618 :
619 17440496 : tevent_req_received(req);
620 17440496 : return ret;
621 : }
622 :
623 : struct tstream_writev_state {
624 : const struct tstream_context_ops *ops;
625 : struct tstream_context *stream;
626 : int ret;
627 : };
628 :
629 6718732 : static int tstream_writev_destructor(struct tstream_writev_state *state)
630 : {
631 6718732 : if (state->stream) {
632 6718732 : state->stream->writev_req = NULL;
633 : }
634 :
635 6718732 : return 0;
636 : }
637 :
638 : static void tstream_writev_done(struct tevent_req *subreq);
639 :
640 6718732 : struct tevent_req *tstream_writev_send(TALLOC_CTX *mem_ctx,
641 : struct tevent_context *ev,
642 : struct tstream_context *stream,
643 : const struct iovec *vector,
644 : size_t count)
645 : {
646 45666 : struct tevent_req *req;
647 45666 : struct tstream_writev_state *state;
648 45666 : struct tevent_req *subreq;
649 6718732 : int to_write = 0;
650 45666 : size_t i;
651 :
652 6718732 : req = tevent_req_create(mem_ctx, &state,
653 : struct tstream_writev_state);
654 6718732 : if (req == NULL) {
655 0 : return NULL;
656 : }
657 :
658 6718732 : state->ops = stream->ops;
659 6718732 : state->stream = stream;
660 6718732 : state->ret = -1;
661 :
662 : /* first check if the input is ok */
663 : #ifdef IOV_MAX
664 6718732 : if (count > IOV_MAX) {
665 0 : tevent_req_error(req, EMSGSIZE);
666 0 : goto post;
667 : }
668 : #endif
669 :
670 17054948 : for (i=0; i < count; i++) {
671 10336216 : int tmp = to_write;
672 10336216 : tmp += vector[i].iov_len;
673 :
674 10336216 : if (tmp < to_write) {
675 0 : tevent_req_error(req, EMSGSIZE);
676 0 : goto post;
677 : }
678 :
679 10336216 : to_write = tmp;
680 : }
681 :
682 6718732 : if (to_write == 0) {
683 0 : tevent_req_error(req, EINVAL);
684 0 : goto post;
685 : }
686 :
687 6718732 : if (stream->writev_req) {
688 0 : tevent_req_error(req, EBUSY);
689 0 : goto post;
690 : }
691 6718732 : stream->writev_req = req;
692 :
693 6718732 : talloc_set_destructor(state, tstream_writev_destructor);
694 :
695 6718732 : subreq = state->ops->writev_send(state, ev, stream, vector, count);
696 6718732 : if (tevent_req_nomem(subreq, req)) {
697 0 : goto post;
698 : }
699 6718732 : tevent_req_set_callback(subreq, tstream_writev_done, req);
700 :
701 6718732 : return req;
702 :
703 0 : post:
704 0 : tevent_req_post(req, ev);
705 0 : return req;
706 : }
707 :
708 6718635 : static void tstream_writev_done(struct tevent_req *subreq)
709 : {
710 6718635 : struct tevent_req *req = tevent_req_callback_data(subreq,
711 : struct tevent_req);
712 6718635 : struct tstream_writev_state *state = tevent_req_data(req,
713 : struct tstream_writev_state);
714 45664 : ssize_t ret;
715 45664 : int sys_errno;
716 :
717 6718635 : ret = state->ops->writev_recv(subreq, &sys_errno);
718 6718635 : if (ret == -1) {
719 36 : tevent_req_error(req, sys_errno);
720 36 : return;
721 : }
722 :
723 6718599 : state->ret = ret;
724 :
725 6718599 : tevent_req_done(req);
726 : }
727 :
728 6718637 : int tstream_writev_recv(struct tevent_req *req,
729 : int *perrno)
730 : {
731 6718637 : struct tstream_writev_state *state = tevent_req_data(req,
732 : struct tstream_writev_state);
733 45666 : int ret;
734 :
735 6718637 : ret = tsocket_simple_int_recv(req, perrno);
736 6718637 : if (ret == 0) {
737 6718599 : ret = state->ret;
738 : }
739 :
740 6718637 : tevent_req_received(req);
741 6718637 : return ret;
742 : }
743 :
744 : struct tstream_disconnect_state {
745 : const struct tstream_context_ops *ops;
746 : };
747 :
748 : static void tstream_disconnect_done(struct tevent_req *subreq);
749 :
750 73596 : struct tevent_req *tstream_disconnect_send(TALLOC_CTX *mem_ctx,
751 : struct tevent_context *ev,
752 : struct tstream_context *stream)
753 : {
754 1111 : struct tevent_req *req;
755 1111 : struct tstream_disconnect_state *state;
756 1111 : struct tevent_req *subreq;
757 :
758 73596 : req = tevent_req_create(mem_ctx, &state,
759 : struct tstream_disconnect_state);
760 73596 : if (req == NULL) {
761 0 : return NULL;
762 : }
763 :
764 73596 : state->ops = stream->ops;
765 :
766 73596 : if (stream->readv_req || stream->writev_req) {
767 20 : tevent_req_error(req, EBUSY);
768 20 : goto post;
769 : }
770 :
771 73576 : subreq = state->ops->disconnect_send(state, ev, stream);
772 73576 : if (tevent_req_nomem(subreq, req)) {
773 0 : goto post;
774 : }
775 73576 : tevent_req_set_callback(subreq, tstream_disconnect_done, req);
776 :
777 73576 : return req;
778 :
779 20 : post:
780 20 : tevent_req_post(req, ev);
781 20 : return req;
782 : }
783 :
784 53547 : static void tstream_disconnect_done(struct tevent_req *subreq)
785 : {
786 53547 : struct tevent_req *req = tevent_req_callback_data(subreq,
787 : struct tevent_req);
788 53547 : struct tstream_disconnect_state *state = tevent_req_data(req,
789 : struct tstream_disconnect_state);
790 244 : int ret;
791 244 : int sys_errno;
792 :
793 53547 : ret = state->ops->disconnect_recv(subreq, &sys_errno);
794 53547 : if (ret == -1) {
795 26057 : tevent_req_error(req, sys_errno);
796 26057 : return;
797 : }
798 :
799 27490 : tevent_req_done(req);
800 : }
801 :
802 53547 : int tstream_disconnect_recv(struct tevent_req *req,
803 : int *perrno)
804 : {
805 244 : int ret;
806 :
807 53547 : ret = tsocket_simple_int_recv(req, perrno);
808 :
809 53547 : tevent_req_received(req);
810 53547 : return ret;
811 : }
812 :
|