pidl:NDR/Client.pm: generate pipe pull/push functions
authorStefan Metzmacher <metze@samba.org>
Tue, 5 Oct 2010 18:58:15 +0000 (20:58 +0200)
committerStefan Metzmacher <metze@samba.org>
Tue, 4 Jun 2019 11:14:55 +0000 (13:14 +0200)
Signed-off-by: Stefan Metzmacher <metze@samba.org>
pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm

index 734e86dd1833a86780920cfc2d04a97af78b2318..8e2e0656f5c253b74b3135c70b786b729b40a21c 100644 (file)
@@ -813,6 +813,379 @@ sub ParseFunction($$$)
        $self->pidl_hdr("");
 }
 
+sub ParsePipeCreate($$$)
+{
+       my ($self, $t, $cname) = @_;
+
+       $self->pidl_both("/* $t->{NAME} */");
+
+       $self->pidl_hdr("struct $t->{NAME};");
+       $self->pidl("struct $t->{NAME} {");
+       $self->indent;
+       $self->pidl("struct dcerpc_pipe_handle_connection *pc;");
+       $self->deindent;
+       $self->pidl("};");
+       $self->pidl("");
+
+       my $proto = "struct $t->{NAME} *dcerpc_$t->{NAME}\_create(TALLOC_CTX *mem_ctx)";
+
+       $self->pidl_hdr("$proto;");
+       $self->pidl("$proto");
+       $self->pidl("{");
+       $self->indent;
+
+       $self->pidl("struct $t->{NAME} *p;");
+       $self->pidl("");
+
+       $self->pidl("p = talloc_zero(mem_ctx, struct $t->{NAME});");
+       $self->pidl("if (p == NULL) {");
+       $self->indent;
+       $self->pidl("return NULL;");
+       $self->deindent;
+       $self->pidl("}");
+       $self->pidl("");
+
+       my $cname = "$t->{NAME}_chunk";
+
+       $self->pidl("/* the pipe is disconnected by default */");
+       $self->pidl("p->pc = dcerpc_pipe_handle_connection_create(p,");
+       $self->pidl("\t\t\t\"$cname\",");
+       $self->pidl("\t\t\tsizeof(struct $cname));");
+       $self->pidl("if (p->pc == NULL) {");
+       $self->indent;
+       $self->pidl("TALLOC_FREE(p);");
+       $self->pidl("return NULL;");
+       $self->deindent;
+       $self->pidl("}");
+       $self->pidl("");
+
+       $self->pidl("return p;");
+       $self->deindent;
+       $self->pidl("}");
+       $self->pidl("");
+}
+
+sub ParsePipeChunkPush_State($$$)
+{
+       my ($self, $t, $cname) = @_;
+
+       my $state_str = "struct dcerpc_$cname\_push_state";
+       my $done_fn = "dcerpc_$cname\_push_done";
+
+       $self->pidl("$state_str {");
+       $self->indent;
+       $self->pidl("uint8_t dummy;");
+       $self->deindent;
+       $self->pidl("};");
+       $self->pidl("");
+
+       $self->pidl("static void $done_fn(struct tevent_req *subreq);");
+       $self->pidl("");
+}
+
+sub ParsePipeChunkPush_Send($$$)
+{
+       my ($self, $t, $cname) = @_;
+
+       my $fn_args = "";
+       my $state_str = "struct dcerpc_$cname\_push_state";
+       my $done_fn = "dcerpc_$cname\_push_done";
+       my $fn_str = "struct tevent_req *dcerpc_$cname\_push_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 $t->{NAME} *p";
+       $fn_args .= ",\n" . $pad . "const struct $cname *chunk";
+
+       $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("");
+
+       $self->pidl("subreq = dcerpc_pipe_handle_push_send(state, ev,");
+       $self->pidl("\t\t\tp->pc, chunk);");
+       $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("");
+
+       $self->pidl("return req;");
+       $self->deindent;
+       $self->pidl("}");
+       $self->pidl("");
+}
+
+sub ParsePipeChunkPush_Done($$$)
+{
+       my ($self, $t, $cname) = @_;
+
+       my $fn_args = "";
+       my $state_str = "struct dcerpc_$cname\_push_state";
+       my $fn_str = "static void dcerpc_$cname\_push_done";
+       my $pad = genpad($fn_str);
+
+       $fn_args .= "struct tevent_req *subreq";
+
+       $self->pidl("$fn_str($fn_args)");
+       $self->pidl("{");
+       $self->indent;
+       $self->pidl("struct tevent_req *req =");
+       $self->pidl("\ttevent_req_callback_data(subreq,");
+       $self->pidl("\tstruct tevent_req);");
+       # unused
+       #$self->pidl("$state_str *state =");
+       #$self->pidl("\ttevent_req_data(req,");
+       #$self->pidl("\t$state_str);");
+       $self->pidl("NTSTATUS status;");
+       $self->pidl("");
+
+       $self->pidl("status = dcerpc_pipe_handle_push_recv(subreq);");
+       $self->pidl("TALLOC_FREE(subreq);");
+       $self->pidl("if (tevent_req_nterror(req, status)) {");
+       $self->indent;
+       $self->pidl("return;");
+       $self->deindent;
+       $self->pidl("}");
+       $self->pidl("");
+
+       $self->pidl("tevent_req_done(req);");
+       $self->deindent;
+       $self->pidl("}");
+       $self->pidl("");
+}
+
+sub ParsePipeChunkPush_Recv($$$)
+{
+       my ($self, $t, $cname) = @_;
+
+       my $fn_args = "";
+       my $state_str = "struct dcerpc_$cname\_push_state";
+       my $fn_str = "NTSTATUS dcerpc_$cname\_push_recv";
+       my $pad = genpad($fn_str);
+
+       $fn_args .= "struct tevent_req *req";
+
+       $self->fn_declare("$fn_str($fn_args)");
+       $self->pidl("{");
+       $self->indent;
+       $self->pidl("$state_str *state =");
+       $self->pidl("\ttevent_req_data(req,");
+       $self->pidl("\t$state_str);");
+       $self->pidl("NTSTATUS status;");
+       $self->pidl("");
+
+       $self->pidl("if (tevent_req_is_nterror(req, &status)) {");
+       $self->indent;
+       $self->pidl("/*");
+       $self->pidl(" * We want the tevent_req_data() protection,");
+       $self->pidl(" * but don't need 'state', so just pretend we use it");
+       $self->pidl(" * in order to avoid compiler warnings.");
+       $self->pidl(" */");
+       $self->pidl("state->dummy = 0;");
+       $self->pidl("tevent_req_received(req);");
+       $self->pidl("return status;");
+       $self->deindent;
+       $self->pidl("}");
+       $self->pidl("");
+
+       $self->pidl("tevent_req_received(req);");
+       $self->pidl("return NT_STATUS_OK;");
+       $self->deindent;
+       $self->pidl("}");
+       $self->pidl("");
+}
+
+sub ParsePipeChunkPull_State($$$)
+{
+       my ($self, $t, $cname) = @_;
+
+       my $state_str = "struct dcerpc_$cname\_pull_state";
+       my $done_fn = "dcerpc_$cname\_pull_done";
+
+       $self->pidl("$state_str {");
+       $self->indent;
+       $self->pidl("struct $cname *chunk;");
+       $self->deindent;
+       $self->pidl("};");
+       $self->pidl("");
+
+       $self->pidl("static void $done_fn(struct tevent_req *subreq);");
+       $self->pidl("");
+}
+
+sub ParsePipeChunkPull_Send($$$)
+{
+       my ($self, $t, $cname) = @_;
+
+       my $fn_args = "";
+       my $state_str = "struct dcerpc_$cname\_pull_state";
+       my $done_fn = "dcerpc_$cname\_pull_done";
+       my $fn_str = "struct tevent_req *dcerpc_$cname\_pull_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 $t->{NAME} *p";
+
+       $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->chunk = talloc_zero(state, struct $cname);");
+       $self->pidl("if (tevent_req_nomem(state->chunk, req)) {");
+       $self->indent;
+       $self->pidl("return tevent_req_post(req, ev);");
+       $self->deindent;
+       $self->pidl("}");
+       $self->pidl("");
+
+       $self->pidl("subreq = dcerpc_pipe_handle_pull_send(state, ev,");
+       $self->pidl("\t\t\tp->pc, state->chunk, state->chunk);");
+       $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("");
+
+       $self->pidl("return req;");
+       $self->deindent;
+       $self->pidl("}");
+       $self->pidl("");
+}
+
+sub ParsePipeChunkPull_Done($$$)
+{
+       my ($self, $t, $cname) = @_;
+
+       my $fn_args = "";
+       my $state_str = "struct dcerpc_$cname\_pull_state";
+       my $fn_str = "static void dcerpc_$cname\_pull_done";
+       my $pad = genpad($fn_str);
+
+       $fn_args .= "struct tevent_req *subreq";
+
+       $self->pidl("$fn_str($fn_args)");
+       $self->pidl("{");
+       $self->indent;
+       $self->pidl("struct tevent_req *req =");
+       $self->pidl("\ttevent_req_callback_data(subreq,");
+       $self->pidl("\tstruct tevent_req);");
+       # unused
+       #$self->pidl("$state_str *state =");
+       #$self->pidl("\ttevent_req_data(req,");
+       #$self->pidl("\t$state_str);");
+       $self->pidl("NTSTATUS status;");
+       $self->pidl("");
+
+       $self->pidl("status = dcerpc_pipe_handle_pull_recv(subreq);");
+       $self->pidl("TALLOC_FREE(subreq);");
+       $self->pidl("if (tevent_req_nterror(req, status)) {");
+       $self->indent;
+       $self->pidl("return;");
+       $self->deindent;
+       $self->pidl("}");
+       $self->pidl("");
+
+       $self->pidl("tevent_req_done(req);");
+       $self->deindent;
+       $self->pidl("}");
+       $self->pidl("");
+}
+
+sub ParsePipeChunkPull_Recv($$$)
+{
+       my ($self, $t, $cname) = @_;
+
+       my $fn_args = "";
+       my $state_str = "struct dcerpc_$cname\_pull_state";
+       my $fn_str = "NTSTATUS dcerpc_$cname\_pull_recv";
+       my $pad = genpad($fn_str);
+
+       $fn_args .= "struct tevent_req *req";
+       $fn_args .= ",\n" . $pad . "TALLOC_CTX *mem_ctx";
+       $fn_args .= ",\n" . $pad . "struct $cname **chunk";
+
+       $self->fn_declare("$fn_str($fn_args)");
+       $self->pidl("{");
+       $self->indent;
+       $self->pidl("$state_str *state =");
+       $self->pidl("\ttevent_req_data(req,");
+       $self->pidl("\t$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("*chunk = talloc_move(mem_ctx, &state->chunk);");
+       $self->pidl("");
+
+       $self->pidl("tevent_req_received(req);");
+       $self->pidl("return NT_STATUS_OK;");
+       $self->deindent;
+       $self->pidl("}");
+       $self->pidl("");
+}
+
+sub ParsePipe($$)
+{
+       my ($self, $t) = @_;
+
+       my $pipe = $t;
+       $pipe = $t->{DATA} if ($t->{TYPE} eq "TYPEDEF");
+       my $struct = $pipe->{DATA};
+
+       my $name = "$struct->{NAME}";
+
+       $self->ParsePipeCreate($t, $name);
+
+       $self->ParsePipeChunkPush_State($t, $name);
+       $self->ParsePipeChunkPush_Send($t, $name);
+       $self->ParsePipeChunkPush_Done($t, $name);
+       $self->ParsePipeChunkPush_Recv($t, $name);
+
+       $self->ParsePipeChunkPull_State($t, $name);
+       $self->ParsePipeChunkPull_Send($t, $name);
+       $self->ParsePipeChunkPull_Done($t, $name);
+       $self->ParsePipeChunkPull_Recv($t, $name);
+       $self->pidl_both("");
+}
+
 my %done;
 
 #####################################################################
@@ -834,6 +1207,13 @@ sub ParseInterface($$)
        $self->pidl("/* $if->{NAME} - client functions generated by pidl */");
        $self->pidl("");
 
+       foreach my $t (reverse @{$if->{TYPES}}) {
+               next unless Parse::Pidl::Typelist::typeIs($t, "PIPE");
+
+               $self->ParsePipe($t);
+               $done{$t->{NAME}} = 1;
+       }
+
        foreach my $fn (@{$if->{FUNCTIONS}}) {
                next if defined($done{$fn->{NAME}});
                next if has_property($fn, "noopnum");