summaryrefslogtreecommitdiffstats
path: root/libfreerdp/core/test/TestConnect.c
diff options
context:
space:
mode:
Diffstat (limited to 'libfreerdp/core/test/TestConnect.c')
-rw-r--r--libfreerdp/core/test/TestConnect.c338
1 files changed, 338 insertions, 0 deletions
diff --git a/libfreerdp/core/test/TestConnect.c b/libfreerdp/core/test/TestConnect.c
new file mode 100644
index 0000000..4a3b89a
--- /dev/null
+++ b/libfreerdp/core/test/TestConnect.c
@@ -0,0 +1,338 @@
+#include <winpr/sysinfo.h>
+#include <winpr/path.h>
+#include <winpr/crypto.h>
+#include <winpr/pipe.h>
+
+#include <freerdp/freerdp.h>
+#include <freerdp/gdi/gdi.h>
+#include <freerdp/client/cmdline.h>
+
+static HANDLE s_sync = NULL;
+
+static int runInstance(int argc, char* argv[], freerdp** inst, DWORD timeout)
+{
+ int rc = -1;
+ RDP_CLIENT_ENTRY_POINTS clientEntryPoints = { 0 };
+ rdpContext* context = NULL;
+
+ clientEntryPoints.Size = sizeof(RDP_CLIENT_ENTRY_POINTS);
+ clientEntryPoints.Version = RDP_CLIENT_INTERFACE_VERSION;
+ clientEntryPoints.ContextSize = sizeof(rdpContext);
+ context = freerdp_client_context_new(&clientEntryPoints);
+
+ if (!context)
+ goto finish;
+
+ if (inst)
+ *inst = context->instance;
+
+ context->instance->ChooseSmartcard = NULL;
+ context->instance->PresentGatewayMessage = NULL;
+ context->instance->LogonErrorInfo = NULL;
+ context->instance->AuthenticateEx = NULL;
+ context->instance->VerifyCertificateEx = NULL;
+ context->instance->VerifyChangedCertificateEx = NULL;
+
+ if (!freerdp_settings_set_bool(context->settings, FreeRDP_DeactivateClientDecoding, TRUE))
+ return FALSE;
+
+ if (freerdp_client_settings_parse_command_line(context->settings, argc, argv, FALSE) < 0)
+ goto finish;
+
+ if (!freerdp_settings_set_uint32(context->settings, FreeRDP_TcpConnectTimeout, timeout))
+ goto finish;
+
+ if (!freerdp_client_load_addins(context->channels, context->settings))
+ goto finish;
+
+ if (s_sync)
+ {
+ if (!SetEvent(s_sync))
+ goto finish;
+ }
+
+ rc = 1;
+
+ if (!freerdp_connect(context->instance))
+ goto finish;
+
+ rc = 2;
+
+ if (!freerdp_disconnect(context->instance))
+ goto finish;
+
+ rc = 0;
+finish:
+ freerdp_client_context_free(context);
+ if (inst)
+ *inst = NULL;
+ return rc;
+}
+
+static int testTimeout(int port)
+{
+ const DWORD timeout = 200;
+ DWORD start = 0;
+ DWORD end = 0;
+ DWORD diff = 0;
+ char arg1[] = "/v:192.0.2.1:XXXXX";
+ char* argv[] = { "test", "/v:192.0.2.1:XXXXX" };
+ int rc = 0;
+ _snprintf(arg1, 18, "/v:192.0.2.1:%d", port);
+ argv[1] = arg1;
+ start = GetTickCount();
+ rc = runInstance(ARRAYSIZE(argv), argv, NULL, timeout);
+ end = GetTickCount();
+
+ if (rc != 1)
+ return -1;
+
+ diff = end - start;
+
+ if (diff > 4 * timeout)
+ return -1;
+
+ if (diff < timeout)
+ return -1;
+
+ printf("%s: Success!\n", __func__);
+ return 0;
+}
+
+struct testThreadArgs
+{
+ int port;
+ freerdp** arg;
+};
+
+static DWORD WINAPI testThread(LPVOID arg)
+{
+ char arg1[] = "/v:192.0.2.1:XXXXX";
+ char* argv[] = { "test", "/v:192.0.2.1:XXXXX" };
+ int rc = 0;
+ struct testThreadArgs* args = arg;
+ _snprintf(arg1, 18, "/v:192.0.2.1:%d", args->port);
+ argv[1] = arg1;
+ rc = runInstance(ARRAYSIZE(argv), argv, args->arg, 5000);
+
+ if (rc != 1)
+ ExitThread(-1);
+
+ ExitThread(0);
+ return 0;
+}
+
+static int testAbort(int port)
+{
+ DWORD status = 0;
+ DWORD start = 0;
+ DWORD end = 0;
+ DWORD diff = 0;
+ HANDLE thread = NULL;
+ struct testThreadArgs args;
+ freerdp* instance = NULL;
+ s_sync = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ if (!s_sync)
+ return -1;
+
+ args.port = port;
+ args.arg = &instance;
+ start = GetTickCount();
+ thread = CreateThread(NULL, 0, testThread, &args, 0, NULL);
+
+ if (!thread)
+ {
+ CloseHandle(s_sync);
+ s_sync = NULL;
+ return -1;
+ }
+
+ WaitForSingleObject(s_sync, INFINITE);
+ Sleep(100); /* Wait until freerdp_connect has been called */
+ if (instance)
+ {
+ freerdp_abort_connect_context(instance->context);
+
+ if (!freerdp_shall_disconnect_context(instance->context))
+ {
+ CloseHandle(s_sync);
+ CloseHandle(thread);
+ s_sync = NULL;
+ return -1;
+ }
+ }
+
+ status = WaitForSingleObject(thread, 20000);
+ end = GetTickCount();
+ CloseHandle(s_sync);
+ CloseHandle(thread);
+ s_sync = NULL;
+ diff = end - start;
+
+ if (diff > 5000)
+ {
+ printf("%s required %" PRIu32 "ms for the test\n", __func__, diff);
+ return -1;
+ }
+
+ if (WAIT_OBJECT_0 != status)
+ return -1;
+
+ printf("%s: Success!\n", __func__);
+ return 0;
+}
+
+static char* concatenate(size_t count, ...)
+{
+ char* rc = NULL;
+ va_list ap;
+ va_start(ap, count);
+ rc = _strdup(va_arg(ap, char*));
+ for (size_t x = 1; x < count; x++)
+ {
+ const char* cur = va_arg(ap, const char*);
+ char* tmp = GetCombinedPath(rc, cur);
+ free(rc);
+ rc = tmp;
+ }
+ va_end(ap);
+ return rc;
+}
+
+static BOOL prepare_certificates(const char* path)
+{
+ BOOL rc = FALSE;
+ char* exe = NULL;
+ DWORD status = 0;
+ STARTUPINFOA si = { 0 };
+ PROCESS_INFORMATION process = { 0 };
+ char commandLine[8192] = { 0 };
+
+ if (!path)
+ return FALSE;
+
+ exe = concatenate(5, TESTING_OUTPUT_DIRECTORY, "winpr", "tools", "makecert-cli",
+ "winpr-makecert" CMAKE_EXECUTABLE_SUFFIX);
+ if (!exe)
+ return FALSE;
+ _snprintf(commandLine, sizeof(commandLine), "%s -format crt -path . -n server", exe);
+
+ rc = CreateProcessA(exe, commandLine, NULL, NULL, TRUE, 0, NULL, path, &si, &process);
+ free(exe);
+ if (!rc)
+ goto fail;
+ status = WaitForSingleObject(process.hProcess, 30000);
+ if (status != WAIT_OBJECT_0)
+ goto fail;
+ rc = TRUE;
+fail:
+ CloseHandle(process.hProcess);
+ CloseHandle(process.hThread);
+ return rc;
+}
+
+static int testSuccess(int port)
+{
+ int r = 0;
+ int rc = -2;
+ STARTUPINFOA si = { 0 };
+ PROCESS_INFORMATION process = { 0 };
+ char arg1[] = "/v:127.0.0.1:XXXXX";
+ char* clientArgs[] = { "test", "/v:127.0.0.1:XXXXX", "/cert:ignore", "/rfx", NULL };
+ char* commandLine = NULL;
+ size_t commandLineLen = 0;
+ int argc = 4;
+ char* path = NULL;
+ char* wpath = NULL;
+ char* exe = GetCombinedPath(TESTING_OUTPUT_DIRECTORY, "server");
+ _snprintf(arg1, 18, "/v:127.0.0.1:%d", port);
+ clientArgs[1] = arg1;
+
+ if (!exe)
+ goto fail;
+
+ path = GetCombinedPath(exe, "Sample");
+ wpath = GetCombinedPath(exe, "Sample");
+ free(exe);
+ exe = NULL;
+
+ if (!path || !wpath)
+ goto fail;
+
+ exe = GetCombinedPath(path, "sfreerdp-server" CMAKE_EXECUTABLE_SUFFIX);
+
+ if (!exe)
+ goto fail;
+
+ printf("Sample Server: %s\n", exe);
+ printf("Workspace: %s\n", wpath);
+
+ if (!winpr_PathFileExists(exe))
+ goto fail;
+
+ if (!prepare_certificates(wpath))
+ goto fail;
+
+ // Start sample server locally.
+ commandLineLen = strlen(exe) + strlen("--port=XXXXX") + 1;
+ commandLine = malloc(commandLineLen);
+
+ if (!commandLine)
+ goto fail;
+
+ _snprintf(commandLine, commandLineLen, "%s --port=%d", exe, port);
+ si.cb = sizeof(si);
+
+ if (!CreateProcessA(NULL, commandLine, NULL, NULL, FALSE, 0, NULL, wpath, &si, &process))
+ goto fail;
+
+ Sleep(5000); /* let the server start */
+ r = runInstance(argc, clientArgs, NULL, 10000);
+
+ if (!TerminateProcess(process.hProcess, 0))
+ goto fail;
+
+ WaitForSingleObject(process.hProcess, INFINITE);
+ CloseHandle(process.hProcess);
+ CloseHandle(process.hThread);
+ printf("%s: returned %d!\n", __func__, r);
+ rc = r;
+
+ if (rc == 0)
+ printf("%s: Success!\n", __func__);
+
+fail:
+ free(exe);
+ free(path);
+ free(wpath);
+ free(commandLine);
+ return rc;
+}
+
+int TestConnect(int argc, char* argv[])
+{
+ int randomPort = 0;
+ int random = 0;
+ WINPR_UNUSED(argc);
+ WINPR_UNUSED(argv);
+ winpr_RAND(&random, sizeof(random));
+ randomPort = 3389 + (random % 200);
+
+ /* Test connect to not existing server,
+ * check if timeout is honored. */
+ if (testTimeout(randomPort))
+ return -1;
+
+ /* Test connect to not existing server,
+ * check if connection abort is working. */
+ if (testAbort(randomPort))
+ return -1;
+
+ /* Test connect to existing server,
+ * check if connection is working. */
+ if (testSuccess(randomPort))
+ return -1;
+
+ return 0;
+}