s3-rpc: make api_pipe_request async
authorDavid Disseldorp <ddiss@samba.org>
Thu, 26 Apr 2012 09:56:23 +0000 (11:56 +0200)
committerDavid Disseldorp <ddiss@samba.org>
Wed, 19 Sep 2012 03:59:02 +0000 (05:59 +0200)
source3/rpc_server/srv_pipe.c

index 2b0c55775b5e6803405b9921c96afa2af945b76e..0eb51b568f820591721c1e5caef47f0914e05ece 100644 (file)
@@ -1286,28 +1286,40 @@ static bool api_rpcTNP(struct pipes_struct *p, struct ncacn_packet *pkt,
                       const struct api_struct *api_rpc_cmds, int n_cmds,
                       const struct ndr_syntax_id *syntax);
 
+struct api_pipe_request_state {
+       bool ret;
+};
 /****************************************************************************
  Find the correct RPC function to call for this request.
  If the pipe is authenticated then become the correct UNIX user
  before doing the call.
 ****************************************************************************/
 
-static bool api_pipe_request(struct pipes_struct *p,
-                               struct ncacn_packet *pkt)
+static struct tevent_req *api_pipe_request_send(struct tevent_context *ev,
+                                               struct pipes_struct *p,
+                                               struct ncacn_packet *pkt)
 {
-       bool ret = False;
        struct pipe_rpc_fns *pipe_fns;
+       struct api_pipe_request_state *state;
+       struct tevent_req *req = tevent_req_create(p->mem_ctx, &state,
+                                               struct api_pipe_request_state);
+       if (req == NULL) {
+               return NULL;
+       }
+       state->ret = false;
 
        if (!p->pipe_bound) {
                DEBUG(1, ("Pipe not bound!\n"));
                data_blob_free(&p->out_data.rdata);
-               return false;
+               tevent_req_done(req);
+               return tevent_req_post(req, ev);
        }
 
        if (!become_authenticated_pipe_user(p->session_info)) {
                DEBUG(1, ("Failed to become pipe user!\n"));
                data_blob_free(&p->out_data.rdata);
-               return false;
+               tevent_req_done(req);
+               return tevent_req_post(req, ev);
        }
 
        /* get the set of RPC functions for this context */
@@ -1321,9 +1333,9 @@ static bool api_pipe_request(struct pipes_struct *p,
                DEBUG(5, ("Requested %s rpc service\n",
                          get_pipe_name_from_syntax(talloc_tos(), &pipe_fns->syntax)));
 
-               ret = api_rpcTNP(p, pkt, pipe_fns->cmds, pipe_fns->n_cmds,
-                                &pipe_fns->syntax);
-
+               state->ret = api_rpcTNP(p, pkt, pipe_fns->cmds,
+                                       pipe_fns->n_cmds,
+                                       &pipe_fns->syntax);
                TALLOC_FREE(frame);
        }
        else {
@@ -1333,10 +1345,21 @@ static bool api_pipe_request(struct pipes_struct *p,
        }
 
        unbecome_authenticated_pipe_user();
+       tevent_req_done(req);
+       return tevent_req_post(req, ev);
+}
+
+static bool api_pipe_request_recv(struct tevent_req *req)
+{
+       struct api_pipe_request_state *state
+               = tevent_req_data(req, struct api_pipe_request_state);
+       bool ret = state->ret;
 
+       tevent_req_received(req);
        return ret;
 }
 
+
 /*******************************************************************
  Calls the underlying RPC function for a named pipe.
  ********************************************************************/
@@ -1501,6 +1524,7 @@ static NTSTATUS dcesrv_auth_request(struct pipe_auth_data *auth,
 struct process_request_pdu_state {
        bool success;
 };
+static void process_request_pdu_done(struct tevent_req *subreq);
 /****************************************************************************
  Processes a request pdu. This will do auth processing if needed, and
  appends the data into the complete stream if the LAST flag is not set.
@@ -1579,7 +1603,6 @@ static struct tevent_req *process_request_pdu_send(struct tevent_context *ev,
        }
 
        if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
-               bool ret = False;
                /*
                 * Ok - we finally have a complete RPC stream.
                 * Call the rpc command to process it.
@@ -1589,10 +1612,18 @@ static struct tevent_req *process_request_pdu_send(struct tevent_context *ev,
                 * Process the complete data stream here.
                 */
                if (pipe_init_outgoing_data(p)) {
-                       ret = api_pipe_request(p, pkt);
+                       struct tevent_req *subreq;
+                       subreq = api_pipe_request_send(ev, p, pkt);
+                       if (tevent_req_nomem(subreq, req)) {
+                               state->success = false;
+                               return tevent_req_post(req, ev);
+                       }
+                       tevent_req_set_callback(subreq,
+                                               process_request_pdu_done, req);
+                       return req;
                }
 
-               state->success = ret;
+               state->success = false;
                tevent_req_done(req);
                return tevent_req_post(req, ev);
        }
@@ -1602,6 +1633,17 @@ static struct tevent_req *process_request_pdu_send(struct tevent_context *ev,
        return tevent_req_post(req, ev);
 }
 
+static void process_request_pdu_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(subreq,
+                                                         struct tevent_req);
+       struct process_request_pdu_state *state
+               = tevent_req_data(req, struct process_request_pdu_state);
+
+       state->success = api_pipe_request_recv(subreq);
+       tevent_req_done(req);
+}
+
 static bool process_request_pdu_recv(struct tevent_req *req)
 {
        struct process_request_pdu_state *state