libsmbclient: Make cli_tree_connect async
authorVolker Lendecke <vl@samba.org>
Sat, 6 Apr 2013 08:57:41 +0000 (10:57 +0200)
committerJeremy Allison <jra@samba.org>
Thu, 11 Apr 2013 21:46:36 +0000 (14:46 -0700)
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/libsmb/cliconnect.c

index f196941e9cc0ac3a10aabd5b7ff428cb65065e8f..b5055cc34f77954b3bae642284a84b13952e1ccb 100644 (file)
@@ -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;
 }
 
 /****************************************************************************