[client,x11] add thread reading from named pipe

the named pipe input is converted to unicode and sent as keyboard input
This commit is contained in:
akallabeth 2023-06-30 15:08:10 +02:00 committed by Martin Fleisz
parent a01f3ec5ab
commit 2d85aa43fa
3 changed files with 107 additions and 3 deletions

View File

@ -64,6 +64,8 @@
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/select.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <freerdp/freerdp.h>
#include <freerdp/constants.h>
@ -1210,6 +1212,93 @@ static BOOL xf_pre_connect(freerdp* instance)
return TRUE;
}
static BOOL xf_inject_keypress(rdpContext* context, const char* buffer, size_t size)
{
WCHAR wbuffer[64] = { 0 };
const SSIZE_T len = ConvertUtf8NToWChar(buffer, size, wbuffer, ARRAYSIZE(wbuffer));
if (len < 0)
return FALSE;
rdpInput* input = context->input;
WINPR_ASSERT(input);
for (SSIZE_T x = 0; x < len; x++)
{
const WCHAR code = wbuffer[x];
freerdp_input_send_unicode_keyboard_event(input, 0, code);
Sleep(5);
freerdp_input_send_unicode_keyboard_event(input, KBD_FLAGS_RELEASE, code);
Sleep(5);
}
return TRUE;
}
static BOOL xf_process_pipe(rdpContext* context, const char* pipe)
{
int fd = open(pipe, O_NONBLOCK | O_RDONLY);
if (fd < 0)
{
WLog_ERR(TAG, "pipe '%s' open returned %s [%d]", pipe, strerror(errno), errno);
return FALSE;
}
while (!freerdp_shall_disconnect_context(context))
{
char buffer[64] = { 0 };
ssize_t rd = read(fd, buffer, sizeof(buffer) - 1);
if (rd == 0)
{
if ((errno == EAGAIN) || (errno == 0))
{
Sleep(100);
continue;
}
// EOF, abort reading.
WLog_ERR(TAG, "pipe '%s' read returned %s [%d]", pipe, strerror(errno), errno);
break;
}
else if (rd < 0)
{
WLog_ERR(TAG, "pipe '%s' read returned %s [%d]", pipe, strerror(errno), errno);
break;
}
else
{
if (!xf_inject_keypress(context, buffer, rd))
break;
}
}
close(fd);
return TRUE;
}
static DWORD WINAPI xf_handle_pipe(void* arg)
{
xfContext* xfc = arg;
WINPR_ASSERT(xfc);
rdpContext* context = &xfc->common.context;
WINPR_ASSERT(context);
rdpSettings* settings = context->settings;
WINPR_ASSERT(settings);
const char* pipe = freerdp_settings_get_string(settings, FreeRDP_KeyboardPipeName);
WINPR_ASSERT(pipe);
const int rc = mkfifo(pipe, S_IWUSR | S_IRUSR);
if (rc != 0)
{
WLog_ERR(TAG, "Failed to create named pipe '%s': %s [%d]", pipe, strerror(errno), errno);
return 0;
}
xf_process_pipe(context, pipe);
unlink(pipe);
return 0;
}
/**
* Callback given to freerdp_connect() to perform post-connection operations.
* It will be called only if the connection was initialized properly, and will continue the
@ -1297,9 +1386,14 @@ static BOOL xf_post_connect(freerdp* instance)
return FALSE;
if (!(xfc->xfDisp = xf_disp_new(xfc)))
{
xf_clipboard_free(xfc->clipboard);
return FALSE;
const char* pipe = freerdp_settings_get_string(settings, FreeRDP_KeyboardPipeName);
if (pipe)
{
xfc->pipethread = CreateThread(NULL, 0, xf_handle_pipe, xfc, 0, NULL);
if (!xfc->pipethread)
return FALSE;
}
EventArgsInit(&e, "xfreerdp");
@ -1325,6 +1419,12 @@ static void xf_post_disconnect(freerdp* instance)
xf_OnChannelDisconnectedEventHandler);
gdi_free(instance);
if (xfc->pipethread)
{
WaitForSingleObject(xfc->pipethread, INFINITE);
CloseHandle(xfc->pipethread);
xfc->pipethread = NULL;
}
if (xfc->clipboard)
{
xf_clipboard_free(xfc->clipboard);

View File

@ -294,6 +294,7 @@ struct xf_context
#endif
BOOL xi_rawevent;
BOOL xi_event;
HANDLE pipethread;
};
BOOL xf_create_window(xfContext* xfc);

View File

@ -2175,7 +2175,9 @@ static int parse_kbd_options(rdpSettings* settings, const COMMAND_LINE_ARGUMENT_
}
else if (option_starts_with("pipe:", val))
{
if (!freerdp_settings_set_string(settings, FreeRDP_KeyboardPipeName, &val[5]))
if (!freerdp_settings_set_bool(settings, FreeRDP_UnicodeInput, TRUE))
rc = COMMAND_LINE_ERROR_UNEXPECTED_VALUE;
else if (!freerdp_settings_set_string(settings, FreeRDP_KeyboardPipeName, &val[5]))
rc = COMMAND_LINE_ERROR_UNEXPECTED_VALUE;
}
#if defined(WITH_FREERDP_DEPRECATED_COMMANDLINE)
@ -2192,6 +2194,7 @@ static int parse_kbd_options(rdpSettings* settings, const COMMAND_LINE_ARGUMENT_
break;
}
}
free(ptr);
return rc;
}