blob: 82a9a63d1f5c869cd9c0b99a6740c80cf8056f8a [file] [log] [blame]
/*
* 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 "config.h"
#include <freerdp/svc.h>
#include <guacamole/client.h>
#include <guacamole/stream.h>
#include <winpr/stream.h>
#include <winpr/wtsapi.h>
#include <winpr/wtypes.h>
/**
* 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