mirror of
https://github.com/FreeRDP/FreeRDP.git
synced 2024-11-23 18:03:30 +08:00
channel echo hardend
This commit is contained in:
parent
2b3b999929
commit
0cfbc6648b
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user