From fae215266b6711b24f4893653b146751885e4e5f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 11 Jan 2005 16:53:02 +0000 Subject: r4690: - add support for async rpc server replies the backend should check for (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_MAY_ASYNC) then it's allowed to reply async then the backend should mark that call as async with dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC; later it has to manualy set r->out.result and then send the reply by calling status = dcesrv_reply(p->dce_call); NOTE: that ncacn_np doesn't support async replies yet - implement an async version of echo_TestSleep - reenable the echo_TestSleep torture test (this need to be more strict when we have support for async ncacn_np) metze (This used to be commit f0a0dbeb25b034b1333078ca085999359f5f6209) --- source4/build/pidl/server.pm | 73 ++++++++++++++++++++++++++++++--------- source4/build/pidl/stub.pm | 82 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 120 insertions(+), 35 deletions(-) (limited to 'source4/build') diff --git a/source4/build/pidl/server.pm b/source4/build/pidl/server.pm index 5c70adf2af..e080bf5654 100644 --- a/source4/build/pidl/server.pm +++ b/source4/build/pidl/server.pm @@ -36,6 +36,29 @@ sub gen_dispatch_switch($) } else { pidl "\t\t$d->{NAME}(dce_call, mem_ctx, r2);\n"; } + pidl "\t\tif (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {\n"; + pidl "\t\t\tDEBUG(5,(\"function $d->{NAME} will reply async\\n\"));\n"; + pidl "\t\t}\n"; + pidl "\t\tbreak;\n\t}\n"; + $count++; + } +} + +##################################################### +# generate the switch statement for function reply +sub gen_reply_switch($) +{ + my $data = shift; + + my $count = 0; + foreach my $d (@{$data}) { + next if ($d->{TYPE} ne "FUNCTION"); + + pidl "\tcase $count: {\n"; + pidl "\t\tstruct $d->{NAME} *r2 = r;\n"; + pidl "\t\tif (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {\n"; + pidl "\t\t\tDEBUG(5,(\"function $d->{NAME} replied async\\n\"));\n"; + pidl "\t\t}\n"; pidl "\t\tif (DEBUGLEVEL > 10 && dce_call->fault_code == 0) {\n"; pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($d->{NAME}, NDR_OUT | NDR_SET_VALUES, r2);\n"; pidl "\t\t}\n"; @@ -47,7 +70,6 @@ sub gen_dispatch_switch($) } } - ##################################################################### # produce boilerplate code for a interface sub Boilerplate_Iface($) @@ -91,9 +113,7 @@ static NTSTATUS $name\__op_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_C } *r = talloc_size(mem_ctx, dcerpc_table_$name.calls[opnum].struct_size); - if (!*r) { - return NT_STATUS_NO_MEMORY; - } + NT_STATUS_HAVE_NO_MEMORY(*r); /* unravel the NDR for the packet */ status = dcerpc_table_$name.calls[opnum].ndr_pull(pull, NDR_IN, *r); @@ -111,8 +131,6 @@ static NTSTATUS $name\__op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_C { uint16 opnum = dce_call->pkt.u.request.opnum; - dce_call->fault_code = 0; - switch (opnum) { "; gen_dispatch_switch($data); @@ -132,6 +150,29 @@ pidl " return NT_STATUS_OK; } +static NTSTATUS $name\__op_reply(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r) +{ + uint16 opnum = dce_call->pkt.u.request.opnum; + + switch (opnum) { +"; + gen_reply_switch($data); + +pidl " + default: + dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR; + break; + } + + if (dce_call->fault_code != 0) { + dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN, + &dce_call->pkt.u.request.stub_and_verifier); + return NT_STATUS_NET_WRITE_FAULT; + } + + return NT_STATUS_OK; +} + static NTSTATUS $name\__op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_push *push, void *r) { NTSTATUS status; @@ -147,14 +188,15 @@ static NTSTATUS $name\__op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_C } static const struct dcesrv_interface $name\_interface = { - \"$name\", - $uuid, - $if_version, - $name\__op_bind, - $name\__op_unbind, - $name\__op_ndr_pull, - $name\__op_dispatch, - $name\__op_ndr_push + .name = \"$name\", + .uuid = $uuid, + .if_version = $if_version, + .bind = $name\__op_bind, + .unbind = $name\__op_unbind, + .ndr_pull = $name\__op_ndr_pull, + .dispatch = $name\__op_dispatch, + .reply = $name\__op_reply, + .ndr_push = $name\__op_ndr_push }; "; @@ -237,7 +279,7 @@ NTSTATUS dcerpc_server_$name\_init(void) } ##################################################################### -# parse a parsed IDL structure back into an IDL file +# dcerpc server boilerplate from a parsed IDL structure sub ParseInterface($) { my($interface) = shift; @@ -270,4 +312,3 @@ sub ParseInterface($) } 1; - diff --git a/source4/build/pidl/stub.pm b/source4/build/pidl/stub.pm index d1448d467b..a9c938df63 100644 --- a/source4/build/pidl/stub.pm +++ b/source4/build/pidl/stub.pm @@ -2,6 +2,7 @@ # stub boilerplate generator # Copyright jelmer@samba.org 2004 # Copyright tridge@samba.org 2003 +# Copyright metze@samba.org 2004 # released under the GNU GPL package IdlStub; @@ -39,25 +40,46 @@ sub gen_dispatch_switch($) } else { pidl "\t\tvtable->$d->{NAME}(iface, mem_ctx, r2);\n"; } + pidl "\t\tif (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {\n"; + pidl "\t\t\tDEBUG(5,(\"function $d->{NAME} will reply async\\n\"));\n"; + pidl "\t\t}\n"; + pidl "\t\tbreak;\n\t}\n"; + $count++; + } +} + +##################################################### +# generate the switch statement for function reply +sub gen_reply_switch($) +{ + my $data = shift; + + my $count = 0; + foreach my $d (@{$data}) { + next if ($d->{TYPE} ne "FUNCTION"); + + pidl "\tcase $count: {\n"; + pidl "\t\tstruct $d->{NAME} *r2 = r;\n"; + pidl "\t\tif (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {\n"; + pidl "\t\t\tDEBUG(5,(\"function $d->{NAME} replied async\\n\"));\n"; + pidl "\t\t}\n"; pidl "\t\tif (DEBUGLEVEL > 10 && dce_call->fault_code == 0) {\n"; pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($d->{NAME}, NDR_OUT | NDR_SET_VALUES, r2);\n"; pidl "\t\t}\n"; pidl "\t\tif (dce_call->fault_code != 0) {\n"; - pidl "\t\t\tDEBUG(2,(\"dcerpc_fault 0x%x in $d->{NAME}\\n\", dce_call->fault_code));\n"; + pidl "\t\t\tDEBUG(2,(\"dcerpc_fault %s in $d->{NAME}\\n\", dcerpc_errstr(mem_ctx, dce_call->fault_code)));\n"; pidl "\t\t}\n"; pidl "\t\tbreak;\n\t}\n"; $count++; } } - ##################################################################### # produce boilerplate code for a interface sub Boilerplate_Iface($) { my($interface) = shift; my($data) = $interface->{DATA}; - my $count = 0; my $name = $interface->{NAME}; my $uname = uc $name; my $uuid = util::make_str($interface->{PROPERTIES}->{uuid}); @@ -76,7 +98,7 @@ static NTSTATUS $name\__op_bind(struct dcesrv_call_state *dce_call, const struct static void $name\__op_unbind(struct dcesrv_connection_context *context, const struct dcesrv_interface *iface) { #ifdef DCESRV_INTERFACE_$uname\_UNBIND - DCESRV_INTERFACE_$uname\_UNBIND(context,iface); + DCESRV_INTERFACE_$uname\_UNBIND(context, iface); #else return; #endif @@ -95,11 +117,9 @@ static NTSTATUS $name\__op_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_C } *r = talloc_size(mem_ctx, dcerpc_table_$name.calls[opnum].struct_size); - if (!*r) { - return NT_STATUS_NO_MEMORY; - } + NT_STATUS_HAVE_NO_MEMORY(*r); - /* unravel the NDR for the packet */ + /* unravel the NDR for the packet */ status = dcerpc_table_$name.calls[opnum].ndr_pull(pull, NDR_IN, *r); if (!NT_STATUS_IS_OK(status)) { dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN, @@ -118,8 +138,6 @@ static NTSTATUS $name\__op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_C struct dcom_interface_p *iface = dcom_get_local_iface_p(&ipid); const struct dcom_$name\_vtable *vtable = iface->vtable; - dce_call->fault_code = 0; - switch (opnum) { "; gen_dispatch_switch($data); @@ -139,6 +157,29 @@ pidl " return NT_STATUS_OK; } +static NTSTATUS $name\__op_reply(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r) +{ + uint16 opnum = dce_call->pkt.u.request.opnum; + + switch (opnum) { +"; + gen_reply_switch($data); + +pidl " + default: + dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR; + break; + } + + if (dce_call->fault_code != 0) { + dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN, + &dce_call->pkt.u.request.stub_and_verifier); + return NT_STATUS_NET_WRITE_FAULT; + } + + return NT_STATUS_OK; +} + static NTSTATUS $name\__op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_push *push, void *r) { NTSTATUS status; @@ -154,14 +195,15 @@ static NTSTATUS $name\__op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_C } static const struct dcesrv_interface $name\_interface = { - \"$name\", - $uuid, - $if_version, - $name\__op_bind, - $name\__op_unbind, - $name\__op_ndr_pull, - $name\__op_dispatch, - $name\__op_ndr_push + .name = \"$name\", + .uuid = $uuid, + .if_version = $if_version, + .bind = $name\__op_bind, + .unbind = $name\__op_unbind, + .ndr_pull = $name\__op_ndr_pull, + .dispatch = $name\__op_dispatch, + .reply = $name\__op_reply, + .ndr_push = $name\__op_ndr_push }; "; @@ -243,10 +285,12 @@ NTSTATUS dcerpc_server_$name\_init(void) "; } +##################################################################### +# dcom interface stub from a parsed IDL structure sub ParseInterface($) { my($interface) = shift; - my($data) = $interface->{DATA}; + my($data) = $interface->{DATA}; my $count = 0; $res = ""; -- cgit