FreeRDP/libfreerdp/core/test/TestConnect.c
2021-06-08 08:21:47 +02:00

268 lines
5.6 KiB
C

#include <winpr/sysinfo.h>
#include <winpr/path.h>
#include <winpr/crypto.h>
#include <freerdp/freerdp.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;
ZeroMemory(&clientEntryPoints, sizeof(RDP_CLIENT_ENTRY_POINTS));
clientEntryPoints.Size = sizeof(RDP_CLIENT_ENTRY_POINTS);
clientEntryPoints.Version = RDP_CLIENT_INTERFACE_VERSION;
clientEntryPoints.ContextSize = sizeof(rdpContext);
rdpContext* context = freerdp_client_context_new(&clientEntryPoints);
if (!context)
goto finish;
if (inst)
*inst = context->instance;
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);
return rc;
}
static int testTimeout(int port)
{
const DWORD timeout = 200;
DWORD start, end, diff;
char arg1[] = "/v:192.0.2.1:XXXXX";
char* argv[] = { "test", "/v:192.0.2.1:XXXXX" };
int rc;
_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", __FUNCTION__);
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;
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;
DWORD start, end, diff;
HANDLE thread;
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 */
freerdp_abort_connect(instance);
status = WaitForSingleObject(instance->context->abortEvent, 0);
if (status != WAIT_OBJECT_0)
{
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", __FUNCTION__, diff);
return -1;
}
if (WAIT_OBJECT_0 != status)
return -1;
printf("%s: Success!\n", __FUNCTION__);
return 0;
}
static int testSuccess(int port)
{
int r;
int rc = -2;
STARTUPINFOA si;
PROCESS_INFORMATION process;
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;
int argc = 4;
char* path = NULL;
char* wpath = NULL;
char* exe = GetCombinedPath(TESTING_OUTPUT_DIRECTORY, "server");
char* wexe = GetCombinedPath(TESTING_SRC_DIRECTORY, "server");
_snprintf(arg1, 18, "/v:127.0.0.1:%d", port);
clientArgs[1] = arg1;
if (!exe || !wexe)
goto fail;
path = GetCombinedPath(exe, "Sample");
wpath = GetCombinedPath(wexe, "Sample");
free(exe);
exe = NULL;
if (!path || !wpath)
goto fail;
exe = GetCombinedPath(path, "sfreerdp-server");
if (!exe)
goto fail;
printf("Sample Server: %s\n", exe);
printf("Workspace: %s\n", wpath);
if (!winpr_PathFileExists(exe))
goto fail;
// Start sample server locally.
commandLineLen = strlen(exe) + strlen("--local-only --port=XXXXX") + 1;
commandLine = malloc(commandLineLen);
if (!commandLine)
goto fail;
_snprintf(commandLine, commandLineLen, "%s --local-only --port=%d", exe, port);
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
if (!CreateProcessA(exe, commandLine, NULL, NULL, FALSE, 0, NULL, wpath, &si, &process))
goto fail;
Sleep(600); /* let the server start */
r = runInstance(argc, clientArgs, NULL, 5000);
if (!TerminateProcess(process.hProcess, 0))
goto fail;
WaitForSingleObject(process.hProcess, INFINITE);
CloseHandle(process.hProcess);
CloseHandle(process.hThread);
printf("%s: returned %d!\n", __FUNCTION__, r);
rc = r;
if (rc == 0)
printf("%s: Success!\n", __FUNCTION__);
fail:
free(exe);
free(wexe);
free(path);
free(wpath);
free(commandLine);
return rc;
}
int TestConnect(int argc, char* argv[])
{
int randomPort;
int random;
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
winpr_RAND((BYTE*)&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;
}