blob: 4a38cb389dbd0e080f990daf607a9c92f914a34a [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.
*/
#include "config.h"
#include "svc_service.h"
#include <stdlib.h>
#include <string.h>
#include <freerdp/constants.h>
#include <freerdp/utils/svc_plugin.h>
#include <guacamole/client.h>
#include <guacamole/protocol.h>
#include <guacamole/socket.h>
#ifdef ENABLE_WINPR
#include <winpr/stream.h>
#else
#include "compat/winpr-stream.h"
#endif
/**
* Entry point for arbitrary SVC.
*/
int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints) {
/* Gain access to plugin data */
CHANNEL_ENTRY_POINTS_FREERDP* entry_points_ex =
(CHANNEL_ENTRY_POINTS_FREERDP*) pEntryPoints;
/* Allocate plugin */
guac_svcPlugin* svc_plugin =
(guac_svcPlugin*) calloc(1, sizeof(guac_svcPlugin));
/* Get SVC descriptor from plugin parameters */
guac_rdp_svc* svc = (guac_rdp_svc*) entry_points_ex->pExtendedData;
/* Init channel def */
strncpy(svc_plugin->plugin.channel_def.name, svc->name,
GUAC_RDP_SVC_MAX_LENGTH);
svc_plugin->plugin.channel_def.options =
CHANNEL_OPTION_INITIALIZED
| CHANNEL_OPTION_ENCRYPT_RDP
| CHANNEL_OPTION_COMPRESS_RDP;
/* Init plugin */
svc_plugin->svc = svc;
/* Set callbacks */
svc_plugin->plugin.connect_callback = guac_svc_process_connect;
svc_plugin->plugin.receive_callback = guac_svc_process_receive;
svc_plugin->plugin.event_callback = guac_svc_process_event;
svc_plugin->plugin.terminate_callback = guac_svc_process_terminate;
/* Store plugin reference in SVC */
svc->plugin = (rdpSvcPlugin*) svc_plugin;
/* Finish init */
svc_plugin_init((rdpSvcPlugin*) svc_plugin, pEntryPoints);
return 1;
}
/*
* Service Handlers
*/
void guac_svc_process_connect(rdpSvcPlugin* plugin) {
/* Get corresponding guac_rdp_svc */
guac_svcPlugin* svc_plugin = (guac_svcPlugin*) plugin;
guac_rdp_svc* svc = svc_plugin->svc;
/* NULL out pExtendedData so we don't lose our guac_rdp_svc due to an
* automatic free() within libfreerdp */
plugin->channel_entry_points.pExtendedData = NULL;
/* Create pipe */
svc->output_pipe = guac_client_alloc_stream(svc->client);
/* Notify of pipe's existence */
guac_rdp_svc_send_pipe(svc->client->socket, svc);
/* Log connection to static channel */
guac_client_log(svc->client, GUAC_LOG_INFO,
"Static channel \"%s\" connected.", svc->name);
}
void guac_svc_process_terminate(rdpSvcPlugin* plugin) {
/* Get corresponding guac_rdp_svc */
guac_svcPlugin* svc_plugin = (guac_svcPlugin*) plugin;
guac_rdp_svc* svc = svc_plugin->svc;
/* Remove and free SVC */
guac_client_log(svc->client, GUAC_LOG_INFO, "Closing channel \"%s\"...", svc->name);
guac_rdp_remove_svc(svc->client, svc->name);
free(svc);
free(plugin);
}
void guac_svc_process_event(rdpSvcPlugin* plugin, wMessage* event) {
freerdp_event_free(event);
}
void guac_svc_process_receive(rdpSvcPlugin* plugin,
wStream* input_stream) {
/* Get corresponding guac_rdp_svc */
guac_svcPlugin* svc_plugin = (guac_svcPlugin*) plugin;
guac_rdp_svc* svc = svc_plugin->svc;
/* Fail if output not created */
if (svc->output_pipe == NULL) {
guac_client_log(svc->client, GUAC_LOG_ERROR,
"Output for channel \"%s\" dropped.",
svc->name);
return;
}
/* Send blob */
guac_protocol_send_blob(svc->client->socket, svc->output_pipe,
Stream_Buffer(input_stream),
Stream_Length(input_stream));
guac_socket_flush(svc->client->socket);
}