eb1f1d45871cd2270550b46ce4a6ee48b8673ebf
[metze/samba/wip.git] / source3 / torture / test_async_echo.c
1 /*
2    Unix SMB/CIFS implementation.
3    Run the async echo responder
4    Copyright (C) Volker Lendecke 2010
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "torture/proto.h"
22 #include "libsmb/libsmb.h"
23 #include "async_smb.h"
24 #include "rpc_client/cli_pipe.h"
25 #include "librpc/gen_ndr/ndr_echo_c.h"
26
27 static void rpccli_sleep_done(struct tevent_req *req)
28 {
29         int *done = (int *)tevent_req_callback_data_void(req);
30         NTSTATUS status;
31         uint32_t result = UINT32_MAX;
32
33         status = dcerpc_echo_TestSleep_recv(req, talloc_tos(), &result);
34         TALLOC_FREE(req);
35         printf("sleep returned %s, %d\n", nt_errstr(status), (int)result);
36         *done -= 1;
37 }
38
39 static void cli_echo_done(struct tevent_req *req)
40 {
41         int *done = (int *)tevent_req_callback_data_void(req);
42         NTSTATUS status;
43
44         status = cli_echo_recv(req);
45         TALLOC_FREE(req);
46         printf("echo returned %s\n", nt_errstr(status));
47         *done -= 1;
48 }
49
50 static void write_andx_done(struct tevent_req *req)
51 {
52         int *done = (int *)tevent_req_callback_data_void(req);
53         NTSTATUS status;
54         size_t written;
55
56         status = cli_write_andx_recv(req, &written);
57         TALLOC_FREE(req);
58         printf("cli_write_andx returned %s\n", nt_errstr(status));
59         *done -= 1;
60 }
61
62 bool run_async_echo(int dummy)
63 {
64         struct cli_state *cli = NULL;
65         struct rpc_pipe_client *p;
66         struct dcerpc_binding_handle *b;
67         struct tevent_context *ev;
68         struct tevent_req *req;
69         NTSTATUS status;
70         bool ret = false;
71         int i, num_reqs;
72         uint8_t buf[65536];
73
74         printf("Starting ASYNC_ECHO\n");
75
76         ev = tevent_context_init(talloc_tos());
77         if (ev == NULL) {
78                 printf("tevent_context_init failed\n");
79                 goto fail;
80         }
81
82         if (!torture_open_connection(&cli, 0)) {
83                 printf("torture_open_connection failed\n");
84                 goto fail;
85         }
86         status = cli_rpc_pipe_open_noauth(cli, &ndr_table_rpcecho.syntax_id,
87                                           &p);
88         if (!NT_STATUS_IS_OK(status)) {
89                 printf("Could not open echo pipe: %s\n", nt_errstr(status));
90                 goto fail;
91         }
92         b = p->binding_handle;
93
94         num_reqs = 0;
95
96         req = dcerpc_echo_TestSleep_send(ev, ev, b, 15);
97         if (req == NULL) {
98                 printf("rpccli_echo_TestSleep_send failed\n");
99                 goto fail;
100         }
101         tevent_req_set_callback(req, rpccli_sleep_done, &num_reqs);
102         num_reqs += 1;
103
104         /* Wait until the rpc operation arrives at the smb layer */
105         while (tevent_req_is_in_progress(req) &&
106                !cli_has_async_calls(cli)) {
107                 if (tevent_loop_once(ev) != 0) {
108                         printf("tevent_loop_once failed\n");
109                         goto fail;
110                 }
111         }
112
113         req = cli_echo_send(ev, ev, cli, 1, data_blob_const("hello", 5));
114         if (req == NULL) {
115                 printf("cli_echo_send failed\n");
116                 goto fail;
117         }
118         tevent_req_set_callback(req, cli_echo_done, &num_reqs);
119         num_reqs += 1;
120
121         memset(buf, 0, sizeof(buf));
122
123         for (i=0; i<10; i++) {
124                 req = cli_write_andx_send(ev, ev, cli, 4711, 0, buf, 0,
125                                           sizeof(buf));
126                 if (req == NULL) {
127                         printf("cli_write_andx_send failed\n");
128                         goto fail;
129                 }
130                 tevent_req_set_callback(req, write_andx_done, &num_reqs);
131                 num_reqs += 1;
132
133                 req = cli_echo_send(ev, ev, cli, 1,
134                                     data_blob_const("hello", 5));
135                 if (req == NULL) {
136                         printf("cli_echo_send failed\n");
137                         goto fail;
138                 }
139                 tevent_req_set_callback(req, cli_echo_done, &num_reqs);
140                 num_reqs += 1;
141         }
142
143         while (num_reqs > 0) {
144                 if (tevent_loop_once(ev) != 0) {
145                         printf("tevent_loop_once failed\n");
146                         goto fail;
147                 }
148         }
149
150         TALLOC_FREE(p);
151
152         ret = true;
153 fail:
154         if (cli != NULL) {
155                 torture_close_connection(cli);
156         }
157         return ret;
158 }