2 Unix SMB/CIFS implementation.
4 Copyright (C) Stefan Metzmacher 2010
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "system/network.h"
22 #include "../util/tevent_unix.h"
23 #include "../lib/tsocket/tsocket.h"
24 #include "../lib/tsocket/tsocket_internal.h"
25 #include "cli_np_tstream.h"
27 static const struct tstream_context_ops tstream_cli_np_ops
;
30 * Window uses 1024 hardcoded for read size and trans max data
32 #define TSTREAM_CLI_NP_BUF_SIZE 1024
34 struct tstream_cli_np
{
35 struct cli_state
*cli
;
38 unsigned int default_timeout
;
42 struct tevent_req
*read_req
;
43 struct tevent_req
*write_req
;
50 uint8_t buf
[TSTREAM_CLI_NP_BUF_SIZE
];
54 static int tstream_cli_np_destructor(struct tstream_cli_np
*cli_nps
)
58 if (!cli_state_is_connected(cli_nps
->cli
)) {
63 * TODO: do not use a sync call with a destructor!!!
65 * This only happens, if a caller does talloc_free(),
66 * while the everything was still ok.
68 * If we get an unexpected failure within a normal
69 * operation, we already do an async cli_close_send()/_recv().
71 * Once we've fixed all callers to call
72 * tstream_disconnect_send()/_recv(), this will
75 status
= cli_close(cli_nps
->cli
, cli_nps
->fnum
);
76 if (!NT_STATUS_IS_OK(status
)) {
77 DEBUG(1, ("tstream_cli_np_destructor: cli_close "
78 "failed on pipe %s. Error was %s\n",
79 cli_nps
->npipe
, nt_errstr(status
)));
82 * We can't do much on failure
87 struct tstream_cli_np_open_state
{
88 struct cli_state
*cli
;
93 static void tstream_cli_np_open_done(struct tevent_req
*subreq
);
95 struct tevent_req
*tstream_cli_np_open_send(TALLOC_CTX
*mem_ctx
,
96 struct tevent_context
*ev
,
97 struct cli_state
*cli
,
100 struct tevent_req
*req
;
101 struct tstream_cli_np_open_state
*state
;
102 struct tevent_req
*subreq
;
104 req
= tevent_req_create(mem_ctx
, &state
,
105 struct tstream_cli_np_open_state
);
111 state
->npipe
= talloc_strdup(state
, npipe
);
112 if (tevent_req_nomem(state
->npipe
, req
)) {
113 return tevent_req_post(req
, ev
);
116 subreq
= cli_ntcreate_send(state
, ev
, cli
,
121 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
125 if (tevent_req_nomem(subreq
, req
)) {
126 return tevent_req_post(req
, ev
);
128 tevent_req_set_callback(subreq
, tstream_cli_np_open_done
, req
);
133 static void tstream_cli_np_open_done(struct tevent_req
*subreq
)
135 struct tevent_req
*req
=
136 tevent_req_callback_data(subreq
, struct tevent_req
);
137 struct tstream_cli_np_open_state
*state
=
138 tevent_req_data(req
, struct tstream_cli_np_open_state
);
141 status
= cli_ntcreate_recv(subreq
, &state
->fnum
);
143 if (!NT_STATUS_IS_OK(status
)) {
144 tevent_req_nterror(req
, status
);
148 tevent_req_done(req
);
151 NTSTATUS
_tstream_cli_np_open_recv(struct tevent_req
*req
,
153 struct tstream_context
**_stream
,
154 const char *location
)
156 struct tstream_cli_np_open_state
*state
=
157 tevent_req_data(req
, struct tstream_cli_np_open_state
);
158 struct tstream_context
*stream
;
159 struct tstream_cli_np
*cli_nps
;
162 if (tevent_req_is_nterror(req
, &status
)) {
163 tevent_req_received(req
);
167 stream
= tstream_context_create(mem_ctx
,
170 struct tstream_cli_np
,
173 tevent_req_received(req
);
174 return NT_STATUS_NO_MEMORY
;
176 ZERO_STRUCTP(cli_nps
);
178 cli_nps
->cli
= state
->cli
;
179 cli_nps
->npipe
= talloc_move(cli_nps
, &state
->npipe
);
180 cli_nps
->fnum
= state
->fnum
;
181 cli_nps
->default_timeout
= state
->cli
->timeout
;
183 talloc_set_destructor(cli_nps
, tstream_cli_np_destructor
);
185 cli_nps
->trans
.active
= false;
186 cli_nps
->trans
.read_req
= NULL
;
187 cli_nps
->trans
.write_req
= NULL
;
188 SSVAL(cli_nps
->trans
.setup
+0, 0, TRANSACT_DCERPCCMD
);
189 SSVAL(cli_nps
->trans
.setup
+1, 0, cli_nps
->fnum
);
192 tevent_req_received(req
);
196 static ssize_t
tstream_cli_np_pending_bytes(struct tstream_context
*stream
)
198 struct tstream_cli_np
*cli_nps
= tstream_context_data(stream
,
199 struct tstream_cli_np
);
201 if (!cli_state_is_connected(cli_nps
->cli
)) {
206 return cli_nps
->read
.left
;
209 bool tstream_is_cli_np(struct tstream_context
*stream
)
211 struct tstream_cli_np
*cli_nps
=
212 talloc_get_type(_tstream_context_data(stream
),
213 struct tstream_cli_np
);
222 NTSTATUS
tstream_cli_np_use_trans(struct tstream_context
*stream
)
224 struct tstream_cli_np
*cli_nps
= tstream_context_data(stream
,
225 struct tstream_cli_np
);
227 if (cli_nps
->trans
.read_req
) {
228 return NT_STATUS_PIPE_BUSY
;
231 if (cli_nps
->trans
.write_req
) {
232 return NT_STATUS_PIPE_BUSY
;
235 if (cli_nps
->trans
.active
) {
236 return NT_STATUS_PIPE_BUSY
;
239 cli_nps
->trans
.active
= true;
244 unsigned int tstream_cli_np_set_timeout(struct tstream_context
*stream
,
245 unsigned int timeout
)
247 struct tstream_cli_np
*cli_nps
= tstream_context_data(stream
,
248 struct tstream_cli_np
);
250 if (!cli_state_is_connected(cli_nps
->cli
)) {
251 return cli_nps
->default_timeout
;
254 return cli_set_timeout(cli_nps
->cli
, timeout
);
257 struct cli_state
*tstream_cli_np_get_cli_state(struct tstream_context
*stream
)
259 struct tstream_cli_np
*cli_nps
= tstream_context_data(stream
,
260 struct tstream_cli_np
);
265 struct tstream_cli_np_writev_state
{
266 struct tstream_context
*stream
;
267 struct tevent_context
*ev
;
269 struct iovec
*vector
;
276 const char *location
;
280 static int tstream_cli_np_writev_state_destructor(struct tstream_cli_np_writev_state
*state
)
282 struct tstream_cli_np
*cli_nps
=
283 tstream_context_data(state
->stream
,
284 struct tstream_cli_np
);
286 cli_nps
->trans
.write_req
= NULL
;
291 static void tstream_cli_np_writev_write_next(struct tevent_req
*req
);
293 static struct tevent_req
*tstream_cli_np_writev_send(TALLOC_CTX
*mem_ctx
,
294 struct tevent_context
*ev
,
295 struct tstream_context
*stream
,
296 const struct iovec
*vector
,
299 struct tevent_req
*req
;
300 struct tstream_cli_np_writev_state
*state
;
301 struct tstream_cli_np
*cli_nps
= tstream_context_data(stream
,
302 struct tstream_cli_np
);
304 req
= tevent_req_create(mem_ctx
, &state
,
305 struct tstream_cli_np_writev_state
);
309 state
->stream
= stream
;
313 talloc_set_destructor(state
, tstream_cli_np_writev_state_destructor
);
315 if (!cli_state_is_connected(cli_nps
->cli
)) {
316 tevent_req_error(req
, ENOTCONN
);
317 return tevent_req_post(req
, ev
);
321 * we make a copy of the vector so we can change the structure
323 state
->vector
= talloc_array(state
, struct iovec
, count
);
324 if (tevent_req_nomem(state
->vector
, req
)) {
325 return tevent_req_post(req
, ev
);
327 memcpy(state
->vector
, vector
, sizeof(struct iovec
) * count
);
328 state
->count
= count
;
330 tstream_cli_np_writev_write_next(req
);
331 if (!tevent_req_is_in_progress(req
)) {
332 return tevent_req_post(req
, ev
);
338 static void tstream_cli_np_readv_trans_start(struct tevent_req
*req
);
339 static void tstream_cli_np_writev_write_done(struct tevent_req
*subreq
);
341 static void tstream_cli_np_writev_write_next(struct tevent_req
*req
)
343 struct tstream_cli_np_writev_state
*state
=
345 struct tstream_cli_np_writev_state
);
346 struct tstream_cli_np
*cli_nps
=
347 tstream_context_data(state
->stream
,
348 struct tstream_cli_np
);
349 struct tevent_req
*subreq
;
351 cli_nps
->write
.ofs
= 0;
352 cli_nps
->write
.left
= TSTREAM_CLI_NP_BUF_SIZE
;
355 * copy the pending buffer first
357 while (cli_nps
->write
.left
> 0 && state
->count
> 0) {
358 uint8_t *base
= (uint8_t *)state
->vector
[0].iov_base
;
359 size_t len
= MIN(cli_nps
->write
.left
, state
->vector
[0].iov_len
);
361 memcpy(cli_nps
->write
.buf
+ cli_nps
->write
.ofs
, base
, len
);
364 state
->vector
[0].iov_base
= base
;
365 state
->vector
[0].iov_len
-= len
;
367 cli_nps
->write
.ofs
+= len
;
368 cli_nps
->write
.left
-= len
;
370 if (state
->vector
[0].iov_len
== 0) {
378 if (cli_nps
->write
.ofs
== 0) {
379 tevent_req_done(req
);
383 if (cli_nps
->trans
.active
&& state
->count
== 0) {
384 cli_nps
->trans
.active
= false;
385 cli_nps
->trans
.write_req
= req
;
389 if (cli_nps
->trans
.read_req
&& state
->count
== 0) {
390 cli_nps
->trans
.write_req
= req
;
391 tstream_cli_np_readv_trans_start(cli_nps
->trans
.read_req
);
395 subreq
= cli_write_andx_send(state
, state
->ev
, cli_nps
->cli
,
397 8, /* 8 means message mode. */
398 cli_nps
->write
.buf
, 0,
400 if (tevent_req_nomem(subreq
, req
)) {
403 tevent_req_set_callback(subreq
,
404 tstream_cli_np_writev_write_done
,
408 static void tstream_cli_np_writev_disconnect_now(struct tevent_req
*req
,
410 const char *location
);
412 static void tstream_cli_np_writev_write_done(struct tevent_req
*subreq
)
414 struct tevent_req
*req
=
415 tevent_req_callback_data(subreq
, struct tevent_req
);
416 struct tstream_cli_np_writev_state
*state
=
417 tevent_req_data(req
, struct tstream_cli_np_writev_state
);
418 struct tstream_cli_np
*cli_nps
=
419 tstream_context_data(state
->stream
,
420 struct tstream_cli_np
);
424 status
= cli_write_andx_recv(subreq
, &written
);
426 if (!NT_STATUS_IS_OK(status
)) {
427 tstream_cli_np_writev_disconnect_now(req
, EIO
, __location__
);
431 if (written
!= cli_nps
->write
.ofs
) {
432 tstream_cli_np_writev_disconnect_now(req
, EIO
, __location__
);
436 tstream_cli_np_writev_write_next(req
);
439 static void tstream_cli_np_writev_disconnect_done(struct tevent_req
*subreq
);
441 static void tstream_cli_np_writev_disconnect_now(struct tevent_req
*req
,
443 const char *location
)
445 struct tstream_cli_np_writev_state
*state
=
447 struct tstream_cli_np_writev_state
);
448 struct tstream_cli_np
*cli_nps
=
449 tstream_context_data(state
->stream
,
450 struct tstream_cli_np
);
451 struct tevent_req
*subreq
;
453 state
->error
.val
= error
;
454 state
->error
.location
= location
;
456 if (!cli_state_is_connected(cli_nps
->cli
)) {
457 /* return the original error */
458 _tevent_req_error(req
, state
->error
.val
, state
->error
.location
);
462 subreq
= cli_close_send(state
, state
->ev
, cli_nps
->cli
, cli_nps
->fnum
);
463 if (subreq
== NULL
) {
464 /* return the original error */
465 _tevent_req_error(req
, state
->error
.val
, state
->error
.location
);
468 tevent_req_set_callback(subreq
,
469 tstream_cli_np_writev_disconnect_done
,
473 static void tstream_cli_np_writev_disconnect_done(struct tevent_req
*subreq
)
475 struct tevent_req
*req
=
476 tevent_req_callback_data(subreq
, struct tevent_req
);
477 struct tstream_cli_np_writev_state
*state
=
478 tevent_req_data(req
, struct tstream_cli_np_writev_state
);
479 struct tstream_cli_np
*cli_nps
=
480 tstream_context_data(state
->stream
, struct tstream_cli_np
);
483 status
= cli_close_recv(subreq
);
488 /* return the original error */
489 _tevent_req_error(req
, state
->error
.val
, state
->error
.location
);
492 static int tstream_cli_np_writev_recv(struct tevent_req
*req
,
495 struct tstream_cli_np_writev_state
*state
=
497 struct tstream_cli_np_writev_state
);
500 ret
= tsocket_simple_int_recv(req
, perrno
);
505 tevent_req_received(req
);
509 struct tstream_cli_np_readv_state
{
510 struct tstream_context
*stream
;
511 struct tevent_context
*ev
;
513 struct iovec
*vector
;
519 struct tevent_immediate
*im
;
524 const char *location
;
528 static int tstream_cli_np_readv_state_destructor(struct tstream_cli_np_readv_state
*state
)
530 struct tstream_cli_np
*cli_nps
=
531 tstream_context_data(state
->stream
,
532 struct tstream_cli_np
);
534 cli_nps
->trans
.read_req
= NULL
;
539 static void tstream_cli_np_readv_read_next(struct tevent_req
*req
);
541 static struct tevent_req
*tstream_cli_np_readv_send(TALLOC_CTX
*mem_ctx
,
542 struct tevent_context
*ev
,
543 struct tstream_context
*stream
,
544 struct iovec
*vector
,
547 struct tevent_req
*req
;
548 struct tstream_cli_np_readv_state
*state
;
549 struct tstream_cli_np
*cli_nps
=
550 tstream_context_data(stream
, struct tstream_cli_np
);
552 req
= tevent_req_create(mem_ctx
, &state
,
553 struct tstream_cli_np_readv_state
);
557 state
->stream
= stream
;
561 talloc_set_destructor(state
, tstream_cli_np_readv_state_destructor
);
563 if (!cli_state_is_connected(cli_nps
->cli
)) {
564 tevent_req_error(req
, ENOTCONN
);
565 return tevent_req_post(req
, ev
);
569 * we make a copy of the vector so we can change the structure
571 state
->vector
= talloc_array(state
, struct iovec
, count
);
572 if (tevent_req_nomem(state
->vector
, req
)) {
573 return tevent_req_post(req
, ev
);
575 memcpy(state
->vector
, vector
, sizeof(struct iovec
) * count
);
576 state
->count
= count
;
578 tstream_cli_np_readv_read_next(req
);
579 if (!tevent_req_is_in_progress(req
)) {
580 return tevent_req_post(req
, ev
);
586 static void tstream_cli_np_readv_read_done(struct tevent_req
*subreq
);
588 static void tstream_cli_np_readv_read_next(struct tevent_req
*req
)
590 struct tstream_cli_np_readv_state
*state
=
592 struct tstream_cli_np_readv_state
);
593 struct tstream_cli_np
*cli_nps
=
594 tstream_context_data(state
->stream
,
595 struct tstream_cli_np
);
596 struct tevent_req
*subreq
;
599 * copy the pending buffer first
601 while (cli_nps
->read
.left
> 0 && state
->count
> 0) {
602 uint8_t *base
= (uint8_t *)state
->vector
[0].iov_base
;
603 size_t len
= MIN(cli_nps
->read
.left
, state
->vector
[0].iov_len
);
605 memcpy(base
, cli_nps
->read
.buf
+ cli_nps
->read
.ofs
, len
);
608 state
->vector
[0].iov_base
= base
;
609 state
->vector
[0].iov_len
-= len
;
611 cli_nps
->read
.ofs
+= len
;
612 cli_nps
->read
.left
-= len
;
614 if (state
->vector
[0].iov_len
== 0) {
622 if (state
->count
== 0) {
623 tevent_req_done(req
);
627 if (cli_nps
->trans
.active
) {
628 cli_nps
->trans
.active
= false;
629 cli_nps
->trans
.read_req
= req
;
633 if (cli_nps
->trans
.write_req
) {
634 cli_nps
->trans
.read_req
= req
;
635 tstream_cli_np_readv_trans_start(req
);
639 subreq
= cli_read_andx_send(state
, state
->ev
, cli_nps
->cli
,
640 cli_nps
->fnum
, 0, TSTREAM_CLI_NP_BUF_SIZE
);
641 if (tevent_req_nomem(subreq
, req
)) {
644 tevent_req_set_callback(subreq
,
645 tstream_cli_np_readv_read_done
,
649 static void tstream_cli_np_readv_trans_done(struct tevent_req
*subreq
);
651 static void tstream_cli_np_readv_trans_start(struct tevent_req
*req
)
653 struct tstream_cli_np_readv_state
*state
=
655 struct tstream_cli_np_readv_state
);
656 struct tstream_cli_np
*cli_nps
=
657 tstream_context_data(state
->stream
,
658 struct tstream_cli_np
);
659 struct tevent_req
*subreq
;
661 state
->trans
.im
= tevent_create_immediate(state
);
662 if (tevent_req_nomem(state
->trans
.im
, req
)) {
666 subreq
= cli_trans_send(state
, state
->ev
,
671 cli_nps
->trans
.setup
, 2,
676 TSTREAM_CLI_NP_BUF_SIZE
);
677 if (tevent_req_nomem(subreq
, req
)) {
680 tevent_req_set_callback(subreq
,
681 tstream_cli_np_readv_trans_done
,
685 static void tstream_cli_np_readv_disconnect_now(struct tevent_req
*req
,
687 const char *location
);
688 static void tstream_cli_np_readv_trans_next(struct tevent_context
*ctx
,
689 struct tevent_immediate
*im
,
692 static void tstream_cli_np_readv_trans_done(struct tevent_req
*subreq
)
694 struct tevent_req
*req
=
695 tevent_req_callback_data(subreq
, struct tevent_req
);
696 struct tstream_cli_np_readv_state
*state
=
697 tevent_req_data(req
, struct tstream_cli_np_readv_state
);
698 struct tstream_cli_np
*cli_nps
=
699 tstream_context_data(state
->stream
, struct tstream_cli_np
);
704 status
= cli_trans_recv(subreq
, state
, NULL
, NULL
, 0, NULL
,
706 &rcvbuf
, 0, &received
);
708 if (NT_STATUS_EQUAL(status
, NT_STATUS_BUFFER_TOO_SMALL
)) {
709 status
= NT_STATUS_OK
;
711 if (!NT_STATUS_IS_OK(status
)) {
712 tstream_cli_np_readv_disconnect_now(req
, EIO
, __location__
);
716 if (received
> TSTREAM_CLI_NP_BUF_SIZE
) {
717 tstream_cli_np_readv_disconnect_now(req
, EIO
, __location__
);
722 tstream_cli_np_readv_disconnect_now(req
, EPIPE
, __location__
);
726 cli_nps
->read
.ofs
= 0;
727 cli_nps
->read
.left
= received
;
728 memcpy(cli_nps
->read
.buf
, rcvbuf
, received
);
731 if (cli_nps
->trans
.write_req
== NULL
) {
732 tstream_cli_np_readv_read_next(req
);
736 tevent_schedule_immediate(state
->trans
.im
, state
->ev
,
737 tstream_cli_np_readv_trans_next
, req
);
739 tevent_req_done(cli_nps
->trans
.write_req
);
742 static void tstream_cli_np_readv_trans_next(struct tevent_context
*ctx
,
743 struct tevent_immediate
*im
,
746 struct tevent_req
*req
=
747 talloc_get_type_abort(private_data
,
750 tstream_cli_np_readv_read_next(req
);
753 static void tstream_cli_np_readv_read_done(struct tevent_req
*subreq
)
755 struct tevent_req
*req
=
756 tevent_req_callback_data(subreq
, struct tevent_req
);
757 struct tstream_cli_np_readv_state
*state
=
758 tevent_req_data(req
, struct tstream_cli_np_readv_state
);
759 struct tstream_cli_np
*cli_nps
=
760 tstream_context_data(state
->stream
, struct tstream_cli_np
);
766 * We must free subreq in this function as there is
767 * a timer event attached to it.
770 status
= cli_read_andx_recv(subreq
, &received
, &rcvbuf
);
772 * We can't TALLOC_FREE(subreq) as usual here, as rcvbuf still is a
775 if (NT_STATUS_EQUAL(status
, NT_STATUS_BUFFER_TOO_SMALL
)) {
777 * NT_STATUS_BUFFER_TOO_SMALL means that there's
778 * more data to read when the named pipe is used
779 * in message mode (which is the case here).
781 * But we hide this from the caller.
783 status
= NT_STATUS_OK
;
785 if (!NT_STATUS_IS_OK(status
)) {
787 tstream_cli_np_readv_disconnect_now(req
, EIO
, __location__
);
791 if (received
> TSTREAM_CLI_NP_BUF_SIZE
) {
793 tstream_cli_np_readv_disconnect_now(req
, EIO
, __location__
);
799 tstream_cli_np_readv_disconnect_now(req
, EPIPE
, __location__
);
803 cli_nps
->read
.ofs
= 0;
804 cli_nps
->read
.left
= received
;
805 memcpy(cli_nps
->read
.buf
, rcvbuf
, received
);
808 tstream_cli_np_readv_read_next(req
);
811 static void tstream_cli_np_readv_disconnect_done(struct tevent_req
*subreq
);
813 static void tstream_cli_np_readv_error(struct tevent_req
*req
);
815 static void tstream_cli_np_readv_disconnect_now(struct tevent_req
*req
,
817 const char *location
)
819 struct tstream_cli_np_readv_state
*state
=
821 struct tstream_cli_np_readv_state
);
822 struct tstream_cli_np
*cli_nps
=
823 tstream_context_data(state
->stream
,
824 struct tstream_cli_np
);
825 struct tevent_req
*subreq
;
827 state
->error
.val
= error
;
828 state
->error
.location
= location
;
830 if (!cli_state_is_connected(cli_nps
->cli
)) {
831 /* return the original error */
832 tstream_cli_np_readv_error(req
);
836 subreq
= cli_close_send(state
, state
->ev
, cli_nps
->cli
, cli_nps
->fnum
);
837 if (subreq
== NULL
) {
838 /* return the original error */
839 tstream_cli_np_readv_error(req
);
842 tevent_req_set_callback(subreq
,
843 tstream_cli_np_readv_disconnect_done
,
847 static void tstream_cli_np_readv_disconnect_done(struct tevent_req
*subreq
)
849 struct tevent_req
*req
=
850 tevent_req_callback_data(subreq
, struct tevent_req
);
851 struct tstream_cli_np_readv_state
*state
=
852 tevent_req_data(req
, struct tstream_cli_np_readv_state
);
853 struct tstream_cli_np
*cli_nps
=
854 tstream_context_data(state
->stream
, struct tstream_cli_np
);
857 status
= cli_close_recv(subreq
);
862 tstream_cli_np_readv_error(req
);
865 static void tstream_cli_np_readv_error_trigger(struct tevent_context
*ctx
,
866 struct tevent_immediate
*im
,
869 static void tstream_cli_np_readv_error(struct tevent_req
*req
)
871 struct tstream_cli_np_readv_state
*state
=
873 struct tstream_cli_np_readv_state
);
874 struct tstream_cli_np
*cli_nps
=
875 tstream_context_data(state
->stream
,
876 struct tstream_cli_np
);
878 if (cli_nps
->trans
.write_req
== NULL
) {
879 /* return the original error */
880 _tevent_req_error(req
, state
->error
.val
, state
->error
.location
);
884 if (state
->trans
.im
== NULL
) {
885 /* return the original error */
886 _tevent_req_error(req
, state
->error
.val
, state
->error
.location
);
890 tevent_schedule_immediate(state
->trans
.im
, state
->ev
,
891 tstream_cli_np_readv_error_trigger
, req
);
893 /* return the original error for writev */
894 _tevent_req_error(cli_nps
->trans
.write_req
,
895 state
->error
.val
, state
->error
.location
);
898 static void tstream_cli_np_readv_error_trigger(struct tevent_context
*ctx
,
899 struct tevent_immediate
*im
,
902 struct tevent_req
*req
=
903 talloc_get_type_abort(private_data
,
905 struct tstream_cli_np_readv_state
*state
=
907 struct tstream_cli_np_readv_state
);
909 /* return the original error */
910 _tevent_req_error(req
, state
->error
.val
, state
->error
.location
);
913 static int tstream_cli_np_readv_recv(struct tevent_req
*req
,
916 struct tstream_cli_np_readv_state
*state
=
917 tevent_req_data(req
, struct tstream_cli_np_readv_state
);
920 ret
= tsocket_simple_int_recv(req
, perrno
);
925 tevent_req_received(req
);
929 struct tstream_cli_np_disconnect_state
{
930 struct tstream_context
*stream
;
933 static void tstream_cli_np_disconnect_done(struct tevent_req
*subreq
);
935 static struct tevent_req
*tstream_cli_np_disconnect_send(TALLOC_CTX
*mem_ctx
,
936 struct tevent_context
*ev
,
937 struct tstream_context
*stream
)
939 struct tstream_cli_np
*cli_nps
= tstream_context_data(stream
,
940 struct tstream_cli_np
);
941 struct tevent_req
*req
;
942 struct tstream_cli_np_disconnect_state
*state
;
943 struct tevent_req
*subreq
;
945 req
= tevent_req_create(mem_ctx
, &state
,
946 struct tstream_cli_np_disconnect_state
);
951 state
->stream
= stream
;
953 if (!cli_state_is_connected(cli_nps
->cli
)) {
954 tevent_req_error(req
, ENOTCONN
);
955 return tevent_req_post(req
, ev
);
958 subreq
= cli_close_send(state
, ev
, cli_nps
->cli
, cli_nps
->fnum
);
959 if (tevent_req_nomem(subreq
, req
)) {
960 return tevent_req_post(req
, ev
);
962 tevent_req_set_callback(subreq
, tstream_cli_np_disconnect_done
, req
);
967 static void tstream_cli_np_disconnect_done(struct tevent_req
*subreq
)
969 struct tevent_req
*req
= tevent_req_callback_data(subreq
,
971 struct tstream_cli_np_disconnect_state
*state
=
972 tevent_req_data(req
, struct tstream_cli_np_disconnect_state
);
973 struct tstream_cli_np
*cli_nps
=
974 tstream_context_data(state
->stream
, struct tstream_cli_np
);
977 status
= cli_close_recv(subreq
);
979 if (!NT_STATUS_IS_OK(status
)) {
980 tevent_req_error(req
, EIO
);
986 tevent_req_done(req
);
989 static int tstream_cli_np_disconnect_recv(struct tevent_req
*req
,
994 ret
= tsocket_simple_int_recv(req
, perrno
);
996 tevent_req_received(req
);
1000 static const struct tstream_context_ops tstream_cli_np_ops
= {
1003 .pending_bytes
= tstream_cli_np_pending_bytes
,
1005 .readv_send
= tstream_cli_np_readv_send
,
1006 .readv_recv
= tstream_cli_np_readv_recv
,
1008 .writev_send
= tstream_cli_np_writev_send
,
1009 .writev_recv
= tstream_cli_np_writev_recv
,
1011 .disconnect_send
= tstream_cli_np_disconnect_send
,
1012 .disconnect_recv
= tstream_cli_np_disconnect_recv
,
1015 NTSTATUS
_tstream_cli_np_existing(TALLOC_CTX
*mem_ctx
,
1016 struct cli_state
*cli
,
1018 struct tstream_context
**_stream
,
1019 const char *location
)
1021 struct tstream_context
*stream
;
1022 struct tstream_cli_np
*cli_nps
;
1024 stream
= tstream_context_create(mem_ctx
,
1025 &tstream_cli_np_ops
,
1027 struct tstream_cli_np
,
1030 return NT_STATUS_NO_MEMORY
;
1032 ZERO_STRUCTP(cli_nps
);
1035 cli_nps
->fnum
= fnum
;
1038 return NT_STATUS_OK
;