Compare commits
1 Commits
master
...
working/rd
Author | SHA1 | Date | |
---|---|---|---|
|
2cff6c6b73 |
@ -717,3 +717,62 @@ int guac_client_supports_webp(guac_client* client) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A callback that it is invokved by the call to guac_client_owner_send_uri
|
||||
* which sends the 'uri" instruction and parameter to the specified user, who
|
||||
* is the owner of the connection.
|
||||
*
|
||||
* @param user
|
||||
* The user to send the "uri" instruction and parameter to, who owns the
|
||||
* connection.
|
||||
*
|
||||
* @param data
|
||||
* The URI to send to the owner, cast as a void*.
|
||||
*
|
||||
* @return
|
||||
* Zero if the operation succeeds or non-zero on failure.
|
||||
*/
|
||||
static void* guac_client_owner_send_uri_callback(guac_user* user, void* data) {
|
||||
|
||||
const char* uri = (const char *) data;
|
||||
|
||||
/* Send uri parameter to owner. */
|
||||
if (user != NULL)
|
||||
return (void*) ((intptr_t) guac_protocol_send_uri(user->socket, uri));
|
||||
|
||||
return (void*) ((intptr_t) -1);
|
||||
}
|
||||
|
||||
int guac_client_owner_send_uri(guac_client* client, const char* uri) {
|
||||
|
||||
/* Don't send the uri instruction if the client does not support it. */
|
||||
if (!guac_client_owner_supports_uri(client))
|
||||
return -1;
|
||||
|
||||
return (int) ((intptr_t) guac_client_for_owner(client, guac_client_owner_send_uri_callback, (void *) uri));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback function that is invoked by guac_client_owner_supports_uri to
|
||||
* determine if the owner of a connection supports the "uri" instruction,
|
||||
* so that Guacamole can pass URIs to the client browser.
|
||||
*
|
||||
* @param user
|
||||
* The user that is being checked for URI support, which should be the
|
||||
* owner of the connection.
|
||||
*
|
||||
* @param data
|
||||
* Additional data - this will always be null.
|
||||
*
|
||||
* @return
|
||||
* A non-zero integer if the user supports the "uri" instruction, otherwise
|
||||
* zero to indicate a lack of URI support.
|
||||
*/
|
||||
static void* guac_owner_supports_uri_callback(guac_user* user, void* data) {
|
||||
return (void*) ((intptr_t) guac_user_supports_uri(user));
|
||||
}
|
||||
|
||||
int guac_client_owner_supports_uri(guac_client* client) {
|
||||
return (int) ((intptr_t) guac_client_for_owner(client, guac_owner_supports_uri_callback, NULL));
|
||||
}
|
@ -565,6 +565,22 @@ int guac_client_get_processing_lag(guac_client* client);
|
||||
*/
|
||||
int guac_client_owner_send_required(guac_client* client, const char** required);
|
||||
|
||||
/**
|
||||
* Sends the "uri" instruction to the given guac_client so that the remote
|
||||
* client can process the URI, if the client supports it and has a handler
|
||||
* configured for the URI.
|
||||
*
|
||||
* @param client
|
||||
* The client to which to send the URI instruction.
|
||||
*
|
||||
* @param uri
|
||||
* The URI to send to the remote client.
|
||||
*
|
||||
* @return
|
||||
* Zero on success, non-zero on failure.
|
||||
*/
|
||||
int guac_client_owner_send_uri(guac_client* client, const char* uri);
|
||||
|
||||
/**
|
||||
* Streams the given connection parameter value over an argument value stream
|
||||
* ("argv" instruction), exposing the current value of the named connection
|
||||
@ -736,6 +752,8 @@ int guac_client_owner_supports_required(guac_client* client);
|
||||
*/
|
||||
int guac_client_supports_webp(guac_client* client);
|
||||
|
||||
int guac_client_owner_supports_uri(guac_client* client);
|
||||
|
||||
/**
|
||||
* The default Guacamole client layer, layer 0.
|
||||
*/
|
||||
|
@ -38,7 +38,7 @@
|
||||
* This version is passed by the __guac_protocol_send_args() function from the
|
||||
* server to the client during the client/server handshake.
|
||||
*/
|
||||
#define GUACAMOLE_PROTOCOL_VERSION "VERSION_1_3_0"
|
||||
#define GUACAMOLE_PROTOCOL_VERSION "VERSION_1_6_0"
|
||||
|
||||
/**
|
||||
* The maximum number of bytes that should be sent in any one blob instruction
|
||||
|
@ -306,7 +306,13 @@ typedef enum guac_protocol_version {
|
||||
* allowing connections in guacd to request information from the client and
|
||||
* await a response.
|
||||
*/
|
||||
GUAC_PROTOCOL_VERSION_1_3_0 = 0x010300
|
||||
GUAC_PROTOCOL_VERSION_1_3_0 = 0x010300,
|
||||
|
||||
/**
|
||||
* Protocol version 1.6.0, which supports the "uri" instruction, allowing
|
||||
* remote systems to send
|
||||
*/
|
||||
GUAC_PROTOCOL_VERSION_1_6_0 = 0x010600
|
||||
|
||||
} guac_protocol_version;
|
||||
|
||||
|
@ -1037,6 +1037,21 @@ int guac_protocol_send_shade(guac_socket* socket, const guac_layer* layer,
|
||||
int guac_protocol_send_size(guac_socket* socket, const guac_layer* layer,
|
||||
int w, int h);
|
||||
|
||||
/**
|
||||
* Send the uri instruction over the given guac_socket connection,
|
||||
* providing a URI that the client should then process locally.
|
||||
*
|
||||
* @param socket
|
||||
* The guac_socket connection to which to send the uri instruction.
|
||||
*
|
||||
* @param uri
|
||||
* The URI that should be sent to the client.
|
||||
*
|
||||
* @return
|
||||
* Zero on success, non-zero on error.
|
||||
*/
|
||||
int guac_protocol_send_uri(guac_socket* socket, const char* uri);
|
||||
|
||||
/* TEXT INSTRUCTIONS */
|
||||
|
||||
/**
|
||||
|
@ -861,6 +861,17 @@ void guac_user_stream_webp(guac_user* user, guac_socket* socket,
|
||||
*/
|
||||
int guac_user_supports_required(guac_user* user);
|
||||
|
||||
/**
|
||||
* Returns non-zero if the user supports the "uri" instruction.
|
||||
*
|
||||
* @param user
|
||||
* The Guacamole user to check for support of the "uri" instruction.
|
||||
*
|
||||
* @return
|
||||
* Non-zero if the user supports the "uri" instruction, otherwise zero.
|
||||
*/
|
||||
int guac_user_supports_uri(guac_user* user);
|
||||
|
||||
/**
|
||||
* Returns whether the given user supports WebP. If the user does not
|
||||
* support WebP, or the server cannot encode WebP images, zero is returned.
|
||||
|
@ -65,6 +65,7 @@ guac_protocol_version_mapping guac_protocol_version_table[] = {
|
||||
{ GUAC_PROTOCOL_VERSION_1_0_0, "VERSION_1_0_0" },
|
||||
{ GUAC_PROTOCOL_VERSION_1_1_0, "VERSION_1_1_0" },
|
||||
{ GUAC_PROTOCOL_VERSION_1_3_0, "VERSION_1_3_0" },
|
||||
{ GUAC_PROTOCOL_VERSION_1_6_0, "VERSION_1_6_0" },
|
||||
{ GUAC_PROTOCOL_VERSION_UNKNOWN, NULL }
|
||||
};
|
||||
|
||||
@ -1274,6 +1275,21 @@ int guac_protocol_send_undefine(guac_socket* socket,
|
||||
|
||||
}
|
||||
|
||||
int guac_protocol_send_uri(guac_socket* socket, const char* uri) {
|
||||
|
||||
int ret_val;
|
||||
|
||||
guac_socket_instruction_begin(socket);
|
||||
ret_val =
|
||||
guac_socket_write_string(socket, "3.uri,")
|
||||
|| __guac_socket_write_length_string(socket, uri)
|
||||
|| guac_socket_write_string(socket, ";");
|
||||
|
||||
guac_socket_instruction_end(socket);
|
||||
return ret_val;
|
||||
|
||||
}
|
||||
|
||||
int guac_protocol_send_video(guac_socket* socket, const guac_stream* stream,
|
||||
const guac_layer* layer, const char* mimetype) {
|
||||
|
||||
|
@ -325,6 +325,14 @@ int guac_user_supports_required(guac_user* user) {
|
||||
|
||||
}
|
||||
|
||||
int guac_user_supports_uri(guac_user* user) {
|
||||
|
||||
if (user == NULL)
|
||||
return 0;
|
||||
|
||||
return (user->info.protocol_version >= GUAC_PROTOCOL_VERSION_1_6_0);
|
||||
}
|
||||
|
||||
int guac_user_supports_webp(guac_user* user) {
|
||||
|
||||
#ifdef ENABLE_WEBP
|
||||
|
@ -59,6 +59,7 @@ libguac_client_rdp_la_SOURCES = \
|
||||
channels/rdpei.c \
|
||||
channels/rdpsnd/rdpsnd-messages.c \
|
||||
channels/rdpsnd/rdpsnd.c \
|
||||
channels/rdpuri.c \
|
||||
client.c \
|
||||
color.c \
|
||||
decompose.c \
|
||||
@ -105,6 +106,7 @@ noinst_HEADERS = \
|
||||
channels/rdpei.h \
|
||||
channels/rdpsnd/rdpsnd-messages.h \
|
||||
channels/rdpsnd/rdpsnd.h \
|
||||
channels/rdpuri.h \
|
||||
client.h \
|
||||
color.h \
|
||||
decompose.h \
|
||||
|
133
src/protocols/rdp/channels/rdpuri.c
Normal file
133
src/protocols/rdp/channels/rdpuri.c
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "channels/rdpuri.h"
|
||||
#include "client.h"
|
||||
#include "config.h"
|
||||
#include "plugins/channels.h"
|
||||
#include "rdp.h"
|
||||
#include "unicode.h"
|
||||
|
||||
#include <freerdp/client/cliprdr.h>
|
||||
#include <freerdp/event.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <guacamole/client.h>
|
||||
#include <guacamole/stream.h>
|
||||
#include <guacamole/user.h>
|
||||
#include <winpr/wtsapi.h>
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* Callback which associates handlers specific to Guacamole with the
|
||||
* CliprdrClientContext instance allocated by FreeRDP to deal with received
|
||||
* CLIPRDR (clipboard redirection) messages.
|
||||
*
|
||||
* This function is called whenever a channel connects via the PubSub event
|
||||
* system within FreeRDP, but only has any effect if the connected channel is
|
||||
* the CLIPRDR channel. This specific callback is registered with the PubSub
|
||||
* system of the relevant rdpContext when guac_rdp_clipboard_load_plugin() is
|
||||
* called.
|
||||
*
|
||||
* @param context
|
||||
* The rdpContext associated with the active RDP session.
|
||||
*
|
||||
* @param e
|
||||
* Event-specific arguments, mainly the name of the channel, and a
|
||||
* reference to the associated plugin loaded for that channel by FreeRDP.
|
||||
*/
|
||||
static void guac_rdpuri_channel_connected(guac_rdp_common_svc* svc) {
|
||||
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG, "RDPURI (URI redirection) "
|
||||
"channel connected.");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback which disassociates Guacamole from the CliprdrClientContext
|
||||
* instance that was originally allocated by FreeRDP and is about to be
|
||||
* deallocated.
|
||||
*
|
||||
* This function is called whenever a channel disconnects via the PubSub event
|
||||
* system within FreeRDP, but only has any effect if the disconnected channel
|
||||
* is the CLIPRDR channel. This specific callback is registered with the PubSub
|
||||
* system of the relevant rdpContext when guac_rdp_clipboard_load_plugin() is
|
||||
* called.
|
||||
*
|
||||
* @param context
|
||||
* The rdpContext associated with the active RDP session.
|
||||
*
|
||||
* @param e
|
||||
* Event-specific arguments, mainly the name of the channel, and a
|
||||
* reference to the associated plugin loaded for that channel by FreeRDP.
|
||||
*/
|
||||
static void guac_rdpuri_channel_disconnected(guac_rdp_common_svc* svc) {
|
||||
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG, "RDPURI (URI redirection) "
|
||||
"channel disconnected.");
|
||||
|
||||
}
|
||||
|
||||
static void guac_rdpuri_channel_receive(guac_rdp_common_svc* svc, wStream* input_stream) {
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG, "RDPURI (URI redirection) "
|
||||
"channel received data.");
|
||||
|
||||
// int len = Stream_Length(input_stream);
|
||||
int len = Stream_Length(input_stream);
|
||||
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG, "Received URI %d in length.", len);
|
||||
|
||||
if (len < 1) {
|
||||
guac_client_log(svc->client, GUAC_LOG_WARNING, "Received URI data is too "
|
||||
"small.");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Convert input stream to UTF8 and send it to the client. */
|
||||
char uri[len/2];
|
||||
guac_rdp_utf16_to_utf8(Stream_Pointer(input_stream), len/2 - 1, uri, sizeof(uri));
|
||||
guac_client_log(svc->client, GUAC_LOG_DEBUG, "Received URI from server: %s", uri);
|
||||
guac_client_owner_send_uri(svc->client, uri);
|
||||
|
||||
}
|
||||
|
||||
void guac_rdpuri_load_plugin(rdpContext* context) {
|
||||
|
||||
guac_client* client = ((rdp_freerdp_context*) context)->client;
|
||||
|
||||
/* Attempt to load FreeRDP support for the CLIPRDR channel */
|
||||
if (guac_rdp_common_svc_load_plugin(context, "rdpuri", 0,
|
||||
guac_rdpuri_channel_connected, guac_rdpuri_channel_receive,
|
||||
guac_rdpuri_channel_disconnected)) {
|
||||
guac_client_log(client, GUAC_LOG_WARNING,
|
||||
"Support for the RDPURI channel (URI redirection) "
|
||||
"could not be loaded. This support normally takes the form of "
|
||||
"a plugin which is built into FreeRDP. Lacking this support, "
|
||||
"URI redirection will not work.");
|
||||
return;
|
||||
}
|
||||
|
||||
guac_client_log(client, GUAC_LOG_DEBUG, "Support for RDPURI "
|
||||
"(URI redirection) registered. Awaiting channel "
|
||||
"connection.");
|
||||
|
||||
}
|
45
src/protocols/rdp/channels/rdpuri.h
Normal file
45
src/protocols/rdp/channels/rdpuri.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef GUAC_RDP_CHANNELS_RDPURI_H
|
||||
#define GUAC_RDP_CHANNELS_RDPURI_H
|
||||
|
||||
#include "channels/common-svc.h"
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <guacamole/client.h>
|
||||
#include <guacamole/user.h>
|
||||
#include <winpr/stream.h>
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
/**
|
||||
* Initializes clipboard support for RDP and handling of the RDPURI channel.
|
||||
* If failures occur, messages noting the specifics of those failures will be
|
||||
* logged, and the RDP side of URI redirection will not be functional.
|
||||
*
|
||||
* This MUST be called within the PreConnect callback of the freerdp instance
|
||||
* for RDPURI support to be loaded.
|
||||
*
|
||||
* @param context
|
||||
* The rdpContext associated with the FreeRDP side of the RDP connection.
|
||||
*/
|
||||
void guac_rdpuri_load_plugin(rdpContext* context);
|
||||
|
||||
#endif
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "channels/rdpdr/rdpdr.h"
|
||||
#include "channels/rdpei.h"
|
||||
#include "channels/rdpsnd/rdpsnd.h"
|
||||
#include "channels/rdpuri.h"
|
||||
#include "client.h"
|
||||
#include "color.h"
|
||||
#include "common/cursor.h"
|
||||
@ -123,6 +124,9 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) {
|
||||
guac_rdpsnd_load_plugin(context);
|
||||
}
|
||||
|
||||
/* Load rdpuri service */
|
||||
guac_rdpuri_load_plugin(context);
|
||||
|
||||
/* Load RAIL plugin if RemoteApp in use */
|
||||
if (settings->remote_app != NULL)
|
||||
guac_rdp_rail_load_plugin(context);
|
||||
|
Loading…
Reference in New Issue
Block a user