summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm245
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);
}