channel echo hardend

This commit is contained in:
Martin Haimberger 2015-06-08 05:35:27 -07:00
parent 2b3b999929
commit 0cfbc6648b
3 changed files with 110 additions and 46 deletions

View File

@ -3,6 +3,8 @@
* Echo Virtual Channel Extension
*
* Copyright 2013 Christian Hofstaedtler
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -23,15 +25,14 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/crt.h>
#include <winpr/stream.h>
#include <winpr/cmdline.h>
#include <freerdp/addin.h>
#include "echo_main.h"
#include <freerdp/channels/log.h>
#define TAG CHANNELS_TAG("echo.client")
typedef struct _ECHO_LISTENER_CALLBACK ECHO_LISTENER_CALLBACK;
struct _ECHO_LISTENER_CALLBACK
@ -60,29 +61,26 @@ struct _ECHO_PLUGIN
ECHO_LISTENER_CALLBACK* listener_callback;
};
static int echo_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data)
static WIN32ERROR echo_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data)
{
int status;
ECHO_CHANNEL_CALLBACK* callback = (ECHO_CHANNEL_CALLBACK*) pChannelCallback;
BYTE* pBuffer = Stream_Pointer(data);
UINT32 cbSize = Stream_GetRemainingLength(data);
/* echo back what we have received. ECHO does not have any message IDs. */
status = callback->channel->Write(callback->channel, cbSize, pBuffer, NULL);
return status;
return callback->channel->Write(callback->channel, cbSize, pBuffer, NULL);
}
static int echo_on_close(IWTSVirtualChannelCallback* pChannelCallback)
static WIN32ERROR echo_on_close(IWTSVirtualChannelCallback* pChannelCallback)
{
ECHO_CHANNEL_CALLBACK* callback = (ECHO_CHANNEL_CALLBACK*) pChannelCallback;
free(callback);
return 0;
return CHANNEL_RC_OK;
}
static int echo_on_new_channel_connection(IWTSListenerCallback* pListenerCallback,
static WIN32ERROR echo_on_new_channel_connection(IWTSListenerCallback* pListenerCallback,
IWTSVirtualChannel* pChannel, BYTE* Data, int* pbAccept,
IWTSVirtualChannelCallback** ppCallback)
{
@ -92,7 +90,10 @@ static int echo_on_new_channel_connection(IWTSListenerCallback* pListenerCallbac
callback = (ECHO_CHANNEL_CALLBACK*) calloc(1, sizeof(ECHO_CHANNEL_CALLBACK));
if (!callback)
return -1;
{
WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
callback->iface.OnDataReceived = echo_on_data_received;
callback->iface.OnClose = echo_on_close;
@ -102,17 +103,20 @@ static int echo_on_new_channel_connection(IWTSListenerCallback* pListenerCallbac
*ppCallback = (IWTSVirtualChannelCallback*) callback;
return 0;
return CHANNEL_RC_OK;
}
static int echo_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr)
static WIN32ERROR echo_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr)
{
ECHO_PLUGIN* echo = (ECHO_PLUGIN*) pPlugin;
echo->listener_callback = (ECHO_LISTENER_CALLBACK*) calloc(1, sizeof(ECHO_LISTENER_CALLBACK));
if (!echo->listener_callback)
return -1;
{
WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
echo->listener_callback->iface.OnNewChannelConnection = echo_on_new_channel_connection;
echo->listener_callback->plugin = pPlugin;
@ -122,22 +126,22 @@ static int echo_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager
(IWTSListenerCallback*) echo->listener_callback, NULL);
}
static int echo_plugin_terminated(IWTSPlugin* pPlugin)
static WIN32ERROR echo_plugin_terminated(IWTSPlugin* pPlugin)
{
ECHO_PLUGIN* echo = (ECHO_PLUGIN*) pPlugin;
free(echo);
return 0;
return CHANNEL_RC_OK;
}
#ifdef STATIC_CHANNELS
#define DVCPluginEntry echo_DVCPluginEntry
#endif
int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
WIN32ERROR DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
{
int status = 0;
WIN32ERROR status = CHANNEL_RC_OK;
ECHO_PLUGIN* echo;
echo = (ECHO_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "echo");
@ -147,7 +151,10 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
echo = (ECHO_PLUGIN*) calloc(1, sizeof(ECHO_PLUGIN));
if (!echo)
return -1;
{
WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
echo->iface.Initialize = echo_plugin_initialize;
echo->iface.Connected = NULL;

View File

@ -3,6 +3,8 @@
* Echo Virtual Channel Extension
*
* Copyright 2014 Vic Lee
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -32,6 +34,9 @@
#include <winpr/sysinfo.h>
#include <freerdp/server/echo.h>
#include <freerdp/channels/log.h>
#define TAG CHANNELS_TAG("echo.server")
typedef struct _echo_server
{
@ -48,7 +53,7 @@ typedef struct _echo_server
} echo_server;
static BOOL echo_server_open_channel(echo_server* echo)
static WIN32ERROR echo_server_open_channel(echo_server* echo)
{
DWORD Error;
HANDLE hEvent;
@ -59,8 +64,10 @@ static BOOL echo_server_open_channel(echo_server* echo)
if (WTSQuerySessionInformationA(echo->context.vcm, WTS_CURRENT_SESSION,
WTSSessionId, (LPSTR*) &pSessionId, &BytesReturned) == FALSE)
{
return FALSE;
WLog_ERR(TAG, "WTSQuerySessionInformationA failed!");
return ERROR_INTERNAL_ERROR;
}
echo->SessionId = (DWORD) *pSessionId;
WTSFreeMemory(pSessionId);
@ -85,7 +92,7 @@ static BOOL echo_server_open_channel(echo_server* echo)
break;
}
return echo->echo_channel ? TRUE : FALSE;
return echo->echo_channel ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
}
static void* echo_server_thread_func(void* arg)
@ -98,10 +105,13 @@ static void* echo_server_thread_func(void* arg)
HANDLE ChannelEvent;
DWORD BytesReturned = 0;
echo_server* echo = (echo_server*) arg;
WIN32ERROR error;
if (echo_server_open_channel(echo) == FALSE)
if ((error = echo_server_open_channel(echo)))
{
IFCALL(echo->context.OpenResult, &echo->context, ECHO_SERVER_OPEN_RESULT_NOTSUPPORTED);
IFCALLRET(echo->context.OpenResult, error, &echo->context, ECHO_SERVER_OPEN_RESULT_NOTSUPPORTED);
WLog_ERR(TAG, "echo_server_open_channel failed with error %lu!", error);
ExitThread((DWORD)error);
return NULL;
}
@ -127,13 +137,17 @@ static void* echo_server_thread_func(void* arg)
{
if (WaitForMultipleObjects(nCount, events, FALSE, 100) == WAIT_OBJECT_0)
{
IFCALL(echo->context.OpenResult, &echo->context, ECHO_SERVER_OPEN_RESULT_CLOSED);
IFCALLRET(echo->context.OpenResult, error, &echo->context, ECHO_SERVER_OPEN_RESULT_CLOSED);
if (error)
WLog_ERR(TAG, "OpenResult failed with error %lu!", error);
break;
}
if (WTSVirtualChannelQuery(echo->echo_channel, WTSVirtualChannelReady, &buffer, &BytesReturned) == FALSE)
{
IFCALL(echo->context.OpenResult, &echo->context, ECHO_SERVER_OPEN_RESULT_ERROR);
IFCALLRET(echo->context.OpenResult, error, &echo->context, ECHO_SERVER_OPEN_RESULT_ERROR);
if (error)
WLog_ERR(TAG, "OpenResult failed with error %lu!", error);
break;
}
@ -143,12 +157,21 @@ static void* echo_server_thread_func(void* arg)
if (ready)
{
IFCALL(echo->context.OpenResult, &echo->context, ECHO_SERVER_OPEN_RESULT_OK);
IFCALLRET(echo->context.OpenResult, error, &echo->context, ECHO_SERVER_OPEN_RESULT_OK);
if (error)
WLog_ERR(TAG, "OpenResult failed with error %lu!", error);
break;
}
}
s = Stream_New(NULL, 4096);
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");
WTSVirtualChannelClose(echo->echo_channel);
ExitThread((DWORD)ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
while (ready)
{
@ -160,35 +183,60 @@ static void* echo_server_thread_func(void* arg)
WTSVirtualChannelRead(echo->echo_channel, 0, NULL, 0, &BytesReturned);
if (BytesReturned < 1)
continue;
Stream_EnsureRemainingCapacity(s, BytesReturned);
if (WTSVirtualChannelRead(echo->echo_channel, 0, (PCHAR) Stream_Buffer(s),
(ULONG) Stream_Capacity(s), &BytesReturned) == FALSE)
if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
{
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
error = CHANNEL_RC_NO_MEMORY;
break;
}
IFCALL(echo->context.Response, &echo->context, (BYTE *) Stream_Buffer(s), BytesReturned);
if (WTSVirtualChannelRead(echo->echo_channel, 0, (PCHAR) Stream_Buffer(s),
(ULONG) Stream_Capacity(s), &BytesReturned) == FALSE)
{
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
error = ERROR_INTERNAL_ERROR;
break;
}
IFCALLRET(echo->context.Response, error, &echo->context, (BYTE *) Stream_Buffer(s), BytesReturned);
if (error)
{
WLog_ERR(TAG, "Response failed with error %lu!", error);
break;
}
}
Stream_Free(s, TRUE);
WTSVirtualChannelClose(echo->echo_channel);
echo->echo_channel = NULL;
ExitThread((DWORD)error);
return NULL;
}
static void echo_server_open(echo_server_context* context)
static WIN32ERROR echo_server_open(echo_server_context* context)
{
echo_server* echo = (echo_server*) context;
if (echo->thread == NULL)
{
echo->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
echo->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) echo_server_thread_func, (void*) echo, 0, NULL);
if (!(echo->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
{
WLog_ERR(TAG, "CreateEvent failed!");
return ERROR_INTERNAL_ERROR;
}
if (!(echo->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) echo_server_thread_func, (void*) echo, 0, NULL)))
{
WLog_ERR(TAG, "CreateEvent failed!");
CloseHandle(echo->stopEvent);
echo->stopEvent = NULL;
return ERROR_INTERNAL_ERROR;
}
}
return CHANNEL_RC_OK;
}
static void echo_server_close(echo_server_context* context)
static WIN32ERROR echo_server_close(echo_server_context* context)
{
echo_server* echo = (echo_server*) context;
@ -201,6 +249,7 @@ static void echo_server_close(echo_server_context* context)
echo->thread = NULL;
echo->stopEvent = NULL;
}
return CHANNEL_RC_OK;
}
static BOOL echo_server_request(echo_server_context* context, const BYTE* buffer, UINT32 length)
@ -216,10 +265,15 @@ echo_server_context* echo_server_context_new(HANDLE vcm)
echo = (echo_server*) calloc(1, sizeof(echo_server));
echo->context.vcm = vcm;
echo->context.Open = echo_server_open;
echo->context.Close = echo_server_close;
echo->context.Request = echo_server_request;
if (echo)
{
echo->context.vcm = vcm;
echo->context.Open = echo_server_open;
echo->context.Close = echo_server_close;
echo->context.Request = echo_server_request;
}
else
WLog_ERR(TAG, "calloc failed!");
return (echo_server_context*) echo;
}

View File

@ -3,6 +3,8 @@
* Echo Virtual Channel Extension
*
* Copyright 2014 Vic Lee
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -21,6 +23,7 @@
#define FREERDP_CHANNEL_ECHO_SERVER_H
#include <freerdp/channels/wtsvc.h>
#include <winpr/win32error.h>
typedef enum ECHO_SERVER_OPEN_RESULT
{
@ -32,12 +35,12 @@ typedef enum ECHO_SERVER_OPEN_RESULT
typedef struct _echo_server_context echo_server_context;
typedef void (*psEchoServerOpen)(echo_server_context* context);
typedef void (*psEchoServerClose)(echo_server_context* context);
typedef WIN32ERROR (*psEchoServerOpen)(echo_server_context* context);
typedef WIN32ERROR (*psEchoServerClose)(echo_server_context* context);
typedef BOOL (*psEchoServerRequest)(echo_server_context* context, const BYTE* buffer, UINT32 length);
typedef void (*psEchoServerOpenResult)(echo_server_context* context, ECHO_SERVER_OPEN_RESULT result);
typedef void (*psEchoServerResponse)(echo_server_context* context, const BYTE* buffer, UINT32 length);
typedef WIN32ERROR (*psEchoServerOpenResult)(echo_server_context* context, ECHO_SERVER_OPEN_RESULT result);
typedef WIN32ERROR (*psEchoServerResponse)(echo_server_context* context, const BYTE* buffer, UINT32 length);
struct _echo_server_context
{