diff options
-rw-r--r-- | pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm b/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm index 34480ff8dac..e2fc54a77f4 100644 --- a/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm +++ b/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm @@ -122,6 +122,246 @@ sub ParseOutputArgument($$$;$$) } } +sub ParseFunctionAsyncState($$$) +{ + my ($self, $if, $fn) = @_; + + my $state_str = "struct rpccli_$fn->{NAME}_state"; + my $done_fn = "rpccli_$fn->{NAME}_done"; + + $self->pidl("$state_str {"); + $self->indent; + $self->pidl("struct $fn->{NAME} orig;"); + $self->pidl("struct $fn->{NAME} tmp;"); + $self->pidl("TALLOC_CTX *out_mem_ctx;"); + $self->pidl("NTSTATUS (*dispatch_recv)(struct tevent_req *req, TALLOC_CTX *mem_ctx);"); + $self->deindent; + $self->pidl("};"); + $self->pidl(""); + $self->pidl("static void $done_fn(struct tevent_req *subreq);"); + $self->pidl(""); +} + +sub ParseFunctionAsyncSend($$$) +{ + my ($self, $if, $fn) = @_; + + my $fn_args = ""; + my $uif = uc($if); + my $ufn = "NDR_".uc($fn->{NAME}); + my $state_str = "struct rpccli_$fn->{NAME}_state"; + my $done_fn = "rpccli_$fn->{NAME}_done"; + my $out_mem_ctx = "rpccli_$fn->{NAME}_out_memory"; + my $fn_str = "struct tevent_req *rpccli_$fn->{NAME}_send"; + my $pad = genpad($fn_str); + + $fn_args .= "TALLOC_CTX *mem_ctx"; + $fn_args .= ",\n" . $pad . "struct tevent_context *ev"; + $fn_args .= ",\n" . $pad . "struct rpc_pipe_client *cli"; + + foreach (@{$fn->{ELEMENTS}}) { + my $dir = ElementDirection($_); + my $prop = HeaderProperties($_->{PROPERTIES}, ["in", "out"]); + $fn_args .= ",\n" . $pad . DeclLong($_, "_") . " /* $dir $prop */"; + } + + $self->fn_declare("$fn_str($fn_args)"); + $self->pidl("{"); + $self->indent; + $self->pidl("struct tevent_req *req;"); + $self->pidl("$state_str *state;"); + $self->pidl("struct tevent_req *subreq;"); + $self->pidl(""); + $self->pidl("req = tevent_req_create(mem_ctx, &state,"); + $self->pidl("\t\t\t$state_str);"); + $self->pidl("if (req == NULL) {"); + $self->indent; + $self->pidl("return NULL;"); + $self->deindent; + $self->pidl("}"); + $self->pidl("state->out_mem_ctx = NULL;"); + $self->pidl("state->dispatch_recv = cli->dispatch_recv;"); + $self->pidl(""); + + $self->pidl("/* In parameters */"); + foreach (@{$fn->{ELEMENTS}}) { + if (grep(/in/, @{$_->{DIRECTION}})) { + $self->pidl("state->orig.in.$_->{NAME} = _$_->{NAME};"); + } + } + $self->pidl(""); + + my $out_params = 0; + $self->pidl("/* Out parameters */"); + foreach (@{$fn->{ELEMENTS}}) { + if (grep(/out/, @{$_->{DIRECTION}})) { + $self->pidl("state->orig.out.$_->{NAME} = _$_->{NAME};"); + $out_params++; + } + } + $self->pidl(""); + + if (defined($fn->{RETURN_TYPE})) { + $self->pidl("/* Result */"); + $self->pidl("ZERO_STRUCT(state->orig.out.result);"); + $self->pidl(""); + } + + $self->pidl("if (DEBUGLEVEL >= 10) {"); + $self->indent; + $self->pidl("NDR_PRINT_IN_DEBUG($fn->{NAME}, &state->orig);"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + + if ($out_params > 0) { + $self->pidl("state->out_mem_ctx = talloc_named_const(state, 0,"); + $self->pidl("\t\t \"$out_mem_ctx\");"); + $self->pidl("if (tevent_req_nomem(state->out_mem_ctx, req)) {"); + $self->indent; + $self->pidl("return tevent_req_post(req, ev);"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + } + + $self->pidl("/* make a temporary copy, that we pass to the dispatch function */"); + $self->pidl("state->tmp = state->orig;"); + $self->pidl(""); + + $self->pidl("subreq = cli->dispatch_send(state, ev, cli,"); + $self->pidl("\t\t\t &ndr_table_$if,"); + $self->pidl("\t\t\t $ufn,"); + $self->pidl("\t\t\t &state->tmp);"); + $self->pidl("if (tevent_req_nomem(subreq, req)) {"); + $self->indent; + $self->pidl("return tevent_req_post(req, ev);"); + $self->deindent; + $self->pidl("}"); + $self->pidl("tevent_req_set_callback(subreq, $done_fn, req);"); + $self->pidl("return req;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); +} + +sub ParseFunctionAsyncDone($$$) +{ + my ($self, $if, $fn) = @_; + + my $state_str = "struct rpccli_$fn->{NAME}_state"; + my $done_fn = "rpccli_$fn->{NAME}_done"; + + $self->pidl("static void $done_fn(struct tevent_req *subreq)"); + $self->pidl("{"); + $self->indent; + $self->pidl("struct tevent_req *req = tevent_req_callback_data("); + $self->pidl("\tsubreq, struct tevent_req);"); + $self->pidl("$state_str *state = tevent_req_data("); + $self->pidl("\treq, $state_str);"); + $self->pidl("NTSTATUS status;"); + $self->pidl("TALLOC_CTX *mem_ctx;"); + $self->pidl(""); + + $self->pidl("if (state->out_mem_ctx) {"); + $self->indent; + $self->pidl("mem_ctx = state->out_mem_ctx;"); + $self->deindent; + $self->pidl("} else {"); + $self->indent; + $self->pidl("mem_ctx = state;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("status = state->dispatch_recv(subreq, mem_ctx);"); + $self->pidl("TALLOC_FREE(subreq);"); + $self->pidl("if (!NT_STATUS_IS_OK(status)) {"); + $self->indent; + $self->pidl("tevent_req_nterror(req, status);"); + $self->pidl("return;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("/* Copy out parameters */"); + foreach my $e (@{$fn->{ELEMENTS}}) { + next unless (grep(/out/, @{$e->{DIRECTION}})); + + $self->ParseOutputArgument($fn, $e, "state->tmp.", "state->orig.out."); + } + $self->pidl(""); + + if (defined($fn->{RETURN_TYPE})) { + $self->pidl("/* Copy result */"); + $self->pidl("state->orig.out.result = state->tmp.out.result;"); + $self->pidl(""); + } + + $self->pidl("/* Reset temporary structure */"); + $self->pidl("ZERO_STRUCT(state->tmp);"); + $self->pidl(""); + + $self->pidl("if (DEBUGLEVEL >= 10) {"); + $self->indent; + $self->pidl("NDR_PRINT_OUT_DEBUG($fn->{NAME}, &state->orig);"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("tevent_req_done(req);"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); +} + +sub ParseFunctionAsyncRecv($$$) +{ + my ($self, $if, $fn) = @_; + + my $fn_args = ""; + my $state_str = "struct rpccli_$fn->{NAME}_state"; + my $fn_str = "NTSTATUS rpccli_$fn->{NAME}_recv"; + my $pad = genpad($fn_str); + + $fn_args .= "struct tevent_req *req,\n" . $pad . "TALLOC_CTX *mem_ctx"; + + if (defined($fn->{RETURN_TYPE})) { + $fn_args .= ",\n" . $pad . "$fn->{RETURN_TYPE} *result"; + } + + $self->fn_declare("$fn_str($fn_args)"); + $self->pidl("{"); + $self->indent; + $self->pidl("$state_str *state = tevent_req_data("); + $self->pidl("\treq, $state_str);"); + $self->pidl("NTSTATUS status;"); + $self->pidl(""); + $self->pidl("if (tevent_req_is_nterror(req, &status)) {"); + $self->indent; + $self->pidl("tevent_req_received(req);"); + $self->pidl("return status;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); + + $self->pidl("/* Steal possbile out parameters to the callers context */"); + $self->pidl("talloc_steal(mem_ctx, state->out_mem_ctx);"); + $self->pidl(""); + + if (defined($fn->{RETURN_TYPE})) { + $self->pidl("/* Return result */"); + $self->pidl("*result = state->orig.out.result;"); + $self->pidl(""); + } + + $self->pidl("tevent_req_received(req);"); + $self->pidl("return NT_STATUS_OK;"); + $self->deindent; + $self->pidl("}"); + $self->pidl(""); +} + sub ParseFunctionSync($$$) { my ($self, $if, $fn) = @_; @@ -227,6 +467,11 @@ sub ParseFunction($$$) { my ($self, $if, $fn) = @_; + $self->ParseFunctionAsyncState($if, $fn); + $self->ParseFunctionAsyncSend($if, $fn); + $self->ParseFunctionAsyncDone($if, $fn); + $self->ParseFunctionAsyncRecv($if, $fn); + $self->ParseFunctionSync($if, $fn); } |