channels/rdpsnd: decouple rdpsnd from svc_plugin
This commit is contained in:
parent
dbbb364caf
commit
bd64e616de
@ -35,6 +35,8 @@
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/thread.h>
|
||||
#include <winpr/stream.h>
|
||||
#include <winpr/cmdline.h>
|
||||
#include <winpr/sysinfo.h>
|
||||
#include <winpr/collections.h>
|
||||
@ -42,9 +44,8 @@
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/addin.h>
|
||||
#include <freerdp/constants.h>
|
||||
#include <winpr/stream.h>
|
||||
#include <freerdp/utils/debug.h>
|
||||
#include <freerdp/utils/signal.h>
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
|
||||
#include "rdpsnd_main.h"
|
||||
|
||||
@ -52,9 +53,16 @@
|
||||
|
||||
struct rdpsnd_plugin
|
||||
{
|
||||
rdpSvcPlugin plugin;
|
||||
CHANNEL_DEF channelDef;
|
||||
CHANNEL_ENTRY_POINTS_EX channelEntryPoints;
|
||||
|
||||
HANDLE thread;
|
||||
wStream* data_in;
|
||||
void* InitHandle;
|
||||
UINT32 OpenHandle;
|
||||
wMessagePipe* MsgPipe;
|
||||
|
||||
HANDLE ScheduleThread;
|
||||
wMessageQueue* queue;
|
||||
|
||||
BYTE cBlockNo;
|
||||
@ -135,7 +143,7 @@ void rdpsnd_send_quality_mode_pdu(rdpsndPlugin* rdpsnd)
|
||||
Stream_Write_UINT16(pdu, HIGH_QUALITY); /* wQualityMode */
|
||||
Stream_Write_UINT16(pdu, 0); /* Reserved */
|
||||
|
||||
svc_plugin_send((rdpSvcPlugin*) rdpsnd, pdu);
|
||||
rdpsnd_virtual_channel_write(rdpsnd, pdu);
|
||||
}
|
||||
|
||||
void rdpsnd_select_supported_audio_formats(rdpsndPlugin* rdpsnd)
|
||||
@ -251,7 +259,7 @@ void rdpsnd_send_client_audio_formats(rdpsndPlugin* rdpsnd)
|
||||
Stream_Write(pdu, clientFormat->data, clientFormat->cbSize);
|
||||
}
|
||||
|
||||
svc_plugin_send((rdpSvcPlugin*) rdpsnd, pdu);
|
||||
rdpsnd_virtual_channel_write(rdpsnd, pdu);
|
||||
}
|
||||
|
||||
void rdpsnd_recv_server_audio_formats_pdu(rdpsndPlugin* rdpsnd, wStream* s)
|
||||
@ -316,7 +324,7 @@ void rdpsnd_send_training_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, U
|
||||
Stream_Write_UINT16(pdu, wTimeStamp);
|
||||
Stream_Write_UINT16(pdu, wPackSize);
|
||||
|
||||
svc_plugin_send((rdpSvcPlugin*) rdpsnd, pdu);
|
||||
rdpsnd_virtual_channel_write(rdpsnd, pdu);
|
||||
}
|
||||
|
||||
static void rdpsnd_recv_training_pdu(rdpsndPlugin* rdpsnd, wStream* s)
|
||||
@ -382,7 +390,7 @@ void rdpsnd_send_wave_confirm_pdu(rdpsndPlugin* rdpsnd, UINT16 wTimeStamp, BYTE
|
||||
Stream_Write_UINT8(pdu, cConfirmedBlockNo); /* cConfirmedBlockNo */
|
||||
Stream_Write_UINT8(pdu, 0); /* bPad */
|
||||
|
||||
svc_plugin_send((rdpSvcPlugin*) rdpsnd, pdu);
|
||||
rdpsnd_virtual_channel_write(rdpsnd, pdu);
|
||||
}
|
||||
|
||||
static void rdpsnd_device_send_wave_confirm_pdu(rdpsndDevicePlugin* device, RDPSND_WAVE* wave)
|
||||
@ -454,8 +462,6 @@ static void rdpsnd_recv_wave_pdu(rdpsndPlugin* rdpsnd, wStream* s)
|
||||
|
||||
static void rdpsnd_recv_close_pdu(rdpsndPlugin* rdpsnd)
|
||||
{
|
||||
DEBUG_SVC("server closes.");
|
||||
|
||||
if (rdpsnd->device)
|
||||
{
|
||||
IFCALL(rdpsnd->device->Close, rdpsnd->device);
|
||||
@ -469,7 +475,6 @@ static void rdpsnd_recv_volume_pdu(rdpsndPlugin* rdpsnd, wStream* s)
|
||||
UINT32 dwVolume;
|
||||
|
||||
Stream_Read_UINT32(s, dwVolume);
|
||||
DEBUG_SVC("dwVolume 0x%X", dwVolume);
|
||||
|
||||
if (rdpsnd->device)
|
||||
{
|
||||
@ -477,11 +482,10 @@ static void rdpsnd_recv_volume_pdu(rdpsndPlugin* rdpsnd, wStream* s)
|
||||
}
|
||||
}
|
||||
|
||||
static void rdpsnd_recv_pdu(rdpSvcPlugin* plugin, wStream* s)
|
||||
static void rdpsnd_recv_pdu(rdpsndPlugin* rdpsnd, wStream* s)
|
||||
{
|
||||
BYTE msgType;
|
||||
UINT16 BodySize;
|
||||
rdpsndPlugin* rdpsnd = (rdpsndPlugin*) plugin;
|
||||
|
||||
if (rdpsnd->expectingWave)
|
||||
{
|
||||
@ -646,20 +650,18 @@ static void rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args)
|
||||
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||
}
|
||||
|
||||
static void rdpsnd_process_connect(rdpSvcPlugin* plugin)
|
||||
static void rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
|
||||
{
|
||||
ADDIN_ARGV* args;
|
||||
rdpsndPlugin* rdpsnd = (rdpsndPlugin*) plugin;
|
||||
|
||||
DEBUG_SVC("connecting");
|
||||
|
||||
rdpsnd->latency = -1;
|
||||
rdpsnd->queue = MessageQueue_New();
|
||||
rdpsnd->thread = CreateThread(NULL, 0,
|
||||
(LPTHREAD_START_ROUTINE) rdpsnd_schedule_thread,
|
||||
(void*) plugin, 0, NULL);
|
||||
|
||||
args = (ADDIN_ARGV*) plugin->channel_entry_points.pExtendedData;
|
||||
rdpsnd->ScheduleThread = CreateThread(NULL, 0,
|
||||
(LPTHREAD_START_ROUTINE) rdpsnd_schedule_thread,
|
||||
(void*) rdpsnd, 0, NULL);
|
||||
|
||||
args = (ADDIN_ARGV*) rdpsnd->channelEntryPoints.pExtendedData;
|
||||
|
||||
if (args)
|
||||
rdpsnd_process_addin_args(rdpsnd, args);
|
||||
@ -733,23 +735,16 @@ static void rdpsnd_process_connect(rdpSvcPlugin* plugin)
|
||||
}
|
||||
}
|
||||
|
||||
static void rdpsnd_process_event(rdpSvcPlugin* plugin, wMessage* event)
|
||||
static void rdpsnd_process_terminate(rdpsndPlugin* rdpsnd)
|
||||
{
|
||||
freerdp_event_free(event);
|
||||
}
|
||||
|
||||
static void rdpsnd_process_terminate(rdpSvcPlugin* plugin)
|
||||
{
|
||||
rdpsndPlugin* rdpsnd = (rdpsndPlugin*) plugin;
|
||||
|
||||
if (rdpsnd->device)
|
||||
IFCALL(rdpsnd->device->Free, rdpsnd->device);
|
||||
|
||||
MessageQueue_PostQuit(rdpsnd->queue, 0);
|
||||
WaitForSingleObject(rdpsnd->thread, INFINITE);
|
||||
WaitForSingleObject(rdpsnd->ScheduleThread, INFINITE);
|
||||
|
||||
MessageQueue_Free(rdpsnd->queue);
|
||||
CloseHandle(rdpsnd->thread);
|
||||
CloseHandle(rdpsnd->ScheduleThread);
|
||||
|
||||
if (rdpsnd->subsystem)
|
||||
free(rdpsnd->subsystem);
|
||||
@ -766,26 +761,253 @@ static void rdpsnd_process_terminate(rdpSvcPlugin* plugin)
|
||||
rdpsnd->ClientFormats = NULL;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
|
||||
static wListDictionary* g_InitHandles;
|
||||
static wListDictionary* g_OpenHandles;
|
||||
|
||||
void rdpsnd_add_init_handle_data(void* pInitHandle, void* pUserData)
|
||||
{
|
||||
if (!g_InitHandles)
|
||||
g_InitHandles = ListDictionary_New(TRUE);
|
||||
|
||||
ListDictionary_Add(g_InitHandles, pInitHandle, pUserData);
|
||||
}
|
||||
|
||||
void* rdpsnd_get_init_handle_data(void* pInitHandle)
|
||||
{
|
||||
void* pUserData = NULL;
|
||||
pUserData = ListDictionary_GetItemValue(g_InitHandles, pInitHandle);
|
||||
return pUserData;
|
||||
}
|
||||
|
||||
void rdpsnd_remove_init_handle_data(void* pInitHandle)
|
||||
{
|
||||
ListDictionary_Remove(g_InitHandles, pInitHandle);
|
||||
}
|
||||
|
||||
void rdpsnd_add_open_handle_data(DWORD openHandle, void* pUserData)
|
||||
{
|
||||
void* pOpenHandle = (void*) (size_t) openHandle;
|
||||
|
||||
if (!g_OpenHandles)
|
||||
g_OpenHandles = ListDictionary_New(TRUE);
|
||||
|
||||
ListDictionary_Add(g_OpenHandles, pOpenHandle, pUserData);
|
||||
}
|
||||
|
||||
void* rdpsnd_get_open_handle_data(DWORD openHandle)
|
||||
{
|
||||
void* pUserData = NULL;
|
||||
void* pOpenHandle = (void*) (size_t) openHandle;
|
||||
pUserData = ListDictionary_GetItemValue(g_OpenHandles, pOpenHandle);
|
||||
return pUserData;
|
||||
}
|
||||
|
||||
void rdpsnd_remove_open_handle_data(DWORD openHandle)
|
||||
{
|
||||
void* pOpenHandle = (void*) (size_t) openHandle;
|
||||
ListDictionary_Remove(g_OpenHandles, pOpenHandle);
|
||||
}
|
||||
|
||||
int rdpsnd_virtual_channel_write(rdpsndPlugin* rdpsnd, wStream* s)
|
||||
{
|
||||
UINT32 status = 0;
|
||||
|
||||
if (!rdpsnd)
|
||||
status = CHANNEL_RC_BAD_INIT_HANDLE;
|
||||
else
|
||||
status = rdpsnd->channelEntryPoints.pVirtualChannelWrite(rdpsnd->OpenHandle,
|
||||
Stream_Buffer(s), Stream_GetPosition(s), s);
|
||||
|
||||
if (status != CHANNEL_RC_OK)
|
||||
{
|
||||
Stream_Free(s, TRUE);
|
||||
fprintf(stderr, "rdpdr_virtual_channel_write: VirtualChannelWrite failed %d\n", status);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void rdpsnd_virtual_channel_event_data_received(rdpsndPlugin* plugin,
|
||||
void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
||||
{
|
||||
wStream* s;
|
||||
|
||||
if ((dataFlags & CHANNEL_FLAG_SUSPEND) || (dataFlags & CHANNEL_FLAG_RESUME))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (dataFlags & CHANNEL_FLAG_FIRST)
|
||||
{
|
||||
if (plugin->data_in != NULL)
|
||||
Stream_Free(plugin->data_in, TRUE);
|
||||
|
||||
plugin->data_in = Stream_New(NULL, totalLength);
|
||||
}
|
||||
|
||||
s = plugin->data_in;
|
||||
Stream_EnsureRemainingCapacity(s, (int) dataLength);
|
||||
Stream_Write(s, pData, dataLength);
|
||||
|
||||
if (dataFlags & CHANNEL_FLAG_LAST)
|
||||
{
|
||||
if (Stream_Capacity(s) != Stream_GetPosition(s))
|
||||
{
|
||||
fprintf(stderr, "rdpsnd_virtual_channel_event_data_received: read error\n");
|
||||
}
|
||||
|
||||
plugin->data_in = NULL;
|
||||
Stream_SealLength(s);
|
||||
Stream_SetPosition(s, 0);
|
||||
|
||||
MessageQueue_Post(plugin->MsgPipe->In, NULL, 0, (void*) s, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void rdpsnd_virtual_channel_open_event(UINT32 openHandle, UINT32 event,
|
||||
void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
|
||||
{
|
||||
rdpsndPlugin* plugin;
|
||||
|
||||
plugin = (rdpsndPlugin*) rdpsnd_get_open_handle_data(openHandle);
|
||||
|
||||
if (!plugin)
|
||||
{
|
||||
fprintf(stderr, "rdpsnd_virtual_channel_open_event: error no match\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case CHANNEL_EVENT_DATA_RECEIVED:
|
||||
rdpsnd_virtual_channel_event_data_received(plugin, pData, dataLength, totalLength, dataFlags);
|
||||
break;
|
||||
|
||||
case CHANNEL_EVENT_WRITE_COMPLETE:
|
||||
Stream_Free((wStream*) pData, TRUE);
|
||||
break;
|
||||
|
||||
case CHANNEL_EVENT_USER:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void* rdpsnd_virtual_channel_client_thread(void* arg)
|
||||
{
|
||||
wStream* data;
|
||||
wMessage message;
|
||||
rdpsndPlugin* plugin = (rdpsndPlugin*) arg;
|
||||
|
||||
rdpsnd_process_connect(plugin);
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (!MessageQueue_Wait(plugin->MsgPipe->In))
|
||||
break;
|
||||
|
||||
if (MessageQueue_Peek(plugin->MsgPipe->In, &message, TRUE))
|
||||
{
|
||||
if (message.id == WMQ_QUIT)
|
||||
break;
|
||||
|
||||
if (message.id == 0)
|
||||
{
|
||||
data = (wStream*) message.wParam;
|
||||
rdpsnd_recv_pdu(plugin, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ExitThread(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void rdpsnd_virtual_channel_event_connected(rdpsndPlugin* plugin, void* pData, UINT32 dataLength)
|
||||
{
|
||||
UINT32 status;
|
||||
|
||||
status = plugin->channelEntryPoints.pVirtualChannelOpen(plugin->InitHandle,
|
||||
&plugin->OpenHandle, plugin->channelDef.name, rdpsnd_virtual_channel_open_event);
|
||||
|
||||
rdpsnd_add_open_handle_data(plugin->OpenHandle, plugin);
|
||||
|
||||
if (status != CHANNEL_RC_OK)
|
||||
{
|
||||
fprintf(stderr, "rdpsnd_virtual_channel_event_connected: open failed: status: %d\n", status);
|
||||
return;
|
||||
}
|
||||
|
||||
plugin->MsgPipe = MessagePipe_New();
|
||||
|
||||
plugin->thread = CreateThread(NULL, 0,
|
||||
(LPTHREAD_START_ROUTINE) rdpsnd_virtual_channel_client_thread, (void*) plugin, 0, NULL);
|
||||
}
|
||||
|
||||
static void rdpsnd_virtual_channel_event_terminated(rdpsndPlugin* plugin)
|
||||
{
|
||||
MessagePipe_PostQuit(plugin->MsgPipe, 0);
|
||||
WaitForSingleObject(plugin->thread, INFINITE);
|
||||
|
||||
MessagePipe_Free(plugin->MsgPipe);
|
||||
CloseHandle(plugin->thread);
|
||||
|
||||
plugin->channelEntryPoints.pVirtualChannelClose(plugin->OpenHandle);
|
||||
|
||||
if (plugin->data_in)
|
||||
{
|
||||
Stream_Free(plugin->data_in, TRUE);
|
||||
plugin->data_in = NULL;
|
||||
}
|
||||
|
||||
rdpsnd_process_terminate(plugin);
|
||||
|
||||
rdpsnd_remove_open_handle_data(plugin->OpenHandle);
|
||||
rdpsnd_remove_init_handle_data(plugin->InitHandle);
|
||||
}
|
||||
|
||||
static void rdpsnd_virtual_channel_init_event(void* pInitHandle, UINT32 event, void* pData, UINT32 dataLength)
|
||||
{
|
||||
rdpsndPlugin* plugin;
|
||||
|
||||
plugin = (rdpsndPlugin*) rdpsnd_get_init_handle_data(pInitHandle);
|
||||
|
||||
if (!plugin)
|
||||
{
|
||||
fprintf(stderr, "rdpsnd_virtual_channel_init_event: error no match\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case CHANNEL_EVENT_CONNECTED:
|
||||
rdpsnd_virtual_channel_event_connected(plugin, pData, dataLength);
|
||||
break;
|
||||
|
||||
case CHANNEL_EVENT_DISCONNECTED:
|
||||
break;
|
||||
|
||||
case CHANNEL_EVENT_TERMINATED:
|
||||
rdpsnd_virtual_channel_event_terminated(plugin);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* rdpsnd is always built-in */
|
||||
#define VirtualChannelEntry rdpsnd_VirtualChannelEntry
|
||||
|
||||
int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
rdpsndPlugin* _p;
|
||||
rdpsndPlugin* rdpsnd;
|
||||
|
||||
_p = (rdpsndPlugin*) malloc(sizeof(rdpsndPlugin));
|
||||
ZeroMemory(_p, sizeof(rdpsndPlugin));
|
||||
rdpsnd = (rdpsndPlugin*) malloc(sizeof(rdpsndPlugin));
|
||||
|
||||
_p->plugin.channel_def.options =
|
||||
CHANNEL_OPTION_INITIALIZED |
|
||||
CHANNEL_OPTION_ENCRYPT_RDP;
|
||||
|
||||
strcpy(_p->plugin.channel_def.name, "rdpsnd");
|
||||
|
||||
_p->plugin.connect_callback = rdpsnd_process_connect;
|
||||
_p->plugin.receive_callback = rdpsnd_recv_pdu;
|
||||
_p->plugin.event_callback = rdpsnd_process_event;
|
||||
_p->plugin.terminate_callback = rdpsnd_process_terminate;
|
||||
if (rdpsnd)
|
||||
{
|
||||
ZeroMemory(rdpsnd, sizeof(rdpsndPlugin));
|
||||
|
||||
#if !defined(_WIN32) && !defined(ANDROID)
|
||||
{
|
||||
@ -796,7 +1018,19 @@ int VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
|
||||
}
|
||||
#endif
|
||||
|
||||
svc_plugin_init((rdpSvcPlugin*) _p, pEntryPoints);
|
||||
rdpsnd->channelDef.options =
|
||||
CHANNEL_OPTION_INITIALIZED |
|
||||
CHANNEL_OPTION_ENCRYPT_RDP;
|
||||
|
||||
strcpy(rdpsnd->channelDef.name, "rdpsnd");
|
||||
|
||||
CopyMemory(&(rdpsnd->channelEntryPoints), pEntryPoints, pEntryPoints->cbSize);
|
||||
|
||||
rdpsnd->channelEntryPoints.pVirtualChannelInit(&rdpsnd->InitHandle,
|
||||
&rdpsnd->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, rdpsnd_virtual_channel_init_event);
|
||||
|
||||
rdpsnd_add_init_handle_data(rdpsnd->InitHandle, (void*) rdpsnd);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -21,6 +21,9 @@
|
||||
#ifndef __RDPSND_MAIN_H
|
||||
#define __RDPSND_MAIN_H
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/svc.h>
|
||||
#include <freerdp/addin.h>
|
||||
#include <freerdp/client/rdpsnd.h>
|
||||
|
||||
#if defined(WITH_DEBUG_SND)
|
||||
@ -29,4 +32,6 @@
|
||||
#define DEBUG_SND(fmt, ...) do { } while (0)
|
||||
#endif
|
||||
|
||||
int rdpsnd_virtual_channel_write(rdpsndPlugin* rdpsnd, wStream* s);
|
||||
|
||||
#endif /* __RDPSND_MAIN_H */
|
||||
|
Loading…
Reference in New Issue
Block a user