common-svc.h (8108B)
1/* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 20#ifndef GUAC_RDP_CHANNELS_COMMON_SVC_H 21#define GUAC_RDP_CHANNELS_COMMON_SVC_H 22 23#include <freerdp/freerdp.h> 24#include <freerdp/svc.h> 25#include <guacamole/client.h> 26#include <guacamole/stream.h> 27#include <winpr/stream.h> 28#include <winpr/wtsapi.h> 29#include <winpr/wtypes.h> 30 31/** 32 * The maximum number of bytes to allow within each channel name, including 33 * null terminator. 34 */ 35#define GUAC_RDP_SVC_MAX_LENGTH 8 36 37/** 38 * The maximum number of bytes that the RDP server will be allowed to send 39 * within any single write operation, regardless of the number of chunks that 40 * write is split into. Bytes beyond this limit may be dropped. 41 */ 42#define GUAC_SVC_MAX_ASSEMBLED_LENGTH 1048576 43 44/** 45 * Structure describing a static virtual channel, and the corresponding 46 * Guacamole pipes and FreeRDP resources. 47 */ 48typedef struct guac_rdp_common_svc guac_rdp_common_svc; 49 50/** 51 * Handler which is invoked when a CHANNEL_EVENT_CONNECTED event has been 52 * processed and the connection/initialization process of the SVC is now 53 * complete. 54 * 55 * @param svc 56 * The guac_rdp_common_svc structure representing the SVC that is now 57 * connected. 58 */ 59typedef void guac_rdp_common_svc_connect_handler(guac_rdp_common_svc* svc); 60 61/** 62 * Handler which is invoked when a logical block of data has been received 63 * along an SVC, having been reassembled from a series of 64 * CHANNEL_EVENT_DATA_RECEIVED events. 65 * 66 * @param svc 67 * The guac_rdp_common_svc structure representing the SVC that received the 68 * data. 69 * 70 * @param input_stream 71 * The reassembled block of data that was received. 72 */ 73typedef void guac_rdp_common_svc_receive_handler(guac_rdp_common_svc* svc, wStream* input_stream); 74 75/** 76 * Handler which is invoked when a CHANNEL_EVENT_TERMINATED event has been 77 * processed and all resources associated with the SVC must now be freed. 78 * 79 * @param svc 80 * The guac_rdp_common_svc structure representing the SVC that has been 81 * terminated. 82 */ 83typedef void guac_rdp_common_svc_terminate_handler(guac_rdp_common_svc* svc); 84 85struct guac_rdp_common_svc { 86 87 /** 88 * Reference to the client owning this static channel. 89 */ 90 guac_client* client; 91 92 /** 93 * The name of the static virtual channel, as specified to 94 * guac_rdp_common_svc_load_plugin(). This value is stored and defined 95 * internally by the CHANNEL_DEF. 96 */ 97 const char* name; 98 99 /** 100 * Arbitrary channel-specific data which may be assigned and referenced by 101 * channel implementations leveraging the "guac-common-svc" plugin. 102 */ 103 void* data; 104 105 /** 106 * Handler which is invoked when handling a CHANNEL_EVENT_CONNECTED event. 107 */ 108 guac_rdp_common_svc_connect_handler* _connect_handler; 109 110 /** 111 * Handler which is invoked when all chunks of data for a single logical 112 * block have been received via CHANNEL_EVENT_DATA_RECEIVED events and 113 * reassembled. 114 */ 115 guac_rdp_common_svc_receive_handler* _receive_handler; 116 117 /** 118 * Handler which is involved when the SVC has been disconnected and is 119 * about to be freed. 120 */ 121 guac_rdp_common_svc_terminate_handler* _terminate_handler; 122 123 /** 124 * The definition of this static virtual channel, including its name. 125 */ 126 CHANNEL_DEF _channel_def; 127 128 /** 129 * Functions and data specific to the FreeRDP side of the virtual channel 130 * and plugin. 131 */ 132 CHANNEL_ENTRY_POINTS_FREERDP_EX _entry_points; 133 134 /** 135 * Handle which identifies the client connection, typically referred to 136 * within the FreeRDP source as pInitHandle. This handle is provided to the 137 * channel entry point and the channel init event handler. The handle must 138 * eventually be used within the channel open event handler to obtain a 139 * handle to the channel itself. 140 */ 141 PVOID _init_handle; 142 143 /** 144 * Handle which identifies the channel itself, typically referred to within 145 * the FreeRDP source as OpenHandle. This handle is obtained through a call 146 * to entry_points.pVirtualChannelOpenEx() in response to receiving a 147 * CHANNEL_EVENT_CONNECTED event via the init event handler. 148 * 149 * Data is received in CHANNEL_EVENT_DATA_RECEIVED events via the open 150 * event handler, and data is written through calls to 151 * entry_points.pVirtualChannelWriteEx(). 152 */ 153 DWORD _open_handle; 154 155 /** 156 * All data that has been received thus far from the current RDP server 157 * write operation. Data received along virtual channels is sent in chunks 158 * (typically 1600 bytes), and thus must be gradually reassembled as it is 159 * received. 160 */ 161 wStream* _input_stream; 162 163}; 164 165/** 166 * Initializes arbitrary static virtual channel (SVC) support for RDP, loading 167 * a new instance of Guacamole's arbitrary SVC plugin for FreeRDP ("guacsvc") 168 * supporting the channel having the given name. Data sent from within the RDP 169 * session using this channel will be sent along an identically-named pipe 170 * stream to the Guacamole client, and data sent along a pipe stream having the 171 * same name will be written to the SVC and received within the RDP session. If 172 * failures occur while loading the plugin, messages noting the specifics of 173 * those failures will be logged, and support for the given channel will not be 174 * functional. 175 * 176 * This MUST be called within the PreConnect callback of the freerdp instance 177 * for static virtual channel support to be loaded. 178 * 179 * @param context 180 * The rdpContext associated with the FreeRDP side of the RDP connection. 181 * 182 * @param name 183 * The name of the SVC which should be handled by the new instance of the 184 * plugin. 185 * 186 * @param channel_options 187 * Bitwise OR of any of the several CHANNEL_OPTION_* flags. Regardless of 188 * whether specified here, the CHANNEL_OPTION_INTIALIZED and 189 * CHANNEL_OPTION_ENCRYPT_RDP flags will automatically be set. 190 * 191 * @param connect_handler 192 * The function to invoke when the SVC has been connected. 193 * 194 * @param receive_handler 195 * The function to invoke when the SVC has received a logical block of 196 * data, reassembled from perhaps several smaller chunks of data. 197 * 198 * @param terminate_handler 199 * The function to invoke when the SVC has been disconnected and is about 200 * to be freed. 201 * 202 * @return 203 * Zero if the plugin was loaded successfully, non-zero if the plugin could 204 * not be loaded. 205 */ 206int guac_rdp_common_svc_load_plugin(rdpContext* context, 207 char* name, ULONG channel_options, 208 guac_rdp_common_svc_connect_handler* connect_handler, 209 guac_rdp_common_svc_receive_handler* receive_handler, 210 guac_rdp_common_svc_terminate_handler* terminate_handler); 211 212/** 213 * Writes the given data to the virtual channel such that it can be received 214 * within the RDP session. The given data MUST be dynamically allocated, as the 215 * write operation may be queued and the actual write may not occur until 216 * later. The provided wStream and the buffer it points to will be 217 * automatically freed after the write occurs. 218 * 219 * @param svc 220 * The static virtual channel to write data to. 221 * 222 * @param output_stream 223 * The data to write, which MUST be dynamically allocated. 224 */ 225void guac_rdp_common_svc_write(guac_rdp_common_svc* svc, 226 wStream* output_stream); 227 228#endif 229