s3-rpc: make rpcint_dispatch async
authorDavid Disseldorp <ddiss@samba.org>
Thu, 26 Apr 2012 12:53:33 +0000 (14:53 +0200)
committerDavid Disseldorp <ddiss@samba.org>
Mon, 15 Apr 2013 16:15:18 +0000 (18:15 +0200)
source3/rpc_server/rpc_ncacn_np.c

index 25ad8570a2864af64a601fcf021ada2993a655b0..472014b8206875c14116e078d47593ed9b4c3df3 100644 (file)
@@ -102,17 +102,26 @@ struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx,
        return p;
 }
 
-static NTSTATUS rpcint_dispatch(struct pipes_struct *p,
-                               TALLOC_CTX *mem_ctx,
-                               uint32_t opnum,
-                               const DATA_BLOB *in_data,
-                               DATA_BLOB *out_data)
+struct rpcint_dispatch_state {
+       DATA_BLOB out_data;
+};
+static struct tevent_req *rpcint_dispatch_send(struct tevent_context *ev,
+                                              TALLOC_CTX *mem_ctx,
+                                              struct pipes_struct *p,
+                                              uint32_t opnum,
+                                              const DATA_BLOB *in_data)
 {
        struct pipe_rpc_fns *fns = find_pipe_fns_by_context(p->contexts, 0);
        uint32_t num_cmds = fns->n_cmds;
        const struct api_struct *cmds = fns->cmds;
        uint32_t i;
        bool ok;
+       struct rpcint_dispatch_state *state;
+       struct tevent_req *req = tevent_req_create(mem_ctx, &state,
+                                               struct rpcint_dispatch_state);
+       if (req == NULL) {
+               return NULL;
+       }
 
        /* set opnum */
        p->opnum = opnum;
@@ -124,7 +133,8 @@ static NTSTATUS rpcint_dispatch(struct pipes_struct *p,
        }
 
        if (i == num_cmds) {
-               return NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE;
+               tevent_req_nterror(req, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE);
+               return tevent_req_post(req, ev);
        }
 
        p->in_data.data = *in_data;
@@ -135,24 +145,44 @@ static NTSTATUS rpcint_dispatch(struct pipes_struct *p,
        if (!ok) {
                data_blob_free(&p->out_data.rdata);
                talloc_free_children(p->mem_ctx);
-               return NT_STATUS_RPC_CALL_FAILED;
+               tevent_req_nterror(req, NT_STATUS_RPC_CALL_FAILED);
+               return tevent_req_post(req, ev);
        }
 
        if (p->fault_state) {
-               NTSTATUS status;
-
-               status = NT_STATUS(p->fault_state);
+               NTSTATUS status = NT_STATUS(p->fault_state);
                p->fault_state = 0;
                data_blob_free(&p->out_data.rdata);
                talloc_free_children(p->mem_ctx);
-               return status;
+               tevent_req_nterror(req, status);
+               return tevent_req_post(req, ev);
        }
 
-       *out_data = p->out_data.rdata;
-       talloc_steal(mem_ctx, out_data->data);
+       state->out_data = p->out_data.rdata;
+       talloc_steal(state, state->out_data.data);
        p->out_data.rdata = data_blob_null;
 
        talloc_free_children(p->mem_ctx);
+       tevent_req_done(req);
+       return tevent_req_post(req, ev);
+}
+
+static NTSTATUS rpcint_dispatch_recv(struct tevent_req *req,
+                                    TALLOC_CTX *mem_ctx,
+                                    DATA_BLOB *out_data)
+{
+       struct rpcint_dispatch_state *state
+               = tevent_req_data(req, struct rpcint_dispatch_state);
+       NTSTATUS status;
+
+       if (tevent_req_is_nterror(req, &status)) {
+               tevent_req_received(req);
+               return status;
+       }
+
+       *out_data = state->out_data;
+       talloc_steal(mem_ctx, out_data->data);
+       tevent_req_received(req);
        return NT_STATUS_OK;
 }
 
@@ -184,6 +214,7 @@ struct rpcint_bh_raw_call_state {
        DATA_BLOB out_data;
        uint32_t out_flags;
 };
+static void rpcint_bh_raw_call_done(struct tevent_req *subreq);
 
 static struct tevent_req *rpcint_bh_raw_call_send(TALLOC_CTX *mem_ctx,
                                                  struct tevent_context *ev,
@@ -198,9 +229,9 @@ static struct tevent_req *rpcint_bh_raw_call_send(TALLOC_CTX *mem_ctx,
                dcerpc_binding_handle_data(h,
                struct rpcint_bh_state);
        struct tevent_req *req;
+       struct tevent_req *subreq;
        struct rpcint_bh_raw_call_state *state;
        bool ok;
-       NTSTATUS status;
 
        req = tevent_req_create(mem_ctx, &state,
                                struct rpcint_bh_raw_call_state);
@@ -216,17 +247,31 @@ static struct tevent_req *rpcint_bh_raw_call_send(TALLOC_CTX *mem_ctx,
                return tevent_req_post(req, ev);
        }
 
-       /* TODO: allow async */
-       status = rpcint_dispatch(hs->p, state, opnum,
-                                &state->in_data,
-                                &state->out_data);
-       if (!NT_STATUS_IS_OK(status)) {
-               tevent_req_nterror(req, status);
+       subreq = rpcint_dispatch_send(ev, state, hs->p, opnum,
+                                     &state->in_data);
+       if (tevent_req_nomem(subreq, req)) {
                return tevent_req_post(req, ev);
        }
+       tevent_req_set_callback(subreq, rpcint_bh_raw_call_done, req);
 
+       return req;
+}
+
+static void rpcint_bh_raw_call_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(subreq,
+                                                         struct tevent_req);
+       struct rpcint_bh_raw_call_state *state
+               = tevent_req_data(req, struct rpcint_bh_raw_call_state);
+       NTSTATUS status;
+
+       status = rpcint_dispatch_recv(subreq, state,
+                                     &state->out_data);
+       if (!NT_STATUS_IS_OK(status)) {
+               tevent_req_nterror(req, status);
+               return;
+       }
        tevent_req_done(req);
-       return tevent_req_post(req, ev);
 }
 
 static NTSTATUS rpcint_bh_raw_call_recv(struct tevent_req *req,