s3: Optimize g_lock_lock for a heavily contended case
[Samba.git] / source4 / rpc_server / common / forward.c
blob07cf1c80ccd25310d26c45a74c76059916db525f
1 /*
2 Unix SMB/CIFS implementation.
4 forwarding of RPC calls to other tasks
6 Copyright (C) Andrew Tridgell 2009
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "rpc_server/dcerpc_server.h"
24 #include "messaging/irpc.h"
26 struct dcesrv_forward_state {
27 const char *opname;
28 struct dcesrv_call_state *dce_call;
32 called when the forwarded rpc request is finished
34 static void dcesrv_irpc_forward_callback(struct irpc_request *ireq)
36 struct dcesrv_forward_state *st = talloc_get_type(ireq->async.private_data,
37 struct dcesrv_forward_state);
38 const char *opname = st->opname;
39 NTSTATUS status;
40 if (!NT_STATUS_IS_OK(ireq->status)) {
41 DEBUG(0,("IRPC callback failed for %s - %s\n",
42 opname, nt_errstr(ireq->status)));
43 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
45 talloc_free(ireq);
46 status = dcesrv_reply(st->dce_call);
47 if (!NT_STATUS_IS_OK(status)) {
48 DEBUG(0,("%s_handler: dcesrv_reply() failed - %s\n",
49 opname, nt_errstr(status)));
56 forward a RPC call using IRPC to another task
58 void dcesrv_irpc_forward_rpc_call(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
59 void *r, uint32_t callid,
60 const struct ndr_interface_table *ndr_table,
61 const char *dest_task, const char *opname)
63 struct server_id *sid;
64 struct irpc_request *ireq;
65 struct dcesrv_forward_state *st;
67 st = talloc(mem_ctx, struct dcesrv_forward_state);
68 if (st == NULL) {
69 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
70 return;
73 st->dce_call = dce_call;
74 st->opname = opname;
76 /* if the caller has said they can't support async calls
77 then fail the call */
78 if (!(dce_call->state_flags & DCESRV_CALL_STATE_FLAG_MAY_ASYNC)) {
79 /* we're not allowed to reply async */
80 DEBUG(0,("%s: Not available synchronously\n", dest_task));
81 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
82 return;
85 /* find the server task */
86 sid = irpc_servers_byname(dce_call->msg_ctx, mem_ctx, dest_task);
87 if (sid == NULL || sid[0].id == 0) {
88 DEBUG(0,("%s: Unable to find %s task\n", dest_task, opname));
89 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
90 return;
93 /* forward the call */
94 ireq = irpc_call_send(dce_call->msg_ctx, sid[0], ndr_table, callid, r, mem_ctx);
95 if (ireq == NULL) {
96 DEBUG(0,("%s: Failed to forward request to %s task\n",
97 opname, dest_task));
98 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
99 return;
102 /* mark the request as replied async */
103 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
105 /* setup the callback */
106 ireq->async.fn = dcesrv_irpc_forward_callback;
107 ireq->async.private_data = st;