GUACAMOLE-1283: Merge add synchronization around absolutely all outbound RDP messages.
This commit is contained in:
commit
e90e438cf6
@ -31,9 +31,10 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
guac_rdp_audio_buffer* guac_rdp_audio_buffer_alloc() {
|
guac_rdp_audio_buffer* guac_rdp_audio_buffer_alloc(guac_client* client) {
|
||||||
guac_rdp_audio_buffer* buffer = calloc(1, sizeof(guac_rdp_audio_buffer));
|
guac_rdp_audio_buffer* buffer = calloc(1, sizeof(guac_rdp_audio_buffer));
|
||||||
pthread_mutex_init(&(buffer->lock), NULL);
|
pthread_mutex_init(&(buffer->lock), NULL);
|
||||||
|
buffer->client = client;
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,8 +271,8 @@ void guac_rdp_audio_buffer_write(guac_rdp_audio_buffer* audio_buffer,
|
|||||||
|
|
||||||
/* Only actually invoke if defined */
|
/* Only actually invoke if defined */
|
||||||
if (audio_buffer->flush_handler)
|
if (audio_buffer->flush_handler)
|
||||||
audio_buffer->flush_handler(audio_buffer->packet,
|
audio_buffer->flush_handler(audio_buffer,
|
||||||
audio_buffer->bytes_written, audio_buffer->data);
|
audio_buffer->bytes_written);
|
||||||
|
|
||||||
/* Reset buffer in all cases */
|
/* Reset buffer in all cases */
|
||||||
audio_buffer->bytes_written = 0;
|
audio_buffer->bytes_written = 0;
|
||||||
|
@ -24,24 +24,27 @@
|
|||||||
#include <guacamole/user.h>
|
#include <guacamole/user.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A buffer of arbitrary audio data. Received audio data can be written to this
|
||||||
|
* buffer, and will automatically be flushed via a given handler once the
|
||||||
|
* internal buffer reaches capacity.
|
||||||
|
*/
|
||||||
|
typedef struct guac_rdp_audio_buffer guac_rdp_audio_buffer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler which is invoked when a guac_rdp_audio_buffer's internal packet
|
* Handler which is invoked when a guac_rdp_audio_buffer's internal packet
|
||||||
* buffer has reached capacity and must be flushed.
|
* buffer has reached capacity and must be flushed.
|
||||||
*
|
*
|
||||||
* @param buffer
|
* @param audio_buffer
|
||||||
* The buffer which needs to be flushed as an audio packet.
|
* The guac_rdp_audio_buffer that has reached capacity and needs to be
|
||||||
|
* flushed.
|
||||||
*
|
*
|
||||||
* @param length
|
* @param length
|
||||||
* The number of bytes stored within the buffer. This is guaranteed to be
|
* The number of bytes stored within the buffer. This is guaranteed to be
|
||||||
* identical to the packet_size value specified when the audio buffer was
|
* identical to the packet_size value specified when the audio buffer was
|
||||||
* initialized.
|
* initialized.
|
||||||
*
|
|
||||||
* @param data
|
|
||||||
* The arbitrary data pointer provided when the audio buffer was
|
|
||||||
* initialized.
|
|
||||||
*/
|
*/
|
||||||
typedef void guac_rdp_audio_buffer_flush_handler(char* buffer, int length,
|
typedef void guac_rdp_audio_buffer_flush_handler(guac_rdp_audio_buffer* audio_buffer, int length);
|
||||||
void* data);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A description of an arbitrary PCM audio format.
|
* A description of an arbitrary PCM audio format.
|
||||||
@ -66,12 +69,7 @@ typedef struct guac_rdp_audio_format {
|
|||||||
|
|
||||||
} guac_rdp_audio_format;
|
} guac_rdp_audio_format;
|
||||||
|
|
||||||
/**
|
struct guac_rdp_audio_buffer {
|
||||||
* A buffer of arbitrary audio data. Received audio data can be written to this
|
|
||||||
* buffer, and will automatically be flushed via a given handler once the
|
|
||||||
* internal buffer reaches capacity.
|
|
||||||
*/
|
|
||||||
typedef struct guac_rdp_audio_buffer {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lock which is acquired/released to ensure accesses to the audio buffer
|
* Lock which is acquired/released to ensure accesses to the audio buffer
|
||||||
@ -79,6 +77,11 @@ typedef struct guac_rdp_audio_buffer {
|
|||||||
*/
|
*/
|
||||||
pthread_mutex_t lock;
|
pthread_mutex_t lock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The guac_client instance handling the relevant RDP connection.
|
||||||
|
*/
|
||||||
|
guac_client* client;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The user from which this audio buffer will receive data. If no user has
|
* The user from which this audio buffer will receive data. If no user has
|
||||||
* yet opened an associated audio stream, this will be NULL.
|
* yet opened an associated audio stream, this will be NULL.
|
||||||
@ -145,17 +148,20 @@ typedef struct guac_rdp_audio_buffer {
|
|||||||
*/
|
*/
|
||||||
void* data;
|
void* data;
|
||||||
|
|
||||||
} guac_rdp_audio_buffer;
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocates a new audio buffer. The new audio buffer will ignore any received
|
* Allocates a new audio buffer. The new audio buffer will ignore any received
|
||||||
* data until guac_rdp_audio_buffer_begin() is invoked, and will resume
|
* data until guac_rdp_audio_buffer_begin() is invoked, and will resume
|
||||||
* ignoring received data once guac_rdp_audio_buffer_end() is invoked.
|
* ignoring received data once guac_rdp_audio_buffer_end() is invoked.
|
||||||
*
|
*
|
||||||
|
* @param client
|
||||||
|
* The guac_client instance handling the relevant RDP connection.
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
* A newly-allocated audio buffer.
|
* A newly-allocated audio buffer.
|
||||||
*/
|
*/
|
||||||
guac_rdp_audio_buffer* guac_rdp_audio_buffer_alloc();
|
guac_rdp_audio_buffer* guac_rdp_audio_buffer_alloc(guac_client* client);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Associates the given audio buffer with the underlying audio stream which
|
* Associates the given audio buffer with the underlying audio stream which
|
||||||
|
@ -76,6 +76,9 @@ static UINT guac_rdp_cliprdr_send_format_list(CliprdrClientContext* cliprdr) {
|
|||||||
guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
|
guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
|
||||||
assert(clipboard != NULL);
|
assert(clipboard != NULL);
|
||||||
|
|
||||||
|
guac_client* client = clipboard->client;
|
||||||
|
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||||
|
|
||||||
/* We support CP-1252 and UTF-16 text */
|
/* We support CP-1252 and UTF-16 text */
|
||||||
CLIPRDR_FORMAT_LIST format_list = {
|
CLIPRDR_FORMAT_LIST format_list = {
|
||||||
.msgType = CB_FORMAT_LIST,
|
.msgType = CB_FORMAT_LIST,
|
||||||
@ -86,10 +89,12 @@ static UINT guac_rdp_cliprdr_send_format_list(CliprdrClientContext* cliprdr) {
|
|||||||
.numFormats = 2
|
.numFormats = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
|
guac_client_log(client, GUAC_LOG_TRACE, "CLIPRDR: Sending format list");
|
||||||
"format list");
|
|
||||||
|
|
||||||
return cliprdr->ClientFormatList(cliprdr, &format_list);
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
|
int retval = cliprdr->ClientFormatList(cliprdr, &format_list);
|
||||||
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
|
return retval;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,6 +112,17 @@ static UINT guac_rdp_cliprdr_send_format_list(CliprdrClientContext* cliprdr) {
|
|||||||
*/
|
*/
|
||||||
static UINT guac_rdp_cliprdr_send_capabilities(CliprdrClientContext* cliprdr) {
|
static UINT guac_rdp_cliprdr_send_capabilities(CliprdrClientContext* cliprdr) {
|
||||||
|
|
||||||
|
/* This function is only invoked within FreeRDP-specific handlers for
|
||||||
|
* CLIPRDR, which are not assigned, and thus not callable, until after the
|
||||||
|
* relevant guac_rdp_clipboard structure is allocated and associated with
|
||||||
|
* the CliprdrClientContext */
|
||||||
|
guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
|
||||||
|
assert(clipboard != NULL);
|
||||||
|
|
||||||
|
guac_client* client = clipboard->client;
|
||||||
|
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||||
|
|
||||||
|
/* We support CP-1252 and UTF-16 text */
|
||||||
CLIPRDR_GENERAL_CAPABILITY_SET cap_set = {
|
CLIPRDR_GENERAL_CAPABILITY_SET cap_set = {
|
||||||
.capabilitySetType = CB_CAPSTYPE_GENERAL, /* CLIPRDR specification requires that this is CB_CAPSTYPE_GENERAL, the only defined set type */
|
.capabilitySetType = CB_CAPSTYPE_GENERAL, /* CLIPRDR specification requires that this is CB_CAPSTYPE_GENERAL, the only defined set type */
|
||||||
.capabilitySetLength = 12, /* The size of the capability set within the PDU - for CB_CAPSTYPE_GENERAL, this is ALWAYS 12 bytes */
|
.capabilitySetLength = 12, /* The size of the capability set within the PDU - for CB_CAPSTYPE_GENERAL, this is ALWAYS 12 bytes */
|
||||||
@ -119,7 +135,11 @@ static UINT guac_rdp_cliprdr_send_capabilities(CliprdrClientContext* cliprdr) {
|
|||||||
.capabilitySets = (CLIPRDR_CAPABILITY_SET*) &cap_set
|
.capabilitySets = (CLIPRDR_CAPABILITY_SET*) &cap_set
|
||||||
};
|
};
|
||||||
|
|
||||||
return cliprdr->ClientCapabilities(cliprdr, &caps);
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
|
int retval = cliprdr->ClientCapabilities(cliprdr, &caps);
|
||||||
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,6 +210,9 @@ static UINT guac_rdp_cliprdr_send_format_data_request(
|
|||||||
guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
|
guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
|
||||||
assert(clipboard != NULL);
|
assert(clipboard != NULL);
|
||||||
|
|
||||||
|
guac_client* client = clipboard->client;
|
||||||
|
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||||
|
|
||||||
/* Create new data request */
|
/* Create new data request */
|
||||||
CLIPRDR_FORMAT_DATA_REQUEST data_request = {
|
CLIPRDR_FORMAT_DATA_REQUEST data_request = {
|
||||||
.requestedFormatId = format
|
.requestedFormatId = format
|
||||||
@ -199,11 +222,14 @@ static UINT guac_rdp_cliprdr_send_format_data_request(
|
|||||||
* data is received via a Format Data Response PDU */
|
* data is received via a Format Data Response PDU */
|
||||||
clipboard->requested_format = format;
|
clipboard->requested_format = format;
|
||||||
|
|
||||||
guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
|
guac_client_log(client, GUAC_LOG_TRACE, "CLIPRDR: Sending format data request.");
|
||||||
"format data request.");
|
|
||||||
|
|
||||||
/* Send request */
|
/* Send request */
|
||||||
return cliprdr->ClientFormatDataRequest(cliprdr, &data_request);
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
|
int retval = cliprdr->ClientFormatDataRequest(cliprdr, &data_request);
|
||||||
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,15 +291,19 @@ static UINT guac_rdp_cliprdr_format_list(CliprdrClientContext* cliprdr,
|
|||||||
guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
|
guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
|
||||||
assert(clipboard != NULL);
|
assert(clipboard != NULL);
|
||||||
|
|
||||||
guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
|
guac_client* client = clipboard->client;
|
||||||
"format list.");
|
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||||
|
|
||||||
|
guac_client_log(client, GUAC_LOG_TRACE, "CLIPRDR: Received format list.");
|
||||||
|
|
||||||
CLIPRDR_FORMAT_LIST_RESPONSE format_list_response = {
|
CLIPRDR_FORMAT_LIST_RESPONSE format_list_response = {
|
||||||
.msgFlags = CB_RESPONSE_OK
|
.msgFlags = CB_RESPONSE_OK
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Report successful processing of format list */
|
/* Report successful processing of format list */
|
||||||
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
cliprdr->ClientFormatListResponse(cliprdr, &format_list_response);
|
cliprdr->ClientFormatListResponse(cliprdr, &format_list_response);
|
||||||
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
|
|
||||||
/* Prefer Unicode (in this case, UTF-16) */
|
/* Prefer Unicode (in this case, UTF-16) */
|
||||||
if (guac_rdp_cliprdr_format_supported(format_list, CF_UNICODETEXT))
|
if (guac_rdp_cliprdr_format_supported(format_list, CF_UNICODETEXT))
|
||||||
@ -284,9 +314,9 @@ static UINT guac_rdp_cliprdr_format_list(CliprdrClientContext* cliprdr,
|
|||||||
return guac_rdp_cliprdr_send_format_data_request(cliprdr, CF_TEXT);
|
return guac_rdp_cliprdr_send_format_data_request(cliprdr, CF_TEXT);
|
||||||
|
|
||||||
/* Ignore any unsupported data */
|
/* Ignore any unsupported data */
|
||||||
guac_client_log(clipboard->client, GUAC_LOG_DEBUG, "Ignoring unsupported "
|
guac_client_log(client, GUAC_LOG_DEBUG, "Ignoring unsupported clipboard "
|
||||||
"clipboard data. Only Unicode and text clipboard formats are "
|
"data. Only Unicode and text clipboard formats are currently "
|
||||||
"currently supported.");
|
"supported.");
|
||||||
|
|
||||||
return CHANNEL_RC_OK;
|
return CHANNEL_RC_OK;
|
||||||
|
|
||||||
@ -320,8 +350,10 @@ static UINT guac_rdp_cliprdr_format_data_request(CliprdrClientContext* cliprdr,
|
|||||||
guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
|
guac_rdp_clipboard* clipboard = (guac_rdp_clipboard*) cliprdr->custom;
|
||||||
assert(clipboard != NULL);
|
assert(clipboard != NULL);
|
||||||
|
|
||||||
guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Received "
|
guac_client* client = clipboard->client;
|
||||||
"format data request.");
|
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||||
|
|
||||||
|
guac_client_log(client, GUAC_LOG_TRACE, "CLIPRDR: Received format data request.");
|
||||||
|
|
||||||
guac_iconv_write* writer;
|
guac_iconv_write* writer;
|
||||||
const char* input = clipboard->clipboard->buffer;
|
const char* input = clipboard->clipboard->buffer;
|
||||||
@ -341,11 +373,11 @@ static UINT guac_rdp_cliprdr_format_data_request(CliprdrClientContext* cliprdr,
|
|||||||
/* Warn if clipboard data cannot be sent as intended due to a violation
|
/* Warn if clipboard data cannot be sent as intended due to a violation
|
||||||
* of the CLIPRDR spec */
|
* of the CLIPRDR spec */
|
||||||
default:
|
default:
|
||||||
guac_client_log(clipboard->client, GUAC_LOG_WARNING, "Received "
|
guac_client_log(client, GUAC_LOG_WARNING, "Received clipboard "
|
||||||
"clipboard data cannot be sent to the RDP server because "
|
"data cannot be sent to the RDP server because the RDP "
|
||||||
"the RDP server has requested a clipboard format which "
|
"server has requested a clipboard format which was not "
|
||||||
"was not declared as available. This violates the "
|
"declared as available. This violates the specification "
|
||||||
"specification for the CLIPRDR channel.");
|
"for the CLIPRDR channel.");
|
||||||
free(output);
|
free(output);
|
||||||
return CHANNEL_RC_OK;
|
return CHANNEL_RC_OK;
|
||||||
|
|
||||||
@ -363,10 +395,12 @@ static UINT guac_rdp_cliprdr_format_data_request(CliprdrClientContext* cliprdr,
|
|||||||
.msgFlags = CB_RESPONSE_OK
|
.msgFlags = CB_RESPONSE_OK
|
||||||
};
|
};
|
||||||
|
|
||||||
guac_client_log(clipboard->client, GUAC_LOG_TRACE, "CLIPRDR: Sending "
|
guac_client_log(client, GUAC_LOG_TRACE, "CLIPRDR: Sending format data response.");
|
||||||
"format data response.");
|
|
||||||
|
|
||||||
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
UINT result = cliprdr->ClientFormatDataResponse(cliprdr, &data_response);
|
UINT result = cliprdr->ClientFormatDataResponse(cliprdr, &data_response);
|
||||||
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
|
|
||||||
free(start);
|
free(start);
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
@ -407,9 +441,9 @@ static UINT guac_rdp_cliprdr_format_data_response(CliprdrClientContext* cliprdr,
|
|||||||
|
|
||||||
/* Ignore received data if copy has been disabled */
|
/* Ignore received data if copy has been disabled */
|
||||||
if (settings->disable_copy) {
|
if (settings->disable_copy) {
|
||||||
guac_client_log(clipboard->client, GUAC_LOG_DEBUG, "Ignoring received "
|
guac_client_log(client, GUAC_LOG_DEBUG, "Ignoring received clipboard "
|
||||||
"clipboard data as copying from within the remote desktop has "
|
"data as copying from within the remote desktop has been "
|
||||||
"been explicitly disabled.");
|
"explicitly disabled.");
|
||||||
return CHANNEL_RC_OK;
|
return CHANNEL_RC_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,9 +473,8 @@ static UINT guac_rdp_cliprdr_format_data_response(CliprdrClientContext* cliprdr,
|
|||||||
* here. The values which may be stored within requested_format are
|
* here. The values which may be stored within requested_format are
|
||||||
* completely within our control. */
|
* completely within our control. */
|
||||||
default:
|
default:
|
||||||
guac_client_log(clipboard->client, GUAC_LOG_DEBUG, "Requested "
|
guac_client_log(client, GUAC_LOG_DEBUG, "Requested clipboard data "
|
||||||
"clipboard data in unsupported format (0x%X).",
|
"in unsupported format (0x%X).", clipboard->requested_format);
|
||||||
clipboard->requested_format);
|
|
||||||
return CHANNEL_RC_OK;
|
return CHANNEL_RC_OK;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -453,7 +486,7 @@ static UINT guac_rdp_cliprdr_format_data_response(CliprdrClientContext* cliprdr,
|
|||||||
int length = strnlen(received_data, sizeof(received_data));
|
int length = strnlen(received_data, sizeof(received_data));
|
||||||
guac_common_clipboard_reset(clipboard->clipboard, "text/plain");
|
guac_common_clipboard_reset(clipboard->clipboard, "text/plain");
|
||||||
guac_common_clipboard_append(clipboard->clipboard, received_data, length);
|
guac_common_clipboard_append(clipboard->clipboard, received_data, length);
|
||||||
guac_common_clipboard_send(clipboard->clipboard, clipboard->client);
|
guac_common_clipboard_send(clipboard->clipboard, client);
|
||||||
}
|
}
|
||||||
|
|
||||||
return CHANNEL_RC_OK;
|
return CHANNEL_RC_OK;
|
||||||
|
@ -89,12 +89,16 @@ void guac_rdp_common_svc_write(guac_rdp_common_svc* svc,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
guac_rdp_client* rdp_client = (guac_rdp_client*) svc->client->data;
|
||||||
|
|
||||||
/* NOTE: The wStream sent via pVirtualChannelWriteEx will automatically be
|
/* NOTE: The wStream sent via pVirtualChannelWriteEx will automatically be
|
||||||
* freed later with a call to Stream_Free() when handling the
|
* freed later with a call to Stream_Free() when handling the
|
||||||
* corresponding write cancel/completion event. */
|
* corresponding write cancel/completion event. */
|
||||||
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
svc->_entry_points.pVirtualChannelWriteEx(svc->_init_handle,
|
svc->_entry_points.pVirtualChannelWriteEx(svc->_init_handle,
|
||||||
svc->_open_handle, Stream_Buffer(output_stream),
|
svc->_open_handle, Stream_Buffer(output_stream),
|
||||||
Stream_GetPosition(output_stream), output_stream);
|
Stream_GetPosition(output_stream), output_stream);
|
||||||
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,9 +31,10 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
guac_rdp_disp* guac_rdp_disp_alloc() {
|
guac_rdp_disp* guac_rdp_disp_alloc(guac_client* client) {
|
||||||
|
|
||||||
guac_rdp_disp* disp = malloc(sizeof(guac_rdp_disp));
|
guac_rdp_disp* disp = malloc(sizeof(guac_rdp_disp));
|
||||||
|
disp->client = client;
|
||||||
|
|
||||||
/* Not yet connected */
|
/* Not yet connected */
|
||||||
disp->disp = NULL;
|
disp->disp = NULL;
|
||||||
@ -220,8 +221,17 @@ void guac_rdp_disp_update_size(guac_rdp_disp* disp,
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
/* Send display update notification if display channel is connected */
|
/* Send display update notification if display channel is connected */
|
||||||
if (disp->disp != NULL)
|
if (disp->disp != NULL) {
|
||||||
|
|
||||||
|
guac_client* client = disp->client;
|
||||||
|
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
disp->disp->SendMonitorLayout(disp->disp, 1, monitors);
|
disp->disp->SendMonitorLayout(disp->disp, 1, monitors);
|
||||||
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,11 @@
|
|||||||
*/
|
*/
|
||||||
typedef struct guac_rdp_disp {
|
typedef struct guac_rdp_disp {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The guac_client instance handling the relevant RDP connection.
|
||||||
|
*/
|
||||||
|
guac_client* client;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display control interface.
|
* Display control interface.
|
||||||
*/
|
*/
|
||||||
@ -81,10 +86,13 @@ typedef struct guac_rdp_disp {
|
|||||||
* Allocates a new display update module, which will ultimately control the
|
* Allocates a new display update module, which will ultimately control the
|
||||||
* display update channel once connected.
|
* display update channel once connected.
|
||||||
*
|
*
|
||||||
|
* @param client
|
||||||
|
* The guac_client instance handling the relevant RDP connection.
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
* A newly-allocated display update module.
|
* A newly-allocated display update module.
|
||||||
*/
|
*/
|
||||||
guac_rdp_disp* guac_rdp_disp_alloc();
|
guac_rdp_disp* guac_rdp_disp_alloc(guac_client* client);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Frees the resources associated with support for the RDP Display Update
|
* Frees the resources associated with support for the RDP Display Update
|
||||||
|
@ -86,7 +86,10 @@ static UINT guac_rdp_rail_complete_handshake(RailClientContext* rail) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Send client handshake response */
|
/* Send client handshake response */
|
||||||
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
status = rail->ClientHandshake(rail, &handshake);
|
status = rail->ClientHandshake(rail, &handshake);
|
||||||
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
|
|
||||||
if (status != CHANNEL_RC_OK)
|
if (status != CHANNEL_RC_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
@ -95,7 +98,10 @@ static UINT guac_rdp_rail_complete_handshake(RailClientContext* rail) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Send client status */
|
/* Send client status */
|
||||||
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
status = rail->ClientInformation(rail, &client_status);
|
status = rail->ClientInformation(rail, &client_status);
|
||||||
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
|
|
||||||
if (status != CHANNEL_RC_OK)
|
if (status != CHANNEL_RC_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
@ -139,7 +145,10 @@ static UINT guac_rdp_rail_complete_handshake(RailClientContext* rail) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Send client system parameters */
|
/* Send client system parameters */
|
||||||
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
status = rail->ClientSystemParam(rail, &sysparam);
|
status = rail->ClientSystemParam(rail, &sysparam);
|
||||||
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
|
|
||||||
if (status != CHANNEL_RC_OK)
|
if (status != CHANNEL_RC_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
@ -151,7 +160,11 @@ static UINT guac_rdp_rail_complete_handshake(RailClientContext* rail) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Execute desired RemoteApp command */
|
/* Execute desired RemoteApp command */
|
||||||
return rail->ClientExecute(rail, &exec);
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
|
status = rail->ClientExecute(rail, &exec);
|
||||||
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
|
|
||||||
|
return status;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,9 +32,10 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
guac_rdp_rdpei* guac_rdp_rdpei_alloc() {
|
guac_rdp_rdpei* guac_rdp_rdpei_alloc(guac_client* client) {
|
||||||
|
|
||||||
guac_rdp_rdpei* rdpei = malloc(sizeof(guac_rdp_rdpei));
|
guac_rdp_rdpei* rdpei = malloc(sizeof(guac_rdp_rdpei));
|
||||||
|
rdpei->client = client;
|
||||||
|
|
||||||
/* Not yet connected */
|
/* Not yet connected */
|
||||||
rdpei->rdpei = NULL;
|
rdpei->rdpei = NULL;
|
||||||
@ -107,6 +108,9 @@ void guac_rdp_rdpei_load_plugin(rdpContext* context) {
|
|||||||
int guac_rdp_rdpei_touch_update(guac_rdp_rdpei* rdpei, int id, int x, int y,
|
int guac_rdp_rdpei_touch_update(guac_rdp_rdpei* rdpei, int id, int x, int y,
|
||||||
double force) {
|
double force) {
|
||||||
|
|
||||||
|
guac_client* client = rdpei->client;
|
||||||
|
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||||
|
|
||||||
int contact_id; /* Ignored */
|
int contact_id; /* Ignored */
|
||||||
|
|
||||||
/* Track touches only if channel is connected */
|
/* Track touches only if channel is connected */
|
||||||
@ -149,20 +153,31 @@ int guac_rdp_rdpei_touch_update(guac_rdp_rdpei* rdpei, int id, int x, int y,
|
|||||||
if (!touch->active)
|
if (!touch->active)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
context->TouchEnd(context, id, x, y, &contact_id);
|
context->TouchEnd(context, id, x, y, &contact_id);
|
||||||
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
|
|
||||||
touch->active = 0;
|
touch->active = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Signal the start of a touch if this is the first we've seen it */
|
/* Signal the start of a touch if this is the first we've seen it */
|
||||||
else if (!touch->active) {
|
else if (!touch->active) {
|
||||||
|
|
||||||
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
context->TouchBegin(context, id, x, y, &contact_id);
|
context->TouchBegin(context, id, x, y, &contact_id);
|
||||||
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
|
|
||||||
touch->active = 1;
|
touch->active = 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Established touches need only be updated */
|
/* Established touches need only be updated */
|
||||||
else
|
else {
|
||||||
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
context->TouchUpdate(context, id, x, y, &contact_id);
|
context->TouchUpdate(context, id, x, y, &contact_id);
|
||||||
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -66,6 +66,11 @@ typedef struct guac_rdp_rdpei_touch {
|
|||||||
*/
|
*/
|
||||||
typedef struct guac_rdp_rdpei {
|
typedef struct guac_rdp_rdpei {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The guac_client instance handling the relevant RDP connection.
|
||||||
|
*/
|
||||||
|
guac_client* client;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RDPEI control interface.
|
* RDPEI control interface.
|
||||||
*/
|
*/
|
||||||
@ -83,10 +88,13 @@ typedef struct guac_rdp_rdpei {
|
|||||||
* channel once connected. The RDPEI channel allows multi-touch input
|
* channel once connected. The RDPEI channel allows multi-touch input
|
||||||
* events to be sent to the RDP server.
|
* events to be sent to the RDP server.
|
||||||
*
|
*
|
||||||
|
* @param client
|
||||||
|
* The guac_client instance handling the relevant RDP connection.
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
* A newly-allocated RDPEI module.
|
* A newly-allocated RDPEI module.
|
||||||
*/
|
*/
|
||||||
guac_rdp_rdpei* guac_rdp_rdpei_alloc();
|
guac_rdp_rdpei* guac_rdp_rdpei_alloc(guac_client* client);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Frees the resources associated with support for the RDPEI channel. Only
|
* Frees the resources associated with support for the RDPEI channel. Only
|
||||||
|
@ -145,10 +145,10 @@ int guac_client_init(guac_client* client, int argc, char** argv) {
|
|||||||
rdp_client->clipboard = guac_rdp_clipboard_alloc(client);
|
rdp_client->clipboard = guac_rdp_clipboard_alloc(client);
|
||||||
|
|
||||||
/* Init display update module */
|
/* Init display update module */
|
||||||
rdp_client->disp = guac_rdp_disp_alloc();
|
rdp_client->disp = guac_rdp_disp_alloc(client);
|
||||||
|
|
||||||
/* Init multi-touch support module (RDPEI) */
|
/* Init multi-touch support module (RDPEI) */
|
||||||
rdp_client->rdpei = guac_rdp_rdpei_alloc();
|
rdp_client->rdpei = guac_rdp_rdpei_alloc(client);
|
||||||
|
|
||||||
/* Redirect FreeRDP log messages to guac_client_log() */
|
/* Redirect FreeRDP log messages to guac_client_log() */
|
||||||
guac_rdp_redirect_wlog(client);
|
guac_rdp_redirect_wlog(client);
|
||||||
@ -158,8 +158,9 @@ int guac_client_init(guac_client* client, int argc, char** argv) {
|
|||||||
pthread_mutexattr_settype(&(rdp_client->attributes),
|
pthread_mutexattr_settype(&(rdp_client->attributes),
|
||||||
PTHREAD_MUTEX_RECURSIVE);
|
PTHREAD_MUTEX_RECURSIVE);
|
||||||
|
|
||||||
/* Initalize the lock */
|
/* Init required locks */
|
||||||
pthread_rwlock_init(&(rdp_client->lock), NULL);
|
pthread_rwlock_init(&(rdp_client->lock), NULL);
|
||||||
|
pthread_mutex_init(&(rdp_client->message_lock), &(rdp_client->attributes));
|
||||||
|
|
||||||
/* Set handlers */
|
/* Set handlers */
|
||||||
client->join_handler = guac_rdp_user_join_handler;
|
client->join_handler = guac_rdp_user_join_handler;
|
||||||
@ -226,6 +227,7 @@ int guac_rdp_client_free_handler(guac_client* client) {
|
|||||||
guac_rdp_audio_buffer_free(rdp_client->audio_input);
|
guac_rdp_audio_buffer_free(rdp_client->audio_input);
|
||||||
|
|
||||||
pthread_rwlock_destroy(&(rdp_client->lock));
|
pthread_rwlock_destroy(&(rdp_client->lock));
|
||||||
|
pthread_mutex_destroy(&(rdp_client->message_lock));
|
||||||
|
|
||||||
/* Free client data */
|
/* Free client data */
|
||||||
free(rdp_client);
|
free(rdp_client);
|
||||||
|
@ -54,8 +54,11 @@ int guac_rdp_user_mouse_handler(guac_user* user, int x, int y, int mask) {
|
|||||||
guac_common_recording_report_mouse(rdp_client->recording, x, y, mask);
|
guac_common_recording_report_mouse(rdp_client->recording, x, y, mask);
|
||||||
|
|
||||||
/* If button mask unchanged, just send move event */
|
/* If button mask unchanged, just send move event */
|
||||||
if (mask == rdp_client->mouse_button_mask)
|
if (mask == rdp_client->mouse_button_mask) {
|
||||||
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
rdp_inst->input->MouseEvent(rdp_inst->input, PTR_FLAGS_MOVE, x, y);
|
rdp_inst->input->MouseEvent(rdp_inst->input, PTR_FLAGS_MOVE, x, y);
|
||||||
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
|
}
|
||||||
|
|
||||||
/* Otherwise, send events describing button change */
|
/* Otherwise, send events describing button change */
|
||||||
else {
|
else {
|
||||||
@ -75,7 +78,9 @@ int guac_rdp_user_mouse_handler(guac_user* user, int x, int y, int mask) {
|
|||||||
if (released_mask & 0x02) flags |= PTR_FLAGS_BUTTON3;
|
if (released_mask & 0x02) flags |= PTR_FLAGS_BUTTON3;
|
||||||
if (released_mask & 0x04) flags |= PTR_FLAGS_BUTTON2;
|
if (released_mask & 0x04) flags |= PTR_FLAGS_BUTTON2;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
rdp_inst->input->MouseEvent(rdp_inst->input, flags, x, y);
|
rdp_inst->input->MouseEvent(rdp_inst->input, flags, x, y);
|
||||||
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +96,9 @@ int guac_rdp_user_mouse_handler(guac_user* user, int x, int y, int mask) {
|
|||||||
if (pressed_mask & 0x10) flags |= PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x88;
|
if (pressed_mask & 0x10) flags |= PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x88;
|
||||||
|
|
||||||
/* Send event */
|
/* Send event */
|
||||||
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
rdp_inst->input->MouseEvent(rdp_inst->input, flags, x, y);
|
rdp_inst->input->MouseEvent(rdp_inst->input, flags, x, y);
|
||||||
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,18 +106,18 @@ int guac_rdp_user_mouse_handler(guac_user* user, int x, int y, int mask) {
|
|||||||
if (pressed_mask & 0x18) {
|
if (pressed_mask & 0x18) {
|
||||||
|
|
||||||
/* Down */
|
/* Down */
|
||||||
if (pressed_mask & 0x08)
|
if (pressed_mask & 0x08) {
|
||||||
rdp_inst->input->MouseEvent(
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
rdp_inst->input,
|
rdp_inst->input->MouseEvent(rdp_inst->input, PTR_FLAGS_WHEEL | 0x78, x, y);
|
||||||
PTR_FLAGS_WHEEL | 0x78,
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
x, y);
|
}
|
||||||
|
|
||||||
/* Up */
|
/* Up */
|
||||||
if (pressed_mask & 0x10)
|
if (pressed_mask & 0x10) {
|
||||||
rdp_inst->input->MouseEvent(
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
rdp_inst->input,
|
rdp_inst->input->MouseEvent(rdp_inst->input, PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x88, x, y);
|
||||||
PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x88,
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
x, y);
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,8 +104,9 @@ static void guac_rdp_send_key_event(guac_rdp_client* rdp_client,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* Send actual key */
|
/* Send actual key */
|
||||||
rdp_inst->input->KeyboardEvent(rdp_inst->input,
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
flags | pressed_flags, scancode);
|
rdp_inst->input->KeyboardEvent(rdp_inst->input, flags | pressed_flags, scancode);
|
||||||
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,9 +133,9 @@ static void guac_rdp_send_unicode_event(guac_rdp_client* rdp_client,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* Send Unicode event */
|
/* Send Unicode event */
|
||||||
rdp_inst->input->UnicodeKeyboardEvent(
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
rdp_inst->input,
|
rdp_inst->input->UnicodeKeyboardEvent(rdp_inst->input, 0, codepoint);
|
||||||
0, codepoint);
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,7 +162,9 @@ static void guac_rdp_send_synchronize_event(guac_rdp_client* rdp_client,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* Synchronize lock key states */
|
/* Synchronize lock key states */
|
||||||
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
rdp_inst->input->SynchronizeEvent(rdp_inst->input, flags);
|
rdp_inst->input->SynchronizeEvent(rdp_inst->input, flags);
|
||||||
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,6 +247,8 @@ static void guac_rdp_ai_send_formatchange(IWTSVirtualChannel* channel,
|
|||||||
void guac_rdp_ai_process_version(guac_client* client,
|
void guac_rdp_ai_process_version(guac_client* client,
|
||||||
IWTSVirtualChannel* channel, wStream* stream) {
|
IWTSVirtualChannel* channel, wStream* stream) {
|
||||||
|
|
||||||
|
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||||
|
|
||||||
/* Verify we have at least 4 bytes available (UINT32) */
|
/* Verify we have at least 4 bytes available (UINT32) */
|
||||||
if (Stream_GetRemainingLength(stream) < 4) {
|
if (Stream_GetRemainingLength(stream) < 4) {
|
||||||
guac_client_log(client, GUAC_LOG_WARNING, "Audio input Versoin PDU "
|
guac_client_log(client, GUAC_LOG_WARNING, "Audio input Versoin PDU "
|
||||||
@ -269,8 +271,9 @@ void guac_rdp_ai_process_version(guac_client* client,
|
|||||||
Stream_Write_UINT32(response, 1); /* Version */
|
Stream_Write_UINT32(response, 1); /* Version */
|
||||||
|
|
||||||
/* Send response */
|
/* Send response */
|
||||||
channel->Write(channel, (UINT32) Stream_GetPosition(response),
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
Stream_Buffer(response), NULL);
|
channel->Write(channel, (UINT32) Stream_GetPosition(response), Stream_Buffer(response), NULL);
|
||||||
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
Stream_Free(response, TRUE);
|
Stream_Free(response, TRUE);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -313,26 +316,34 @@ void guac_rdp_ai_process_formats(guac_client* client,
|
|||||||
format.channels, format.bps / 8);
|
format.channels, format.bps / 8);
|
||||||
|
|
||||||
/* Accept single format */
|
/* Accept single format */
|
||||||
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
guac_rdp_ai_send_incoming_data(channel);
|
guac_rdp_ai_send_incoming_data(channel);
|
||||||
guac_rdp_ai_send_formats(channel, &format, 1);
|
guac_rdp_ai_send_formats(channel, &format, 1);
|
||||||
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No formats available */
|
/* No formats available */
|
||||||
guac_client_log(client, GUAC_LOG_WARNING, "AUDIO_INPUT: No WAVE format.");
|
guac_client_log(client, GUAC_LOG_WARNING, "AUDIO_INPUT: No WAVE format.");
|
||||||
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
guac_rdp_ai_send_incoming_data(channel);
|
guac_rdp_ai_send_incoming_data(channel);
|
||||||
guac_rdp_ai_send_formats(channel, NULL, 0);
|
guac_rdp_ai_send_formats(channel, NULL, 0);
|
||||||
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void guac_rdp_ai_flush_packet(char* buffer, int length, void* data) {
|
void guac_rdp_ai_flush_packet(guac_rdp_audio_buffer* audio_buffer, int length) {
|
||||||
|
|
||||||
IWTSVirtualChannel* channel = (IWTSVirtualChannel*) data;
|
guac_client* client = audio_buffer->client;
|
||||||
|
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||||
|
IWTSVirtualChannel* channel = (IWTSVirtualChannel*) audio_buffer->data;
|
||||||
|
|
||||||
/* Send data over channel */
|
/* Send data over channel */
|
||||||
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
guac_rdp_ai_send_incoming_data(channel);
|
guac_rdp_ai_send_incoming_data(channel);
|
||||||
guac_rdp_ai_send_data(channel, buffer, length);
|
guac_rdp_ai_send_data(channel, audio_buffer->packet, length);
|
||||||
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -363,8 +374,10 @@ void guac_rdp_ai_process_open(guac_client* client,
|
|||||||
audio_buffer->out_format.bps);
|
audio_buffer->out_format.bps);
|
||||||
|
|
||||||
/* Success */
|
/* Success */
|
||||||
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
guac_rdp_ai_send_formatchange(channel, initial_format);
|
guac_rdp_ai_send_formatchange(channel, initial_format);
|
||||||
guac_rdp_ai_send_open_reply(channel, 0);
|
guac_rdp_ai_send_open_reply(channel, 0);
|
||||||
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
|
|
||||||
/* Begin receiving audio data */
|
/* Begin receiving audio data */
|
||||||
guac_rdp_audio_buffer_begin(audio_buffer, packet_frames,
|
guac_rdp_audio_buffer_begin(audio_buffer, packet_frames,
|
||||||
|
@ -107,7 +107,7 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) {
|
|||||||
|
|
||||||
/* Load "AUDIO_INPUT" plugin for audio input*/
|
/* Load "AUDIO_INPUT" plugin for audio input*/
|
||||||
if (settings->enable_audio_input) {
|
if (settings->enable_audio_input) {
|
||||||
rdp_client->audio_input = guac_rdp_audio_buffer_alloc();
|
rdp_client->audio_input = guac_rdp_audio_buffer_alloc(client);
|
||||||
guac_rdp_audio_load_plugin(instance->context);
|
guac_rdp_audio_load_plugin(instance->context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -564,13 +564,16 @@ static int guac_rdp_handle_connection(guac_client* client) {
|
|||||||
guac_timestamp frame_end;
|
guac_timestamp frame_end;
|
||||||
int frame_remaining;
|
int frame_remaining;
|
||||||
|
|
||||||
/* Check the libfreerdp fds */
|
/* Handle any queued FreeRDP events (this may result in RDP
|
||||||
if (!freerdp_check_event_handles(rdp_inst->context)) {
|
* messages being sent) */
|
||||||
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
|
int event_result = freerdp_check_event_handles(rdp_inst->context);
|
||||||
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
|
|
||||||
/* Flag connection failure */
|
/* Abort if FreeRDP event handling fails */
|
||||||
|
if (!event_result) {
|
||||||
wait_result = -1;
|
wait_result = -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate time remaining in frame */
|
/* Calculate time remaining in frame */
|
||||||
@ -634,7 +637,9 @@ static int guac_rdp_handle_connection(guac_client* client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Disconnect client and channels */
|
/* Disconnect client and channels */
|
||||||
|
pthread_mutex_lock(&(rdp_client->message_lock));
|
||||||
freerdp_disconnect(rdp_inst);
|
freerdp_disconnect(rdp_inst);
|
||||||
|
pthread_mutex_unlock(&(rdp_client->message_lock));
|
||||||
|
|
||||||
/* Clean up FreeRDP internal GDI implementation */
|
/* Clean up FreeRDP internal GDI implementation */
|
||||||
gdi_free(rdp_inst);
|
gdi_free(rdp_inst);
|
||||||
|
@ -172,6 +172,12 @@ typedef struct guac_rdp_client {
|
|||||||
*/
|
*/
|
||||||
pthread_rwlock_t lock;
|
pthread_rwlock_t lock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lock which synchronizes the sending of each RDP message, ensuring
|
||||||
|
* attempts to send RDP messages never overlap.
|
||||||
|
*/
|
||||||
|
pthread_mutex_t message_lock;
|
||||||
|
|
||||||
} guac_rdp_client;
|
} guac_rdp_client;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user