From 5daf6476fa431bea2815f1e7afbfea3688d39d19 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 6 Apr 2013 10:57:41 +0200 Subject: libsmbclient: Make cli_tree_connect async Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison --- source3/libsmb/cliconnect.c | 123 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 109 insertions(+), 14 deletions(-) (limited to 'source3/libsmb') diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index f196941e9c..b5055cc34f 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -2622,34 +2622,129 @@ NTSTATUS cli_tcon_andx(struct cli_state *cli, const char *share, return status; } -NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share, - const char *dev, const char *pass, int passlen) +struct cli_tree_connect_state { + struct cli_state *cli; +}; + +static struct tevent_req *cli_raw_tcon_send( + TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli, + const char *service, const char *pass, const char *dev); +static NTSTATUS cli_raw_tcon_recv(struct tevent_req *req, + uint16 *max_xmit, uint16 *tid); + +static void cli_tree_connect_smb2_done(struct tevent_req *subreq); +static void cli_tree_connect_andx_done(struct tevent_req *subreq); +static void cli_tree_connect_raw_done(struct tevent_req *subreq); + +static struct tevent_req *cli_tree_connect_send( + TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct cli_state *cli, + const char *share, const char *dev, const char *pass, int passlen) { - NTSTATUS status; - uint16_t max_xmit = 0; - uint16_t tid = 0; + struct tevent_req *req, *subreq; + struct cli_tree_connect_state *state; + + req = tevent_req_create(mem_ctx, &state, + struct cli_tree_connect_state); + if (req == NULL) { + return NULL; + } + state->cli = cli; cli->share = talloc_strdup(cli, share); - if (!cli->share) { - return NT_STATUS_NO_MEMORY; + if (tevent_req_nomem(cli->share, req)) { + return tevent_req_post(req, ev); } if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { - return smb2cli_tcon(cli, share); + subreq = smb2cli_tcon_send(state, ev, cli, share); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, cli_tree_connect_smb2_done, + req); + return req; } if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_LANMAN1) { - return cli_tcon_andx(cli, share, dev, pass, passlen); + subreq = cli_tcon_andx_send(state, ev, cli, share, dev, + pass, passlen); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, cli_tree_connect_andx_done, + req); + return req; } - status = cli_raw_tcon(cli, share, pass, dev, &max_xmit, &tid); - if (!NT_STATUS_IS_OK(status)) { - return status; + subreq = cli_raw_tcon_send(state, ev, cli, share, pass, dev); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); } + tevent_req_set_callback(subreq, cli_tree_connect_raw_done, req); - cli_state_set_tid(cli, tid); + return req; +} - return NT_STATUS_OK; +static void cli_tree_connect_smb2_done(struct tevent_req *subreq) +{ + return tevent_req_simple_finish_ntstatus( + subreq, smb2cli_tcon_recv(subreq)); +} + +static void cli_tree_connect_andx_done(struct tevent_req *subreq) +{ + return tevent_req_simple_finish_ntstatus( + subreq, cli_tcon_andx_recv(subreq)); +} + +static void cli_tree_connect_raw_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct cli_tree_connect_state *state = tevent_req_data( + req, struct cli_tree_connect_state); + NTSTATUS status; + uint16_t max_xmit = 0; + uint16_t tid = 0; + + status = cli_raw_tcon_recv(subreq, &max_xmit, &tid); + if (tevent_req_nterror(req, status)) { + return; + } + cli_state_set_tid(state->cli, tid); + tevent_req_done(req); +} + +static NTSTATUS cli_tree_connect_recv(struct tevent_req *req) +{ + return tevent_req_simple_recv_ntstatus(req); +} + +NTSTATUS cli_tree_connect(struct cli_state *cli, const char *share, + const char *dev, const char *pass, int passlen) +{ + struct tevent_context *ev; + struct tevent_req *req; + NTSTATUS status = NT_STATUS_NO_MEMORY; + + if (smbXcli_conn_has_async_calls(cli->conn)) { + return NT_STATUS_INVALID_PARAMETER; + } + ev = samba_tevent_context_init(talloc_tos()); + if (ev == NULL) { + goto fail; + } + req = cli_tree_connect_send(ev, ev, cli, share, dev, pass, passlen); + if (req == NULL) { + goto fail; + } + if (!tevent_req_poll_ntstatus(req, ev, &status)) { + goto fail; + } + status = cli_tree_connect_recv(req); +fail: + TALLOC_FREE(ev); + return status; } /**************************************************************************** -- cgit