FreeRDP
Loading...
Searching...
No Matches
TestClientAutoReconnect.c
1#include <stdio.h>
2
3#include <winpr/crt.h>
4
5#include <freerdp/freerdp.h>
6#include <freerdp/client.h>
7#include <freerdp/transport_io.h>
8
9#define MAX_RETRIES 5
10
11static size_t s_attempts = 0;
12static UINT32 s_connectError = FREERDP_ERROR_SUCCESS;
13
14/* Stands in for the server: every reconnect attempt fails with s_connectError. */
15WINPR_ATTR_NODISCARD
16static int test_tcp_connect(rdpContext* context, WINPR_ATTR_UNUSED rdpSettings* settings,
17 WINPR_ATTR_UNUSED const char* hostname, WINPR_ATTR_UNUSED int port,
18 WINPR_ATTR_UNUSED DWORD timeout)
19{
20 freerdp_set_last_error_log(context, s_connectError);
21 return -1;
22}
23
24WINPR_ATTR_NODISCARD
25static SSIZE_T test_retry_dialog(WINPR_ATTR_UNUSED freerdp* instance,
26 WINPR_ATTR_UNUSED const char* what, size_t current,
27 WINPR_ATTR_UNUSED void* userarg)
28{
29 s_attempts = current + 1;
30 return 0;
31}
32
33WINPR_ATTR_NODISCARD
34static BOOL test_reconnect(UINT32 connectError, size_t expectedAttempts)
35{
36 BOOL rc = FALSE;
37 RDP_CLIENT_ENTRY_POINTS clientEntryPoints = WINPR_C_ARRAY_INIT;
38 clientEntryPoints.Size = sizeof(RDP_CLIENT_ENTRY_POINTS);
39 clientEntryPoints.Version = RDP_CLIENT_INTERFACE_VERSION;
40 clientEntryPoints.ContextSize = sizeof(rdpClientContext);
41
42 rdpContext* context = freerdp_client_context_new(&clientEntryPoints);
43 if (!context)
44 return FALSE;
45
46 s_attempts = 0;
47 s_connectError = connectError;
48 context->instance->RetryDialog = test_retry_dialog;
49
50 rdpSettings* settings = context->settings;
51 if (!freerdp_settings_set_string(settings, FreeRDP_ServerHostname, "127.0.0.1") ||
52 !freerdp_settings_set_bool(settings, FreeRDP_AutoReconnectionEnabled, TRUE) ||
53 !freerdp_settings_set_uint32(settings, FreeRDP_AutoReconnectMaxRetries, MAX_RETRIES))
54 goto fail;
55
56 const rdpTransportIo* defaultIo = freerdp_get_io_callbacks(context);
57 if (!defaultIo)
58 goto fail;
59 rdpTransportIo io = *defaultIo;
60 io.TCPConnect = test_tcp_connect;
61 if (!freerdp_set_io_callbacks(context, &io))
62 goto fail;
63
64 if (client_auto_reconnect_ex(context->instance, nullptr))
65 {
66 (void)fprintf(stderr, "[%s] reconnect succeeded\n",
67 freerdp_get_last_error_name(connectError));
68 goto fail;
69 }
70
71 if (s_attempts != expectedAttempts)
72 {
73 (void)fprintf(stderr, "[%s] expected %" PRIuz " attempts, got %" PRIuz "\n",
74 freerdp_get_last_error_name(connectError), expectedAttempts, s_attempts);
75 goto fail;
76 }
77
78 const UINT32 lastError = freerdp_get_last_error(context);
79 if (lastError != connectError)
80 {
81 (void)fprintf(stderr, "[%s] last error is %s\n", freerdp_get_last_error_name(connectError),
82 freerdp_get_last_error_name(lastError));
83 goto fail;
84 }
85
86 rc = TRUE;
87fail:
88 freerdp_client_context_free(context);
89 return rc;
90}
91
92int TestClientAutoReconnect(int argc, char* argv[])
93{
94 WINPR_UNUSED(argc);
95 WINPR_UNUSED(argv);
96
97 /* A network error keeps retrying until the limit. */
98 if (!test_reconnect(FREERDP_ERROR_CONNECT_FAILED, MAX_RETRIES))
99 return -1;
100
101 /* Rejected credentials stop after the attempt that got them. */
102 const UINT32 rejected[] = { FREERDP_ERROR_CONNECT_LOGON_FAILURE,
103 FREERDP_ERROR_CONNECT_WRONG_PASSWORD,
104 FREERDP_ERROR_CONNECT_ACCOUNT_LOCKED_OUT };
105 for (size_t x = 0; x < ARRAYSIZE(rejected); x++)
106 {
107 if (!test_reconnect(rejected[x], 1))
108 return -1;
109 }
110
111 return 0;
112}
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.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_string(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *val)
Sets a string settings value. The param is copied.