8b5330b50c96c75656465ca269adab984793ba66
[samba.git] / pidl / lib / Parse / Pidl / Samba4 / NDR / Client.pm
1 ###################################################
2 # client calls generator
3 # Copyright tridge@samba.org 2003
4 # Copyright jelmer@samba.org 2005-2006
5 # released under the GNU GPL
6
7 package Parse::Pidl::Samba4::NDR::Client;
8
9 use Parse::Pidl::Samba4 qw(choose_header is_intree);
10 use Parse::Pidl::Util qw(has_property);
11
12 use vars qw($VERSION);
13 $VERSION = '0.01';
14
15 use strict;
16
17 my($res,$res_hdr);
18
19 sub ParseFunction_r_State($$$)
20 {
21         my ($interface, $fn, $name) = @_;
22         my $uname = uc $name;
23
24         if (has_property($fn, "todo")) {
25                 return;
26         }
27
28         $res .= "struct dcerpc_$name\_r_state {\n";
29         $res .= "\tTALLOC_CTX *out_mem_ctx;\n";
30         $res .= "};\n";
31         $res .= "\n";
32         $res .= "static void dcerpc_$name\_r_done(struct tevent_req *subreq);\n";
33         $res .= "\n";
34 }
35
36 sub ParseFunction_r_Send($$$)
37 {
38         my ($interface, $fn, $name) = @_;
39         my $uname = uc $name;
40
41         if (has_property($fn, "todo")) {
42                 return;
43         }
44
45         my $proto = "struct tevent_req *dcerpc_$name\_r_send(TALLOC_CTX *mem_ctx,\n";
46         $proto   .= "\tstruct tevent_context *ev,\n",
47         $proto   .= "\tstruct dcerpc_binding_handle *h,\n",
48         $proto   .= "\tstruct $name *r)";
49
50         $res_hdr .= "\n$proto;\n";
51
52         $res .= "$proto\n{\n";
53
54         $res .= "\tstruct tevent_req *req;\n";
55         $res .= "\tstruct dcerpc_$name\_r_state *state;\n";
56         $res .= "\tstruct tevent_req *subreq;\n";
57         $res .= "\n";
58
59         $res .= "\treq = tevent_req_create(mem_ctx, &state,\n";
60         $res .= "\t\t\t\tstruct dcerpc_$name\_r_state);\n";
61         $res .= "\tif (req == NULL) {\n";
62         $res .= "\t\treturn NULL;\n";
63         $res .= "\t}\n";
64         $res .= "\n";
65
66         my $out_params = 0;
67         foreach (@{$fn->{ELEMENTS}}) {
68                 if (grep(/out/, @{$_->{DIRECTION}})) {
69                         $out_params++;
70                 }
71         }
72
73         my $submem;
74         if ($out_params > 0) {
75                 $res .= "\tstate->out_mem_ctx = talloc_new(state);\n";
76                 $res .= "\tif (tevent_req_nomem(state->out_mem_ctx, req)) {\n";
77                 $res .= "\t\treturn tevent_req_post(req, ev);\n";
78                 $res .= "\t}\n";
79                 $res .= "\n";
80                 $submem = "state->out_mem_ctx";
81         } else {
82                 $res .= "\tstate->out_mem_ctx = NULL;\n";
83                 $submem = "state";
84         }
85
86         $res .= "\tsubreq = dcerpc_binding_handle_call_send(state, ev, h,\n";
87         $res .= "\t\t\tNULL, &ndr_table_$interface->{NAME},\n";
88         $res .= "\t\t\tNDR_$uname, $submem, r);\n";
89         $res .= "\tif (tevent_req_nomem(subreq, req)) {\n";
90         $res .= "\t\treturn tevent_req_post(req, ev);\n";
91         $res .= "\t}\n";
92         $res .= "\ttevent_req_set_callback(subreq, dcerpc_$name\_r_done, req);\n";
93         $res .= "\n";
94
95         $res .= "\treturn req;\n";
96         $res .= "}\n";
97         $res .= "\n";
98 }
99
100 sub ParseFunction_r_Done($$$)
101 {
102         my ($interface, $fn, $name) = @_;
103         my $uname = uc $name;
104
105         if (has_property($fn, "todo")) {
106                 return;
107         }
108
109         my $proto = "static void dcerpc_$name\_r_done(struct tevent_req *subreq)";
110
111         $res .= "$proto\n";
112         $res .= "{\n";
113
114         $res .= "\tstruct tevent_req *req =\n";
115         $res .= "\t\ttevent_req_callback_data(subreq,\n";
116         $res .= "\t\tstruct tevent_req);\n";
117         $res .= "\tNTSTATUS status;\n";
118         $res .= "\n";
119
120         $res .= "\tstatus = dcerpc_binding_handle_call_recv(subreq);\n";
121         $res .= "\tif (!NT_STATUS_IS_OK(status)) {\n";
122         $res .= "\t\ttevent_req_nterror(req, status);\n";
123         $res .= "\t\treturn;\n";
124         $res .= "\t}\n";
125         $res .= "\n";
126
127         $res .= "\ttevent_req_done(req);\n";
128         $res .= "}\n";
129         $res .= "\n";
130 }
131
132 sub ParseFunction_r_Recv($$$)
133 {
134         my ($interface, $fn, $name) = @_;
135         my $uname = uc $name;
136
137         if (has_property($fn, "todo")) {
138                 return;
139         }
140
141         my $proto = "NTSTATUS dcerpc_$name\_r_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx)";
142
143         $res_hdr .= "\n$proto;\n";
144
145         $res .= "$proto\n{\n";
146
147         $res .= "\tstruct dcerpc_$name\_r_state *state =\n";
148         $res .= "\t\ttevent_req_data(req,\n";
149         $res .= "\t\tstruct dcerpc_$name\_r_state);\n";
150         $res .= "\tNTSTATUS status;\n";
151         $res .= "\n";
152
153         $res .= "\tif (tevent_req_is_nterror(req, &status)) {\n";
154         $res .= "\t\ttevent_req_received(req);\n";
155         $res .= "\t\treturn status;\n";
156         $res .= "\t}\n";
157         $res .= "\n";
158
159         $res .= "\ttalloc_steal(mem_ctx, state->out_mem_ctx);\n";
160         $res .= "\n";
161
162         $res .= "\ttevent_req_received(req);\n";
163         $res .= "\treturn NT_STATUS_OK;\n";
164         $res .= "}\n";
165         $res .= "\n";
166 }
167
168 sub ParseFunction_r_Sync($$$)
169 {
170         my ($interface, $fn, $name) = @_;
171         my $uname = uc $name;
172
173         if (has_property($fn, "todo")) {
174                 return;
175         }
176
177         my $proto = "NTSTATUS dcerpc_$name\_r(struct dcerpc_binding_handle *h, TALLOC_CTX *mem_ctx, struct $name *r)";
178
179         $res_hdr .= "\n$proto;\n";
180         $res .= "$proto\n{\n";
181         $res .= "\tNTSTATUS status;\n";
182         $res .= "\n";
183
184         $res .= "\tstatus = dcerpc_binding_handle_call(h,\n";
185         $res .= "\t\t\tNULL, &ndr_table_$interface->{NAME},\n";
186         $res .= "\t\t\tNDR_$uname, mem_ctx, r);\n";
187         $res .= "\n";
188         $res .= "\treturn status;\n";
189
190         $res .= "}\n";
191         $res .= "\n";
192 }
193
194 #####################################################################
195 # parse a function
196 sub ParseFunction($$)
197 {
198         my ($interface, $fn) = @_;
199
200         ParseFunction_r_State($interface, $fn, $fn->{NAME});
201         ParseFunction_r_Send($interface, $fn, $fn->{NAME});
202         ParseFunction_r_Done($interface, $fn, $fn->{NAME});
203         ParseFunction_r_Recv($interface, $fn, $fn->{NAME});
204         ParseFunction_r_Sync($interface, $fn, $fn->{NAME});
205 }
206
207 my %done;
208
209 #####################################################################
210 # parse the interface definitions
211 sub ParseInterface($)
212 {
213         my($interface) = shift;
214
215         $res_hdr .= "#ifndef _HEADER_RPC_$interface->{NAME}\n";
216         $res_hdr .= "#define _HEADER_RPC_$interface->{NAME}\n\n";
217
218         if (defined $interface->{PROPERTIES}->{uuid}) {
219                 $res_hdr .= "extern const struct ndr_interface_table ndr_table_$interface->{NAME};\n";
220         }
221
222         $res .= "/* $interface->{NAME} - client functions generated by pidl */\n\n";
223
224         foreach my $fn (@{$interface->{FUNCTIONS}}) {
225                 next if not defined($fn->{OPNUM});
226                 next if defined($done{$fn->{NAME}});
227                 ParseFunction($interface, $fn);
228                 $done{$fn->{NAME}} = 1;
229         }
230
231         $res_hdr .= "#endif /* _HEADER_RPC_$interface->{NAME} */\n";
232
233         return $res;
234 }
235
236 sub Parse($$$$)
237 {
238         my($ndr,$header,$ndr_header,$client_header) = @_;
239
240         $res = "";
241         $res_hdr = "";
242
243         $res .= "/* client functions auto-generated by pidl */\n";
244         $res .= "\n";
245         if (is_intree()) {
246                 $res .= "#include \"includes.h\"\n";
247         } else {
248                 $res .= "#ifndef _GNU_SOURCE\n";
249                 $res .= "#define _GNU_SOURCE\n";
250                 $res .= "#endif\n";
251                 $res .= "#include <stdio.h>\n";
252                 $res .= "#include <stdbool.h>\n";
253                 $res .= "#include <stdlib.h>\n";
254                 $res .= "#include <stdint.h>\n";
255                 $res .= "#include <stdarg.h>\n";
256                 $res .= "#include <core/ntstatus.h>\n";
257         }
258         $res .= "#include <tevent.h>\n";
259         $res .= choose_header("lib/util/tevent_ntstatus.h", "util/tevent_ntstatus.h")."\n";
260         $res .= "#include \"$ndr_header\"\n";
261         $res .= "#include \"$client_header\"\n";
262         $res .= "\n";
263
264         $res_hdr .= choose_header("librpc/rpc/dcerpc.h", "dcerpc.h")."\n";
265         $res_hdr .= "#include \"$header\"\n";
266
267         foreach my $x (@{$ndr}) {
268                 ($x->{TYPE} eq "INTERFACE") && ParseInterface($x);
269         }
270
271         return ($res,$res_hdr);
272 }
273
274 1;