FreeRDP
Loading...
Searching...
No Matches
TestConnect.c
1#include <winpr/sysinfo.h>
2#include <winpr/path.h>
3#include <winpr/crypto.h>
4#include <winpr/pipe.h>
5
6#include <freerdp/freerdp.h>
7#include <freerdp/gdi/gdi.h>
8#include <freerdp/client/cmdline.h>
9
10static HANDLE s_sync = NULL;
11
12static int runInstance(int argc, char* argv[], freerdp** inst, DWORD timeout)
13{
14 int rc = -1;
15 RDP_CLIENT_ENTRY_POINTS clientEntryPoints = { 0 };
16 rdpContext* context = NULL;
17
18 clientEntryPoints.Size = sizeof(RDP_CLIENT_ENTRY_POINTS);
19 clientEntryPoints.Version = RDP_CLIENT_INTERFACE_VERSION;
20 clientEntryPoints.ContextSize = sizeof(rdpContext);
21 context = freerdp_client_context_new(&clientEntryPoints);
22
23 if (!context)
24 goto finish;
25
26 if (inst)
27 *inst = context->instance;
28
29 context->instance->ChooseSmartcard = NULL;
30 context->instance->PresentGatewayMessage = NULL;
31 context->instance->LogonErrorInfo = NULL;
32 context->instance->AuthenticateEx = NULL;
33 context->instance->VerifyCertificateEx = NULL;
34 context->instance->VerifyChangedCertificateEx = NULL;
35
36 if (!freerdp_settings_set_bool(context->settings, FreeRDP_DeactivateClientDecoding, TRUE))
37 return FALSE;
38
39 if (freerdp_client_settings_parse_command_line(context->settings, argc, argv, FALSE) < 0)
40 goto finish;
41
42 if (!freerdp_settings_set_uint32(context->settings, FreeRDP_TcpConnectTimeout, timeout))
43 goto finish;
44
45 if (!freerdp_client_load_addins(context->channels, context->settings))
46 goto finish;
47
48 if (s_sync)
49 {
50 if (!SetEvent(s_sync))
51 goto finish;
52 }
53
54 rc = 1;
55
56 if (!freerdp_connect(context->instance))
57 goto finish;
58
59 rc = 2;
60
61 if (!freerdp_disconnect(context->instance))
62 goto finish;
63
64 rc = 0;
65finish:
66 freerdp_client_context_free(context);
67 if (inst)
68 *inst = NULL;
69 return rc;
70}
71
72static int testTimeout(int port)
73{
74 const DWORD timeout = 200;
75 DWORD start = 0;
76 DWORD end = 0;
77 DWORD diff = 0;
78 char arg1[] = "/v:192.0.2.1:XXXXX";
79 char* argv[] = { "test", "/v:192.0.2.1:XXXXX" };
80 int rc = 0;
81 (void)_snprintf(arg1, 18, "/v:192.0.2.1:%d", port);
82 argv[1] = arg1;
83 start = GetTickCount();
84 rc = runInstance(ARRAYSIZE(argv), argv, NULL, timeout);
85 end = GetTickCount();
86
87 if (rc != 1)
88 return -1;
89
90 diff = end - start;
91
92 if (diff > 4 * timeout)
93 return -1;
94
95 if (diff < timeout)
96 return -1;
97
98 printf("%s: Success!\n", __func__);
99 return 0;
100}
101
102struct testThreadArgs
103{
104 int port;
105 freerdp** arg;
106};
107
108static DWORD WINAPI testThread(LPVOID arg)
109{
110 char arg1[] = "/v:192.0.2.1:XXXXX";
111 char* argv[] = { "test", "/v:192.0.2.1:XXXXX" };
112 int rc = 0;
113 struct testThreadArgs* args = arg;
114 (void)_snprintf(arg1, 18, "/v:192.0.2.1:%d", args->port);
115 argv[1] = arg1;
116 rc = runInstance(ARRAYSIZE(argv), argv, args->arg, 5000);
117
118 if (rc != 1)
119 ExitThread(-1);
120
121 ExitThread(0);
122 return 0;
123}
124
125static int testAbort(int port)
126{
127 DWORD status = 0;
128 DWORD start = 0;
129 DWORD end = 0;
130 DWORD diff = 0;
131 HANDLE thread = NULL;
132 struct testThreadArgs args;
133 freerdp* instance = NULL;
134 s_sync = CreateEvent(NULL, TRUE, FALSE, NULL);
135
136 if (!s_sync)
137 return -1;
138
139 args.port = port;
140 args.arg = &instance;
141 start = GetTickCount();
142 thread = CreateThread(NULL, 0, testThread, &args, 0, NULL);
143
144 if (!thread)
145 {
146 (void)CloseHandle(s_sync);
147 s_sync = NULL;
148 return -1;
149 }
150
151 (void)WaitForSingleObject(s_sync, INFINITE);
152 Sleep(100); /* Wait until freerdp_connect has been called */
153 if (instance)
154 {
155 freerdp_abort_connect_context(instance->context);
156
157 if (!freerdp_shall_disconnect_context(instance->context))
158 {
159 (void)CloseHandle(s_sync);
160 (void)CloseHandle(thread);
161 s_sync = NULL;
162 return -1;
163 }
164 }
165
166 status = WaitForSingleObject(thread, 20000);
167 end = GetTickCount();
168 (void)CloseHandle(s_sync);
169 (void)CloseHandle(thread);
170 s_sync = NULL;
171 diff = end - start;
172
173 if (diff > 5000)
174 {
175 printf("%s required %" PRIu32 "ms for the test\n", __func__, diff);
176 return -1;
177 }
178
179 if (WAIT_OBJECT_0 != status)
180 return -1;
181
182 printf("%s: Success!\n", __func__);
183 return 0;
184}
185
186static char* concatenate(size_t count, ...)
187{
188 char* rc = NULL;
189 va_list ap = { 0 };
190 va_start(ap, count);
191 rc = _strdup(va_arg(ap, char*));
192 for (size_t x = 1; x < count; x++)
193 {
194 const char* cur = va_arg(ap, const char*);
195 char* tmp = GetCombinedPath(rc, cur);
196 free(rc);
197 rc = tmp;
198 }
199 va_end(ap);
200 return rc;
201}
202
203static BOOL prepare_certificates(const char* path)
204{
205 BOOL rc = FALSE;
206 char* exe = NULL;
207 DWORD status = 0;
208 STARTUPINFOA si = { 0 };
209 PROCESS_INFORMATION process = { 0 };
210 char commandLine[8192] = { 0 };
211
212 if (!path)
213 return FALSE;
214
215 exe = concatenate(5, TESTING_OUTPUT_DIRECTORY, "winpr", "tools", "makecert-cli",
216 "winpr-makecert" CMAKE_EXECUTABLE_SUFFIX);
217 if (!exe)
218 return FALSE;
219 (void)_snprintf(commandLine, sizeof(commandLine), "%s -format crt -path . -n server", exe);
220
221 rc = CreateProcessA(exe, commandLine, NULL, NULL, TRUE, 0, NULL, path, &si, &process);
222 free(exe);
223 if (!rc)
224 goto fail;
225 status = WaitForSingleObject(process.hProcess, 30000);
226 if (status != WAIT_OBJECT_0)
227 goto fail;
228 rc = TRUE;
229fail:
230 (void)CloseHandle(process.hProcess);
231 (void)CloseHandle(process.hThread);
232 return rc;
233}
234
235static int testSuccess(int port)
236{
237 int r = 0;
238 int rc = -2;
239 STARTUPINFOA si = { 0 };
240 PROCESS_INFORMATION process = { 0 };
241 char arg1[] = "/v:127.0.0.1:XXXXX";
242 char* clientArgs[] = { "test", "/v:127.0.0.1:XXXXX", "/cert:ignore", "/rfx", NULL };
243 char* commandLine = NULL;
244 size_t commandLineLen = 0;
245 int argc = 4;
246 char* path = NULL;
247 char* wpath = NULL;
248 char* exe = GetCombinedPath(TESTING_OUTPUT_DIRECTORY, "server");
249 (void)_snprintf(arg1, 18, "/v:127.0.0.1:%d", port);
250 clientArgs[1] = arg1;
251
252 if (!exe)
253 goto fail;
254
255 path = GetCombinedPath(exe, "Sample");
256 wpath = GetCombinedPath(exe, "Sample");
257 free(exe);
258 exe = NULL;
259
260 if (!path || !wpath)
261 goto fail;
262
263 exe = GetCombinedPath(path, "sfreerdp-server" CMAKE_EXECUTABLE_SUFFIX);
264
265 if (!exe)
266 goto fail;
267
268 printf("Sample Server: %s\n", exe);
269 printf("Workspace: %s\n", wpath);
270
271 if (!winpr_PathFileExists(exe))
272 goto fail;
273
274 if (!prepare_certificates(wpath))
275 goto fail;
276
277 // Start sample server locally.
278 commandLineLen = strlen(exe) + strlen("--port=XXXXX") + 1;
279 commandLine = malloc(commandLineLen);
280
281 if (!commandLine)
282 goto fail;
283
284 (void)_snprintf(commandLine, commandLineLen, "%s --port=%d", exe, port);
285 si.cb = sizeof(si);
286
287 if (!CreateProcessA(NULL, commandLine, NULL, NULL, FALSE, 0, NULL, wpath, &si, &process))
288 goto fail;
289
290 Sleep(5000); /* let the server start */
291 r = runInstance(argc, clientArgs, NULL, 10000);
292
293 if (!TerminateProcess(process.hProcess, 0))
294 goto fail;
295
296 (void)WaitForSingleObject(process.hProcess, INFINITE);
297 (void)CloseHandle(process.hProcess);
298 (void)CloseHandle(process.hThread);
299 printf("%s: returned %d!\n", __func__, r);
300 rc = r;
301
302 if (rc == 0)
303 printf("%s: Success!\n", __func__);
304
305fail:
306 free(exe);
307 free(path);
308 free(wpath);
309 free(commandLine);
310 return rc;
311}
312
313int TestConnect(int argc, char* argv[])
314{
315 int randomPort = 0;
316 int random = 0;
317 WINPR_UNUSED(argc);
318 WINPR_UNUSED(argv);
319 winpr_RAND(&random, sizeof(random));
320 randomPort = 3389 + (random % 200);
321
322 /* Test connect to not existing server,
323 * check if timeout is honored. */
324 if (testTimeout(randomPort))
325 return -1;
326
327 /* Test connect to not existing server,
328 * check if connection abort is working. */
329 if (testAbort(randomPort))
330 return -1;
331
332 /* Test connect to existing server,
333 * check if connection is working. */
334 if (testSuccess(randomPort))
335 return -1;
336
337 return 0;
338}
FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 param)
Sets a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL param)
Sets a BOOL settings value.