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 = nullptr;
11
12static int runInstance(int argc, char* argv[], freerdp** inst, DWORD timeout)
13{
14 int rc = -1;
15 RDP_CLIENT_ENTRY_POINTS clientEntryPoints = WINPR_C_ARRAY_INIT;
16 rdpContext* context = nullptr;
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 = nullptr;
30 context->instance->PresentGatewayMessage = nullptr;
31 context->instance->LogonErrorInfo = nullptr;
32 context->instance->AuthenticateEx = nullptr;
33 context->instance->VerifyCertificateEx = nullptr;
34 context->instance->VerifyChangedCertificateEx = nullptr;
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 = nullptr;
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, nullptr, 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 = nullptr;
132 struct testThreadArgs args;
133 freerdp* instance = nullptr;
134 s_sync = CreateEvent(nullptr, TRUE, FALSE, nullptr);
135
136 if (!s_sync)
137 return -1;
138
139 args.port = port;
140 args.arg = &instance;
141 start = GetTickCount();
142 thread = CreateThread(nullptr, 0, testThread, &args, 0, nullptr);
143
144 if (!thread)
145 {
146 (void)CloseHandle(s_sync);
147 s_sync = nullptr;
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 = nullptr;
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 = nullptr;
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 = nullptr;
189 va_list ap = WINPR_C_ARRAY_INIT;
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 = nullptr;
207 DWORD status = 0;
208 STARTUPINFOA si = WINPR_C_ARRAY_INIT;
209 PROCESS_INFORMATION process = WINPR_C_ARRAY_INIT;
210
211 if (!path)
212 return FALSE;
213
214 exe = concatenate(5, TESTING_OUTPUT_DIRECTORY, "winpr", "tools", "makecert-cli",
215 "winpr-makecert" CMAKE_EXECUTABLE_SUFFIX);
216 if (!exe)
217 return FALSE;
218
219 char commandLine[] = "-format crt -path . -n server";
220 rc = CreateProcessA(exe, commandLine, nullptr, nullptr, TRUE, 0, nullptr, path, &si, &process);
221 free(exe);
222 if (!rc)
223 goto fail;
224 status = WaitForSingleObject(process.hProcess, 30000);
225 if (status != WAIT_OBJECT_0)
226 goto fail;
227 rc = TRUE;
228fail:
229 (void)CloseHandle(process.hProcess);
230 (void)CloseHandle(process.hThread);
231 return rc;
232}
233
234static int testSuccess(int port)
235{
236 int r = 0;
237 int rc = -2;
238 STARTUPINFOA si = WINPR_C_ARRAY_INIT;
239 PROCESS_INFORMATION process = WINPR_C_ARRAY_INIT;
240 char arg1[] = "/v:127.0.0.1:XXXXX";
241 char* clientArgs[] = { "test", "/v:127.0.0.1:XXXXX", "/cert:ignore", "/rfx", nullptr };
242 char* commandLine = nullptr;
243 size_t commandLineLen = 0;
244 int argc = 4;
245 char* path = nullptr;
246 char* wpath = nullptr;
247 char* exe = GetCombinedPath(TESTING_OUTPUT_DIRECTORY, "server");
248 (void)_snprintf(arg1, 18, "/v:127.0.0.1:%d", port);
249 clientArgs[1] = arg1;
250
251 if (!exe)
252 goto fail;
253
254 path = GetCombinedPath(exe, "Sample");
255 wpath = GetCombinedPath(exe, "Sample");
256 free(exe);
257 exe = nullptr;
258
259 if (!path || !wpath)
260 goto fail;
261
262 exe = GetCombinedPath(path, "sfreerdp-server" CMAKE_EXECUTABLE_SUFFIX);
263
264 if (!exe)
265 goto fail;
266
267 printf("Sample Server: %s\n", exe);
268 printf("Workspace: %s\n", wpath);
269
270 if (!winpr_PathFileExists(exe))
271 goto fail;
272
273 if (!prepare_certificates(wpath))
274 goto fail;
275
276 // Start sample server locally.
277 commandLineLen = strlen(exe) + strlen("--port=XXXXX") + 1;
278 commandLine = malloc(commandLineLen);
279
280 if (!commandLine)
281 goto fail;
282
283 (void)_snprintf(commandLine, commandLineLen, "%s --port=%d", exe, port);
284 si.cb = sizeof(si);
285
286 if (!CreateProcessA(nullptr, commandLine, nullptr, nullptr, FALSE, 0, nullptr, wpath, &si,
287 &process))
288 goto fail;
289
290 Sleep(5000); /* let the server start */
291 r = runInstance(argc, clientArgs, nullptr, 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 if (winpr_RAND(&random, sizeof(random)) < 0)
320 return -1;
321 randomPort = 3389 + (random % 200);
322
323 /* Test connect to not existing server,
324 * check if timeout is honored. */
325 if (testTimeout(randomPort))
326 return -1;
327
328 /* Test connect to not existing server,
329 * check if connection abort is working. */
330 if (testAbort(randomPort))
331 return -1;
332
333 /* Test connect to existing server,
334 * check if connection is working. */
335 if (testSuccess(randomPort))
336 return -1;
337
338 return 0;
339}
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL val)
Sets a BOOL settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 val)
Sets a UINT32 settings value.