mirror of
https://github.com/FreeRDP/FreeRDP.git
synced 2025-06-03 00:00:20 +00:00
server: Add channel handling for telemetry channel
This commit is contained in:
parent
3337810520
commit
dacc1e1c0f
@ -48,6 +48,7 @@
|
|||||||
#include <freerdp/server/remdesk.h>
|
#include <freerdp/server/remdesk.h>
|
||||||
#include <freerdp/server/encomsp.h>
|
#include <freerdp/server/encomsp.h>
|
||||||
#include <freerdp/server/rail.h>
|
#include <freerdp/server/rail.h>
|
||||||
|
#include <freerdp/server/telemetry.h>
|
||||||
#include <freerdp/server/rdpgfx.h>
|
#include <freerdp/server/rdpgfx.h>
|
||||||
#include <freerdp/server/disp.h>
|
#include <freerdp/server/disp.h>
|
||||||
#include <freerdp/server/gfxredir.h>
|
#include <freerdp/server/gfxredir.h>
|
||||||
@ -70,6 +71,7 @@ void freerdp_channels_dummy(void)
|
|||||||
RemdeskServerContext* remdesk;
|
RemdeskServerContext* remdesk;
|
||||||
EncomspServerContext* encomsp;
|
EncomspServerContext* encomsp;
|
||||||
RailServerContext* rail;
|
RailServerContext* rail;
|
||||||
|
TelemetryServerContext* telemetry;
|
||||||
RdpgfxServerContext* rdpgfx;
|
RdpgfxServerContext* rdpgfx;
|
||||||
DispServerContext* disp;
|
DispServerContext* disp;
|
||||||
#ifdef WITH_CHANNEL_GFXREDIR
|
#ifdef WITH_CHANNEL_GFXREDIR
|
||||||
@ -95,6 +97,8 @@ void freerdp_channels_dummy(void)
|
|||||||
encomsp_server_context_free(encomsp);
|
encomsp_server_context_free(encomsp);
|
||||||
rail = rail_server_context_new(NULL);
|
rail = rail_server_context_new(NULL);
|
||||||
rail_server_context_free(rail);
|
rail_server_context_free(rail);
|
||||||
|
telemetry = telemetry_server_context_new(NULL);
|
||||||
|
telemetry_server_context_free(telemetry);
|
||||||
rdpgfx = rdpgfx_server_context_new(NULL);
|
rdpgfx = rdpgfx_server_context_new(NULL);
|
||||||
rdpgfx_server_context_free(rdpgfx);
|
rdpgfx_server_context_free(rdpgfx);
|
||||||
disp = disp_server_context_new(NULL);
|
disp = disp_server_context_new(NULL);
|
||||||
|
23
channels/telemetry/CMakeLists.txt
Normal file
23
channels/telemetry/CMakeLists.txt
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# FreeRDP: A Remote Desktop Protocol Implementation
|
||||||
|
# FreeRDP cmake build script
|
||||||
|
#
|
||||||
|
# Copyright 2022 Armin Novak <anovak@thincast.com>
|
||||||
|
# Copyright 2022 Thincast Technologies GmbH
|
||||||
|
#
|
||||||
|
# Licensed 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.
|
||||||
|
|
||||||
|
define_channel("telemetry")
|
||||||
|
|
||||||
|
if(WITH_SERVER_CHANNELS)
|
||||||
|
add_channel_server(${MODULE_PREFIX} ${CHANNEL_NAME})
|
||||||
|
endif()
|
12
channels/telemetry/ChannelOptions.cmake
Normal file
12
channels/telemetry/ChannelOptions.cmake
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
set(OPTION_DEFAULT OFF)
|
||||||
|
set(OPTION_CLIENT_DEFAULT OFF)
|
||||||
|
set(OPTION_SERVER_DEFAULT ON)
|
||||||
|
|
||||||
|
define_channel_options(NAME "telemetry" TYPE "dynamic"
|
||||||
|
DESCRIPTION "Telemetry Virtual Channel Extension"
|
||||||
|
SPECIFICATIONS "[MS-RDPET]"
|
||||||
|
DEFAULT ${OPTION_DEFAULT})
|
||||||
|
|
||||||
|
define_channel_server_options(${OPTION_SERVER_DEFAULT})
|
||||||
|
|
26
channels/telemetry/server/CMakeLists.txt
Normal file
26
channels/telemetry/server/CMakeLists.txt
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# FreeRDP: A Remote Desktop Protocol Implementation
|
||||||
|
# FreeRDP cmake build script
|
||||||
|
#
|
||||||
|
# Copyright 2022 Pascal Nowack <Pascal.Nowack@gmx.de>
|
||||||
|
#
|
||||||
|
# Licensed 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.
|
||||||
|
|
||||||
|
define_channel_server("telemetry")
|
||||||
|
|
||||||
|
set(${MODULE_PREFIX}_SRCS
|
||||||
|
telemetry_main.c)
|
||||||
|
|
||||||
|
add_channel_server_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "DVCPluginEntry")
|
||||||
|
|
||||||
|
target_link_libraries(${MODULE_NAME} freerdp)
|
||||||
|
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Server")
|
441
channels/telemetry/server/telemetry_main.c
Normal file
441
channels/telemetry/server/telemetry_main.c
Normal file
@ -0,0 +1,441 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||||
|
* Advanced Input Virtual Channel Extension
|
||||||
|
*
|
||||||
|
* Copyright 2022 Pascal Nowack <Pascal.Nowack@gmx.de>
|
||||||
|
*
|
||||||
|
* Licensed 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 <freerdp/config.h>
|
||||||
|
|
||||||
|
#include <freerdp/channels/log.h>
|
||||||
|
#include <freerdp/server/telemetry.h>
|
||||||
|
|
||||||
|
#define TAG CHANNELS_TAG("telemetry.server")
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
TELEMETRY_INITIAL,
|
||||||
|
TELEMETRY_OPENED,
|
||||||
|
} eTelemetryChannelState;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
TelemetryServerContext context;
|
||||||
|
|
||||||
|
HANDLE stopEvent;
|
||||||
|
|
||||||
|
HANDLE thread;
|
||||||
|
void* telemetry_channel;
|
||||||
|
|
||||||
|
DWORD SessionId;
|
||||||
|
|
||||||
|
BOOL isOpened;
|
||||||
|
BOOL externalThread;
|
||||||
|
|
||||||
|
/* Channel state */
|
||||||
|
eTelemetryChannelState state;
|
||||||
|
|
||||||
|
wStream* buffer;
|
||||||
|
} telemetry_server;
|
||||||
|
|
||||||
|
static UINT telemetry_server_initialize(TelemetryServerContext* context, BOOL externalThread)
|
||||||
|
{
|
||||||
|
UINT error = CHANNEL_RC_OK;
|
||||||
|
telemetry_server* telemetry = (telemetry_server*)context;
|
||||||
|
|
||||||
|
WINPR_ASSERT(telemetry);
|
||||||
|
|
||||||
|
if (telemetry->isOpened)
|
||||||
|
{
|
||||||
|
WLog_WARN(TAG, "Application error: TELEMETRY channel already initialized, "
|
||||||
|
"calling in this state is not possible!");
|
||||||
|
return ERROR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
telemetry->externalThread = externalThread;
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT telemetry_server_open_channel(telemetry_server* telemetry)
|
||||||
|
{
|
||||||
|
TelemetryServerContext* context = &telemetry->context;
|
||||||
|
DWORD Error = ERROR_SUCCESS;
|
||||||
|
HANDLE hEvent;
|
||||||
|
DWORD BytesReturned = 0;
|
||||||
|
PULONG pSessionId = NULL;
|
||||||
|
UINT32 channelId;
|
||||||
|
BOOL status = TRUE;
|
||||||
|
|
||||||
|
WINPR_ASSERT(telemetry);
|
||||||
|
|
||||||
|
if (WTSQuerySessionInformationA(telemetry->context.vcm, WTS_CURRENT_SESSION, WTSSessionId,
|
||||||
|
(LPSTR*)&pSessionId, &BytesReturned) == FALSE)
|
||||||
|
{
|
||||||
|
WLog_ERR(TAG, "WTSQuerySessionInformationA failed!");
|
||||||
|
return ERROR_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
telemetry->SessionId = (DWORD)*pSessionId;
|
||||||
|
WTSFreeMemory(pSessionId);
|
||||||
|
hEvent = WTSVirtualChannelManagerGetEventHandle(telemetry->context.vcm);
|
||||||
|
|
||||||
|
if (WaitForSingleObject(hEvent, 1000) == WAIT_FAILED)
|
||||||
|
{
|
||||||
|
Error = GetLastError();
|
||||||
|
WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", Error);
|
||||||
|
return Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
telemetry->telemetry_channel = WTSVirtualChannelOpenEx(
|
||||||
|
telemetry->SessionId, TELEMETRY_DVC_CHANNEL_NAME, WTS_CHANNEL_OPTION_DYNAMIC);
|
||||||
|
if (!telemetry->telemetry_channel)
|
||||||
|
{
|
||||||
|
Error = GetLastError();
|
||||||
|
WLog_ERR(TAG, "WTSVirtualChannelOpenEx failed with error %" PRIu32 "!", Error);
|
||||||
|
return Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
channelId = WTSChannelGetIdByHandle(telemetry->telemetry_channel);
|
||||||
|
|
||||||
|
IFCALLRET(context->ChannelIdAssigned, status, context, channelId);
|
||||||
|
if (!status)
|
||||||
|
{
|
||||||
|
WLog_ERR(TAG, "context->ChannelIdAssigned failed!");
|
||||||
|
return ERROR_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT telemetry_server_recv_rdp_telemetry_pdu(TelemetryServerContext* context, wStream* s)
|
||||||
|
{
|
||||||
|
TELEMETRY_RDP_TELEMETRY_PDU pdu;
|
||||||
|
UINT error = CHANNEL_RC_OK;
|
||||||
|
|
||||||
|
if (Stream_GetRemainingLength(s) < 16)
|
||||||
|
{
|
||||||
|
WLog_ERR(TAG, "telemetry_server_recv_rdp_telemetry_pdu: Not enough data!");
|
||||||
|
return ERROR_NO_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream_Read_UINT32(s, pdu.PromptForCredentialsMillis);
|
||||||
|
Stream_Read_UINT32(s, pdu.PromptForCredentialsDoneMillis);
|
||||||
|
Stream_Read_UINT32(s, pdu.GraphicsChannelOpenedMillis);
|
||||||
|
Stream_Read_UINT32(s, pdu.FirstGraphicsReceivedMillis);
|
||||||
|
|
||||||
|
IFCALLRET(context->RdpTelemetry, error, context, &pdu);
|
||||||
|
if (error)
|
||||||
|
WLog_ERR(TAG, "context->RdpTelemetry failed with error %" PRIu32 "", error);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT telemetry_process_message(telemetry_server* telemetry)
|
||||||
|
{
|
||||||
|
BOOL rc;
|
||||||
|
UINT error = ERROR_INTERNAL_ERROR;
|
||||||
|
ULONG BytesReturned;
|
||||||
|
BYTE MessageId;
|
||||||
|
BYTE Length;
|
||||||
|
wStream* s;
|
||||||
|
|
||||||
|
WINPR_ASSERT(telemetry);
|
||||||
|
WINPR_ASSERT(telemetry->telemetry_channel);
|
||||||
|
|
||||||
|
s = telemetry->buffer;
|
||||||
|
WINPR_ASSERT(s);
|
||||||
|
|
||||||
|
Stream_SetPosition(s, 0);
|
||||||
|
rc = WTSVirtualChannelRead(telemetry->telemetry_channel, 0, NULL, 0, &BytesReturned);
|
||||||
|
if (!rc)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (BytesReturned < 1)
|
||||||
|
{
|
||||||
|
error = CHANNEL_RC_OK;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
|
||||||
|
{
|
||||||
|
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
|
||||||
|
error = CHANNEL_RC_NO_MEMORY;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WTSVirtualChannelRead(telemetry->telemetry_channel, 0, (PCHAR)Stream_Buffer(s),
|
||||||
|
(ULONG)Stream_Capacity(s), &BytesReturned) == FALSE)
|
||||||
|
{
|
||||||
|
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
|
||||||
|
return ERROR_NO_DATA;
|
||||||
|
|
||||||
|
Stream_SetLength(s, BytesReturned);
|
||||||
|
Stream_Read_UINT8(s, MessageId);
|
||||||
|
Stream_Read_UINT8(s, Length);
|
||||||
|
|
||||||
|
switch (MessageId)
|
||||||
|
{
|
||||||
|
case 0x01:
|
||||||
|
error = telemetry_server_recv_rdp_telemetry_pdu(&telemetry->context, s);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
WLog_ERR(TAG, "telemetry_process_message: unknown MessageId %" PRIu8 "", MessageId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (error)
|
||||||
|
WLog_ERR(TAG, "Response failed with error %" PRIu32 "!", error);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT telemetry_server_context_poll_int(TelemetryServerContext* context)
|
||||||
|
{
|
||||||
|
telemetry_server* telemetry = (telemetry_server*)context;
|
||||||
|
UINT error = ERROR_INTERNAL_ERROR;
|
||||||
|
|
||||||
|
WINPR_ASSERT(telemetry);
|
||||||
|
|
||||||
|
switch (telemetry->state)
|
||||||
|
{
|
||||||
|
case TELEMETRY_INITIAL:
|
||||||
|
error = telemetry_server_open_channel(telemetry);
|
||||||
|
if (error)
|
||||||
|
WLog_ERR(TAG, "telemetry_server_open_channel failed with error %" PRIu32 "!",
|
||||||
|
error);
|
||||||
|
else
|
||||||
|
telemetry->state = TELEMETRY_OPENED;
|
||||||
|
break;
|
||||||
|
case TELEMETRY_OPENED:
|
||||||
|
error = telemetry_process_message(telemetry);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HANDLE telemetry_server_get_channel_handle(telemetry_server* telemetry)
|
||||||
|
{
|
||||||
|
void* buffer = NULL;
|
||||||
|
DWORD BytesReturned = 0;
|
||||||
|
HANDLE ChannelEvent = NULL;
|
||||||
|
|
||||||
|
WINPR_ASSERT(telemetry);
|
||||||
|
|
||||||
|
if (WTSVirtualChannelQuery(telemetry->telemetry_channel, WTSVirtualEventHandle, &buffer,
|
||||||
|
&BytesReturned) == TRUE)
|
||||||
|
{
|
||||||
|
if (BytesReturned == sizeof(HANDLE))
|
||||||
|
CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
|
||||||
|
|
||||||
|
WTSFreeMemory(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ChannelEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD WINAPI telemetry_server_thread_func(LPVOID arg)
|
||||||
|
{
|
||||||
|
DWORD nCount;
|
||||||
|
HANDLE events[2] = { 0 };
|
||||||
|
telemetry_server* telemetry = (telemetry_server*)arg;
|
||||||
|
UINT error = CHANNEL_RC_OK;
|
||||||
|
DWORD status;
|
||||||
|
|
||||||
|
WINPR_ASSERT(telemetry);
|
||||||
|
|
||||||
|
nCount = 0;
|
||||||
|
events[nCount++] = telemetry->stopEvent;
|
||||||
|
|
||||||
|
while ((error == CHANNEL_RC_OK) && (WaitForSingleObject(events[0], 0) != WAIT_OBJECT_0))
|
||||||
|
{
|
||||||
|
switch (telemetry->state)
|
||||||
|
{
|
||||||
|
case TELEMETRY_INITIAL:
|
||||||
|
error = telemetry_server_context_poll_int(&telemetry->context);
|
||||||
|
if (error == CHANNEL_RC_OK)
|
||||||
|
{
|
||||||
|
events[1] = telemetry_server_get_channel_handle(telemetry);
|
||||||
|
nCount = 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TELEMETRY_OPENED:
|
||||||
|
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case WAIT_OBJECT_0:
|
||||||
|
break;
|
||||||
|
case WAIT_OBJECT_0 + 1:
|
||||||
|
case WAIT_TIMEOUT:
|
||||||
|
error = telemetry_server_context_poll_int(&telemetry->context);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WAIT_FAILED:
|
||||||
|
default:
|
||||||
|
error = ERROR_INTERNAL_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WTSVirtualChannelClose(telemetry->telemetry_channel);
|
||||||
|
telemetry->telemetry_channel = NULL;
|
||||||
|
|
||||||
|
if (error && telemetry->context.rdpcontext)
|
||||||
|
setChannelError(telemetry->context.rdpcontext, error,
|
||||||
|
"telemetry_server_thread_func reported an error");
|
||||||
|
|
||||||
|
ExitThread(error);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT telemetry_server_open(TelemetryServerContext* context)
|
||||||
|
{
|
||||||
|
telemetry_server* telemetry = (telemetry_server*)context;
|
||||||
|
|
||||||
|
WINPR_ASSERT(telemetry);
|
||||||
|
|
||||||
|
if (!telemetry->externalThread && (telemetry->thread == NULL))
|
||||||
|
{
|
||||||
|
telemetry->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||||
|
if (!telemetry->stopEvent)
|
||||||
|
{
|
||||||
|
WLog_ERR(TAG, "CreateEvent failed!");
|
||||||
|
return ERROR_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
telemetry->thread = CreateThread(NULL, 0, telemetry_server_thread_func, telemetry, 0, NULL);
|
||||||
|
if (!telemetry->thread)
|
||||||
|
{
|
||||||
|
WLog_ERR(TAG, "CreateThread failed!");
|
||||||
|
CloseHandle(telemetry->stopEvent);
|
||||||
|
telemetry->stopEvent = NULL;
|
||||||
|
return ERROR_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
telemetry->isOpened = TRUE;
|
||||||
|
|
||||||
|
return CHANNEL_RC_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT telemetry_server_close(TelemetryServerContext* context)
|
||||||
|
{
|
||||||
|
UINT error = CHANNEL_RC_OK;
|
||||||
|
telemetry_server* telemetry = (telemetry_server*)context;
|
||||||
|
|
||||||
|
WINPR_ASSERT(telemetry);
|
||||||
|
|
||||||
|
if (!telemetry->externalThread && telemetry->thread)
|
||||||
|
{
|
||||||
|
SetEvent(telemetry->stopEvent);
|
||||||
|
|
||||||
|
if (WaitForSingleObject(telemetry->thread, INFINITE) == WAIT_FAILED)
|
||||||
|
{
|
||||||
|
error = GetLastError();
|
||||||
|
WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", error);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(telemetry->thread);
|
||||||
|
CloseHandle(telemetry->stopEvent);
|
||||||
|
telemetry->thread = NULL;
|
||||||
|
telemetry->stopEvent = NULL;
|
||||||
|
}
|
||||||
|
if (telemetry->externalThread)
|
||||||
|
{
|
||||||
|
if (telemetry->state != TELEMETRY_INITIAL)
|
||||||
|
{
|
||||||
|
WTSVirtualChannelClose(telemetry->telemetry_channel);
|
||||||
|
telemetry->telemetry_channel = NULL;
|
||||||
|
telemetry->state = TELEMETRY_INITIAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
telemetry->isOpened = FALSE;
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT telemetry_server_context_poll(TelemetryServerContext* context)
|
||||||
|
{
|
||||||
|
telemetry_server* telemetry = (telemetry_server*)context;
|
||||||
|
|
||||||
|
WINPR_ASSERT(telemetry);
|
||||||
|
|
||||||
|
if (!telemetry->externalThread)
|
||||||
|
return ERROR_INTERNAL_ERROR;
|
||||||
|
|
||||||
|
return telemetry_server_context_poll_int(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL telemetry_server_context_handle(TelemetryServerContext* context, HANDLE* handle)
|
||||||
|
{
|
||||||
|
telemetry_server* telemetry = (telemetry_server*)context;
|
||||||
|
|
||||||
|
WINPR_ASSERT(telemetry);
|
||||||
|
WINPR_ASSERT(handle);
|
||||||
|
|
||||||
|
if (!telemetry->externalThread)
|
||||||
|
return FALSE;
|
||||||
|
if (telemetry->state == TELEMETRY_INITIAL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
*handle = telemetry_server_get_channel_handle(telemetry);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
TelemetryServerContext* telemetry_server_context_new(HANDLE vcm)
|
||||||
|
{
|
||||||
|
telemetry_server* telemetry = (telemetry_server*)calloc(1, sizeof(telemetry_server));
|
||||||
|
|
||||||
|
if (!telemetry)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
telemetry->context.vcm = vcm;
|
||||||
|
telemetry->context.Initialize = telemetry_server_initialize;
|
||||||
|
telemetry->context.Open = telemetry_server_open;
|
||||||
|
telemetry->context.Close = telemetry_server_close;
|
||||||
|
telemetry->context.Poll = telemetry_server_context_poll;
|
||||||
|
telemetry->context.ChannelHandle = telemetry_server_context_handle;
|
||||||
|
|
||||||
|
telemetry->buffer = Stream_New(NULL, 4096);
|
||||||
|
if (!telemetry->buffer)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
return &telemetry->context;
|
||||||
|
fail:
|
||||||
|
telemetry_server_context_free(&telemetry->context);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void telemetry_server_context_free(TelemetryServerContext* context)
|
||||||
|
{
|
||||||
|
telemetry_server* telemetry = (telemetry_server*)context;
|
||||||
|
|
||||||
|
if (telemetry)
|
||||||
|
{
|
||||||
|
telemetry_server_close(context);
|
||||||
|
Stream_Free(telemetry->buffer, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(telemetry);
|
||||||
|
}
|
@ -125,6 +125,9 @@
|
|||||||
#cmakedefine CHANNEL_SSHAGENT
|
#cmakedefine CHANNEL_SSHAGENT
|
||||||
#cmakedefine CHANNEL_SSHAGENT_CLIENT
|
#cmakedefine CHANNEL_SSHAGENT_CLIENT
|
||||||
#cmakedefine CHANNEL_SSHAGENT_SERVER
|
#cmakedefine CHANNEL_SSHAGENT_SERVER
|
||||||
|
#cmakedefine CHANNEL_TELEMETRY
|
||||||
|
#cmakedefine CHANNEL_TELEMETRY_CLIENT
|
||||||
|
#cmakedefine CHANNEL_TELEMETRY_SERVER
|
||||||
#cmakedefine CHANNEL_TSMF
|
#cmakedefine CHANNEL_TSMF
|
||||||
#cmakedefine CHANNEL_TSMF_CLIENT
|
#cmakedefine CHANNEL_TSMF_CLIENT
|
||||||
#cmakedefine CHANNEL_TSMF_SERVER
|
#cmakedefine CHANNEL_TSMF_SERVER
|
||||||
|
38
include/freerdp/channels/telemetry.h
Normal file
38
include/freerdp/channels/telemetry.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||||
|
* Audio Input Redirection Virtual Channel
|
||||||
|
*
|
||||||
|
* Copyright 2022 Pascal Nowack <Pascal.Nowack@gmx.de>
|
||||||
|
*
|
||||||
|
* Licensed 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 FREERDP_CHANNEL_TELEMETRY_H
|
||||||
|
#define FREERDP_CHANNEL_TELEMETRY_H
|
||||||
|
|
||||||
|
#include <freerdp/api.h>
|
||||||
|
#include <freerdp/dvc.h>
|
||||||
|
#include <freerdp/types.h>
|
||||||
|
|
||||||
|
#define TELEMETRY_DVC_CHANNEL_NAME "Microsoft::Windows::RDS::Telemetry"
|
||||||
|
|
||||||
|
struct _TELEMETRY_RDP_TELEMETRY_PDU
|
||||||
|
{
|
||||||
|
UINT32 PromptForCredentialsMillis;
|
||||||
|
UINT32 PromptForCredentialsDoneMillis;
|
||||||
|
UINT32 GraphicsChannelOpenedMillis;
|
||||||
|
UINT32 FirstGraphicsReceivedMillis;
|
||||||
|
};
|
||||||
|
typedef struct _TELEMETRY_RDP_TELEMETRY_PDU TELEMETRY_RDP_TELEMETRY_PDU;
|
||||||
|
|
||||||
|
#endif /* FREERDP_CHANNEL_TELEMETRY_H */
|
108
include/freerdp/server/telemetry.h
Normal file
108
include/freerdp/server/telemetry.h
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||||
|
* Telemetry Virtual Channel Extension
|
||||||
|
*
|
||||||
|
* Copyright 2022 Pascal Nowack <Pascal.Nowack@gmx.de>
|
||||||
|
*
|
||||||
|
* Licensed 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 FREERDP_CHANNEL_TELEMETRY_SERVER_TELEMETRY_H
|
||||||
|
#define FREERDP_CHANNEL_TELEMETRY_SERVER_TELEMETRY_H
|
||||||
|
|
||||||
|
#include <freerdp/channels/telemetry.h>
|
||||||
|
#include <freerdp/channels/wtsvc.h>
|
||||||
|
|
||||||
|
typedef struct _telemetry_server_context TelemetryServerContext;
|
||||||
|
|
||||||
|
typedef UINT (*psTelemetryServerOpen)(TelemetryServerContext* context);
|
||||||
|
typedef UINT (*psTelemetryServerClose)(TelemetryServerContext* context);
|
||||||
|
|
||||||
|
typedef BOOL (*psTelemetryServerChannelIdAssigned)(TelemetryServerContext* context,
|
||||||
|
UINT32 channelId);
|
||||||
|
|
||||||
|
typedef UINT (*psTelemetryServerInitialize)(TelemetryServerContext* context, BOOL externalThread);
|
||||||
|
typedef UINT (*psTelemetryServerPoll)(TelemetryServerContext* context);
|
||||||
|
typedef BOOL (*psTelemetryServerChannelHandle)(TelemetryServerContext* context, HANDLE* handle);
|
||||||
|
|
||||||
|
typedef UINT (*psTelemetryServerRdpTelemetry)(TelemetryServerContext* context,
|
||||||
|
const TELEMETRY_RDP_TELEMETRY_PDU* rdpTelemetry);
|
||||||
|
|
||||||
|
struct _telemetry_server_context
|
||||||
|
{
|
||||||
|
HANDLE vcm;
|
||||||
|
|
||||||
|
/* Server self-defined pointer. */
|
||||||
|
void* userdata;
|
||||||
|
|
||||||
|
/*** APIs called by the server. ***/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional: Set thread handling.
|
||||||
|
* When externalThread=TRUE, the application is responsible to call
|
||||||
|
* Poll() periodically to process channel events.
|
||||||
|
*
|
||||||
|
* Defaults to externalThread=FALSE
|
||||||
|
*/
|
||||||
|
psTelemetryServerInitialize Initialize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open the telemetry channel.
|
||||||
|
*/
|
||||||
|
psTelemetryServerOpen Open;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the telemetry channel.
|
||||||
|
*/
|
||||||
|
psTelemetryServerClose Close;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Poll
|
||||||
|
* When externalThread=TRUE, call Poll() periodically from your main loop.
|
||||||
|
* If externalThread=FALSE do not call.
|
||||||
|
*/
|
||||||
|
psTelemetryServerPoll Poll;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the channel handle for use in conjunction with Poll().
|
||||||
|
* If externalThread=FALSE do not call.
|
||||||
|
*/
|
||||||
|
psTelemetryServerChannelHandle ChannelHandle;
|
||||||
|
|
||||||
|
/*** Callbacks registered by the server. ***/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback, when the channel got its id assigned
|
||||||
|
*/
|
||||||
|
psTelemetryServerChannelIdAssigned ChannelIdAssigned;
|
||||||
|
/**
|
||||||
|
* Callback for the RDP Telemetry PDU.
|
||||||
|
*/
|
||||||
|
psTelemetryServerRdpTelemetry RdpTelemetry;
|
||||||
|
|
||||||
|
rdpContext* rdpcontext;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FREERDP_API TelemetryServerContext* telemetry_server_context_new(HANDLE vcm);
|
||||||
|
FREERDP_API void telemetry_server_context_free(TelemetryServerContext* context);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* FREERDP_CHANNEL_TELEMETRY_SERVER_TELEMETRY_H */
|
Loading…
Reference in New Issue
Block a user