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

View File

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

View File

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