/* * 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_COMMON_SVC_H #define GUAC_RDP_CHANNELS_COMMON_SVC_H #include #include #include #include #include #include #include /** * The maximum number of bytes to allow within each channel name, including * null terminator. */ #define GUAC_RDP_SVC_MAX_LENGTH 8 /** * The maximum number of bytes that the RDP server will be allowed to send * within any single write operation, regardless of the number of chunks that * write is split into. Bytes beyond this limit may be dropped. */ #define GUAC_SVC_MAX_ASSEMBLED_LENGTH 1048576 /** * Structure describing a static virtual channel, and the corresponding * Guacamole pipes and FreeRDP resources. */ typedef struct guac_rdp_common_svc guac_rdp_common_svc; /** * Handler which is invoked when a CHANNEL_EVENT_CONNECTED event has been * processed and the connection/initialization process of the SVC is now * complete. * * @param svc * The guac_rdp_common_svc structure representing the SVC that is now * connected. */ typedef void guac_rdp_common_svc_connect_handler(guac_rdp_common_svc* svc); /** * Handler which is invoked when a logical block of data has been received * along an SVC, having been reassembled from a series of * CHANNEL_EVENT_DATA_RECEIVED events. * * @param svc * The guac_rdp_common_svc structure representing the SVC that received the * data. * * @param input_stream * The reassembled block of data that was received. */ typedef void guac_rdp_common_svc_receive_handler(guac_rdp_common_svc* svc, wStream* input_stream); /** * Handler which is invoked when a CHANNEL_EVENT_TERMINATED event has been * processed and all resources associated with the SVC must now be freed. * * @param svc * The guac_rdp_common_svc structure representing the SVC that has been * terminated. */ typedef void guac_rdp_common_svc_terminate_handler(guac_rdp_common_svc* svc); struct guac_rdp_common_svc { /** * Reference to the client owning this static channel. */ guac_client* client; /** * The name of the static virtual channel, as specified to * guac_rdp_common_svc_load_plugin(). This value is stored and defined * internally by the CHANNEL_DEF. */ const char* name; /** * Arbitrary channel-specific data which may be assigned and referenced by * channel implementations leveraging the "guac-common-svc" plugin. */ void* data; /** * Handler which is invoked when handling a CHANNEL_EVENT_CONNECTED event. */ guac_rdp_common_svc_connect_handler* _connect_handler; /** * Handler which is invoked when all chunks of data for a single logical * block have been received via CHANNEL_EVENT_DATA_RECEIVED events and * reassembled. */ guac_rdp_common_svc_receive_handler* _receive_handler; /** * Handler which is invokved when the SVC has been disconnected and is * about to be freed. */ guac_rdp_common_svc_terminate_handler* _terminate_handler; /** * The definition of this static virtual channel, including its name. */ CHANNEL_DEF _channel_def; /** * Functions and data specific to the FreeRDP side of the virtual channel * and plugin. */ CHANNEL_ENTRY_POINTS_FREERDP_EX _entry_points; /** * Handle which identifies the client connection, typically referred to * within the FreeRDP source as pInitHandle. This handle is provided to the * channel entry point and the channel init event handler. The handle must * eventually be used within the channel open event handler to obtain a * handle to the channel itself. */ PVOID _init_handle; /** * Handle which identifies the channel itself, typically referred to within * the FreeRDP source as OpenHandle. This handle is obtained through a call * to entry_points.pVirtualChannelOpenEx() in response to receiving a * CHANNEL_EVENT_CONNECTED event via the init event handler. * * Data is received in CHANNEL_EVENT_DATA_RECEIVED events via the open * event handler, and data is written through calls to * entry_points.pVirtualChannelWriteEx(). */ DWORD _open_handle; /** * All data that has been received thus far from the current RDP server * write operation. Data received along virtual channels is sent in chunks * (typically 1600 bytes), and thus must be gradually reassembled as it is * received. */ wStream* _input_stream; }; /** * Initializes arbitrary static virtual channel (SVC) support for RDP, loading * a new instance of Guacamole's arbitrary SVC plugin for FreeRDP ("guacsvc") * supporting the channel having the given name. Data sent from within the RDP * session using this channel will be sent along an identically-named pipe * stream to the Guacamole client, and data sent along a pipe stream having the * same name will be written to the SVC and received within the RDP session. If * failures occur while loading the plugin, messages noting the specifics of * those failures will be logged, and support for the given channel will not be * functional. * * This MUST be called within the PreConnect callback of the freerdp instance * for static virtual channel support to be loaded. * * @param context * The rdpContext associated with the FreeRDP side of the RDP connection. * * @param name * The name of the SVC which should be handled by the new instance of the * plugin. * * @param channel_options * Bitwise OR of any of the several CHANNEL_OPTION_* flags. Regardless of * whether specified here, the CHANNEL_OPTION_INTIALIZED and * CHANNEL_OPTION_ENCRYPT_RDP flags will automatically be set. * * @param connect_handler * The function to invoke when the SVC has been connected. * * @param receive_handler * The function to invoke when the SVC has received a logical block of * data, reassembled from perhaps several smaller chunks of data. * * @param terminate_handler * The function to invoke when the SVC has been disconnected and is about * to be freed. * * @return * Zero if the plugin was loaded successfully, non-zero if the plugin could * not be loaded. */ int guac_rdp_common_svc_load_plugin(rdpContext* context, char* name, ULONG channel_options, guac_rdp_common_svc_connect_handler* connect_handler, guac_rdp_common_svc_receive_handler* receive_handler, guac_rdp_common_svc_terminate_handler* terminate_handler); /** * Writes the given data to the virtual channel such that it can be received * within the RDP session. The given data MUST be dynamically allocated, as the * write operation may be queued and the actual write may not occur until * later. The provided wStream and the buffer it points to will be * automatically freed after the write occurs. * * @param svc * The static virtual channel to write data to. * * @param output_stream * The data to write, which MUST be dynamically allocated. */ void guac_rdp_common_svc_write(guac_rdp_common_svc* svc, wStream* output_stream); #endif