2 * Unix SMB/CIFS implementation.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include "source3/include/includes.h"
19 #include "source3/torture/proto.h"
20 #include "source3/libsmb/libsmb.h"
21 #include "librpc/gen_ndr/ndr_spoolss_c.h"
22 #include "lib/util/tevent_ntstatus.h"
23 #include "source3/rpc_client/rpc_client.h"
24 #include "source3/rpc_client/cli_pipe.h"
25 #include "libcli/smb/smbXcli_base.h"
27 extern int torture_nprocs
;
28 extern int torture_numops
;
30 struct rpc_scale_one_state
{
31 struct tevent_context
*ev
;
32 struct cli_state
*cli
;
33 size_t num_iterations
;
34 struct rpc_pipe_client
*rpccli
;
37 uint32_t num_printers
;
38 union spoolss_PrinterInfo
*printers
;
41 static void rpc_scale_one_opened(struct tevent_req
*subreq
);
42 static void rpc_scale_one_bound(struct tevent_req
*subreq
);
43 static void rpc_scale_one_listed(struct tevent_req
*subreq
);
45 static struct tevent_req
*rpc_scale_one_send(
47 struct tevent_context
*ev
,
48 struct cli_state
*cli
,
49 size_t num_iterations
)
51 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
52 struct rpc_scale_one_state
*state
= NULL
;
54 req
= tevent_req_create(mem_ctx
, &state
, struct rpc_scale_one_state
);
60 state
->num_iterations
= num_iterations
;
62 subreq
= rpc_pipe_open_np_send(
63 state
, ev
, cli
, &ndr_table_spoolss
);
64 if (tevent_req_nomem(subreq
, req
)) {
65 return tevent_req_post(req
, ev
);
67 tevent_req_set_callback(subreq
, rpc_scale_one_opened
, req
);
71 static void rpc_scale_one_opened(struct tevent_req
*subreq
)
73 struct tevent_req
*req
= tevent_req_callback_data(
74 subreq
, struct tevent_req
);
75 struct rpc_scale_one_state
*state
= tevent_req_data(
76 req
, struct rpc_scale_one_state
);
77 struct pipe_auth_data
*auth
= NULL
;
80 status
= rpc_pipe_open_np_recv(subreq
, state
, &state
->rpccli
);
82 if (tevent_req_nterror(req
, status
)) {
86 status
= rpccli_anon_bind_data(state
, &auth
);
87 if (tevent_req_nterror(req
, status
)) {
91 subreq
= rpc_pipe_bind_send(state
, state
->ev
, state
->rpccli
, auth
);
92 if (tevent_req_nomem(subreq
, req
)) {
95 tevent_req_set_callback(subreq
, rpc_scale_one_bound
, req
);
98 static void rpc_scale_one_bound(struct tevent_req
*subreq
)
100 struct tevent_req
*req
= tevent_req_callback_data(
101 subreq
, struct tevent_req
);
102 struct rpc_scale_one_state
*state
= tevent_req_data(
103 req
, struct rpc_scale_one_state
);
107 status
= rpc_pipe_bind_recv(subreq
);
108 if (tevent_req_nterror(req
, status
)) {
112 server
= talloc_asprintf(
115 smbXcli_conn_remote_name(state
->cli
->conn
));
116 if (tevent_req_nomem(server
, req
)) {
119 state
->buffer
= data_blob_talloc(state
, NULL
, 4096);
120 if (tevent_req_nomem(state
->buffer
.data
, req
)) {
124 subreq
= dcerpc_spoolss_EnumPrinters_send(
127 state
->rpccli
->binding_handle
,
132 state
->buffer
.length
,
133 &state
->num_printers
,
136 if (tevent_req_nomem(subreq
, req
)) {
139 tevent_req_set_callback(subreq
, rpc_scale_one_listed
, req
);
142 static void rpc_scale_one_listed(struct tevent_req
*subreq
)
144 struct tevent_req
*req
= tevent_req_callback_data(
145 subreq
, struct tevent_req
);
146 struct rpc_scale_one_state
*state
= tevent_req_data(
147 req
, struct rpc_scale_one_state
);
151 status
= dcerpc_spoolss_EnumPrinters_recv(subreq
, state
, &result
);
152 if (tevent_req_nterror(req
, status
)) {
156 if (!W_ERROR_IS_OK(result
)) {
157 status
= werror_to_ntstatus(result
);
158 tevent_req_nterror(req
, status
);
163 * This will trigger a sync close. Making that async will be a
164 * lot of effort, and even with this being sync this test is
167 TALLOC_FREE(state
->rpccli
);
169 state
->num_iterations
-= 1;
171 if (state
->num_iterations
== 0) {
172 tevent_req_done(req
);
176 subreq
= rpc_pipe_open_np_send(
177 state
, state
->ev
, state
->cli
, &ndr_table_spoolss
);
178 if (tevent_req_nomem(subreq
, req
)) {
181 tevent_req_set_callback(subreq
, rpc_scale_one_opened
, req
);
184 static NTSTATUS
rpc_scale_one_recv(struct tevent_req
*req
)
186 return tevent_req_simple_recv_ntstatus(req
);
189 struct rpc_scale_state
{
194 static void rpc_scale_done(struct tevent_req
*subreq
);
196 static struct tevent_req
*rpc_scale_send(
198 struct tevent_context
*ev
,
199 struct cli_state
**clis
)
201 struct tevent_req
*req
= NULL
;
202 struct rpc_scale_state
*state
= NULL
;
203 size_t i
, num_clis
= talloc_array_length(clis
);
205 req
= tevent_req_create(mem_ctx
, &state
, struct rpc_scale_state
);
209 state
->num_reqs
= num_clis
;
211 for (i
=0; i
<num_clis
; i
++) {
212 struct tevent_req
*subreq
= rpc_scale_one_send(
213 state
, ev
, clis
[i
], torture_numops
);
214 if (tevent_req_nomem(subreq
, req
)) {
215 return tevent_req_post(req
, ev
);
217 tevent_req_set_callback(subreq
, rpc_scale_done
, req
);
222 static void rpc_scale_done(struct tevent_req
*subreq
)
224 struct tevent_req
*req
= tevent_req_callback_data(
225 subreq
, struct tevent_req
);
226 struct rpc_scale_state
*state
= tevent_req_data(
227 req
, struct rpc_scale_state
);
230 status
= rpc_scale_one_recv(subreq
);
232 if (tevent_req_nterror(req
, status
)) {
238 if (state
->done
== state
->num_reqs
) {
239 tevent_req_done(req
);
243 static NTSTATUS
rpc_scale_recv(struct tevent_req
*req
)
245 return tevent_req_simple_recv_ntstatus(req
);
248 bool run_rpc_scale(int dummy
)
250 TALLOC_CTX
*frame
= talloc_stackframe();
251 struct cli_state
**clis
= NULL
;
252 struct tevent_req
*req
= NULL
;
253 struct tevent_context
*ev
= NULL
;
254 bool ok
, result
= false;
258 clis
= talloc_zero_array(
259 talloc_tos(), struct cli_state
*, torture_nprocs
);
261 fprintf(stderr
, "talloc failed\n");
265 for (i
=0; i
<torture_nprocs
; i
++) {
266 ok
= torture_open_connection_flags(&clis
[i
], i
, 0);
268 fprintf(stderr
, "could not open connection %d\n", i
);
273 ev
= samba_tevent_context_init(talloc_tos());
278 req
= rpc_scale_send(talloc_tos(), ev
, clis
);
283 ok
= tevent_req_poll_ntstatus(req
, ev
, &status
);
286 "rpc_scale_send failed: %s\n",
291 status
= rpc_scale_recv(req
);
292 if (!NT_STATUS_IS_OK(status
)) {
293 fprintf(stderr
, "rpc_scale failed: %s\n", nt_errstr(status
));