summaryrefslogtreecommitdiff
path: root/source3/libsmb
diff options
context:
space:
mode:
Diffstat (limited to 'source3/libsmb')
-rw-r--r--source3/libsmb/cli_np_tstream.c93
1 files changed, 70 insertions, 23 deletions
diff --git a/source3/libsmb/cli_np_tstream.c b/source3/libsmb/cli_np_tstream.c
index 409b40dab4..898b40509c 100644
--- a/source3/libsmb/cli_np_tstream.c
+++ b/source3/libsmb/cli_np_tstream.c
@@ -39,6 +39,7 @@ struct tstream_cli_np {
struct {
bool active;
+ struct tevent_req *read_req;
struct tevent_req *write_req;
uint16_t setup[2];
} trans;
@@ -182,6 +183,7 @@ NTSTATUS _tstream_cli_np_open_recv(struct tevent_req *req,
talloc_set_destructor(cli_nps, tstream_cli_np_destructor);
cli_nps->trans.active = false;
+ cli_nps->trans.read_req = NULL;
cli_nps->trans.write_req = NULL;
SSVAL(cli_nps->trans.setup+0, 0, TRANSACT_DCERPCCMD);
SSVAL(cli_nps->trans.setup+1, 0, cli_nps->fnum);
@@ -222,6 +224,10 @@ NTSTATUS tstream_cli_np_use_trans(struct tstream_context *stream)
struct tstream_cli_np *cli_nps = tstream_context_data(stream,
struct tstream_cli_np);
+ if (cli_nps->trans.read_req) {
+ return NT_STATUS_PIPE_BUSY;
+ }
+
if (cli_nps->trans.write_req) {
return NT_STATUS_PIPE_BUSY;
}
@@ -329,6 +335,7 @@ static struct tevent_req *tstream_cli_np_writev_send(TALLOC_CTX *mem_ctx,
return req;
}
+static void tstream_cli_np_readv_trans_start(struct tevent_req *req);
static void tstream_cli_np_writev_write_done(struct tevent_req *subreq);
static void tstream_cli_np_writev_write_next(struct tevent_req *req)
@@ -379,6 +386,12 @@ static void tstream_cli_np_writev_write_next(struct tevent_req *req)
return;
}
+ if (cli_nps->trans.read_req && state->count == 0) {
+ cli_nps->trans.write_req = req;
+ tstream_cli_np_readv_trans_start(cli_nps->trans.read_req);
+ return;
+ }
+
subreq = cli_write_andx_send(state, state->ev, cli_nps->cli,
cli_nps->fnum,
8, /* 8 means message mode. */
@@ -512,6 +525,17 @@ struct tstream_cli_np_readv_state {
} error;
};
+static int tstream_cli_np_readv_state_destructor(struct tstream_cli_np_readv_state *state)
+{
+ struct tstream_cli_np *cli_nps =
+ tstream_context_data(state->stream,
+ struct tstream_cli_np);
+
+ cli_nps->trans.read_req = NULL;
+
+ return 0;
+}
+
static void tstream_cli_np_readv_read_next(struct tevent_req *req);
static struct tevent_req *tstream_cli_np_readv_send(TALLOC_CTX *mem_ctx,
@@ -534,6 +558,8 @@ static struct tevent_req *tstream_cli_np_readv_send(TALLOC_CTX *mem_ctx,
state->ev = ev;
state->ret = 0;
+ talloc_set_destructor(state, tstream_cli_np_readv_state_destructor);
+
if (!cli_state_is_connected(cli_nps->cli)) {
tevent_req_error(req, ENOTCONN);
return tevent_req_post(req, ev);
@@ -557,7 +583,6 @@ static struct tevent_req *tstream_cli_np_readv_send(TALLOC_CTX *mem_ctx,
return req;
}
-static void tstream_cli_np_readv_trans_done(struct tevent_req *subreq);
static void tstream_cli_np_readv_read_done(struct tevent_req *subreq);
static void tstream_cli_np_readv_read_next(struct tevent_req *req)
@@ -599,29 +624,15 @@ static void tstream_cli_np_readv_read_next(struct tevent_req *req)
return;
}
- if (cli_nps->trans.write_req) {
- state->trans.im = tevent_create_immediate(state);
- if (tevent_req_nomem(state->trans.im, req)) {
- return;
- }
+ if (cli_nps->trans.active) {
+ cli_nps->trans.active = false;
+ cli_nps->trans.read_req = req;
+ return;
+ }
- subreq = cli_trans_send(state, state->ev,
- cli_nps->cli,
- SMBtrans,
- "\\PIPE\\",
- 0, 0, 0,
- cli_nps->trans.setup, 2,
- 0,
- NULL, 0, 0,
- cli_nps->write.buf,
- cli_nps->write.ofs,
- TSTREAM_CLI_NP_BUF_SIZE);
- if (tevent_req_nomem(subreq, req)) {
- return;
- }
- tevent_req_set_callback(subreq,
- tstream_cli_np_readv_trans_done,
- req);
+ if (cli_nps->trans.write_req) {
+ cli_nps->trans.read_req = req;
+ tstream_cli_np_readv_trans_start(req);
return;
}
@@ -635,6 +646,42 @@ static void tstream_cli_np_readv_read_next(struct tevent_req *req)
req);
}
+static void tstream_cli_np_readv_trans_done(struct tevent_req *subreq);
+
+static void tstream_cli_np_readv_trans_start(struct tevent_req *req)
+{
+ struct tstream_cli_np_readv_state *state =
+ tevent_req_data(req,
+ struct tstream_cli_np_readv_state);
+ struct tstream_cli_np *cli_nps =
+ tstream_context_data(state->stream,
+ struct tstream_cli_np);
+ struct tevent_req *subreq;
+
+ state->trans.im = tevent_create_immediate(state);
+ if (tevent_req_nomem(state->trans.im, req)) {
+ return;
+ }
+
+ subreq = cli_trans_send(state, state->ev,
+ cli_nps->cli,
+ SMBtrans,
+ "\\PIPE\\",
+ 0, 0, 0,
+ cli_nps->trans.setup, 2,
+ 0,
+ NULL, 0, 0,
+ cli_nps->write.buf,
+ cli_nps->write.ofs,
+ TSTREAM_CLI_NP_BUF_SIZE);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq,
+ tstream_cli_np_readv_trans_done,
+ req);
+}
+
static void tstream_cli_np_readv_disconnect_now(struct tevent_req *req,
int error,
const char *location);