22#include <freerdp/config.h> 
   27#include <winpr/winpr.h> 
   29#include <winpr/cast.h> 
   30#include <winpr/assert.h> 
   32#include <winpr/synch.h> 
   33#include <winpr/file.h> 
   34#include <winpr/string.h> 
   35#include <winpr/path.h> 
   36#include <winpr/image.h> 
   37#include <winpr/winsock.h> 
   39#include <freerdp/streamdump.h> 
   40#include <freerdp/transport_io.h> 
   42#include <freerdp/channels/wtsvc.h> 
   43#include <freerdp/channels/channels.h> 
   44#include <freerdp/channels/drdynvc.h> 
   46#include <freerdp/freerdp.h> 
   47#include <freerdp/constants.h> 
   48#include <freerdp/server/rdpsnd.h> 
   49#include <freerdp/settings.h> 
   54#include "sf_encomsp.h" 
   58#include <freerdp/log.h> 
   59#define TAG SERVER_TAG("sample") 
   61#define SAMPLE_SERVER_USE_CLIENT_RESOLUTION 1 
   62#define SAMPLE_SERVER_DEFAULT_WIDTH 1024 
   63#define SAMPLE_SERVER_DEFAULT_HEIGHT 768 
   67  BOOL test_dump_rfx_realtime;
 
   68  const char* test_pcap_file;
 
   69  const char* replay_dump;
 
   74static void test_peer_context_free(freerdp_peer* client, rdpContext* ctx)
 
   76  testPeerContext* context = (testPeerContext*)ctx;
 
   82    winpr_image_free(context->image, TRUE);
 
   83    if (context->debug_channel_thread)
 
   85      WINPR_ASSERT(context->stopEvent);
 
   86      (void)SetEvent(context->stopEvent);
 
   87      (void)WaitForSingleObject(context->debug_channel_thread, INFINITE);
 
   88      (void)CloseHandle(context->debug_channel_thread);
 
   91    Stream_Free(context->s, TRUE);
 
   92    free(context->bg_data);
 
   93    rfx_context_free(context->rfx_context);
 
   94    nsc_context_free(context->nsc_context);
 
   96    if (context->debug_channel)
 
   97      (void)WTSVirtualChannelClose(context->debug_channel);
 
   99    sf_peer_audin_uninit(context);
 
  101#if defined(CHANNEL_AINPUT_SERVER) 
  102    sf_peer_ainput_uninit(context);
 
  105    rdpsnd_server_context_free(context->rdpsnd);
 
  106    encomsp_server_context_free(context->encomsp);
 
  108    WTSCloseServer(context->vcm);
 
  112static BOOL test_peer_context_new(freerdp_peer* client, rdpContext* ctx)
 
  114  testPeerContext* context = (testPeerContext*)ctx;
 
  116  WINPR_ASSERT(client);
 
  117  WINPR_ASSERT(context);
 
  118  WINPR_ASSERT(ctx->settings);
 
  120  context->image = winpr_image_new();
 
  123  if (!(context->rfx_context = rfx_context_new_ex(
 
  127  if (!rfx_context_reset(context->rfx_context, SAMPLE_SERVER_DEFAULT_WIDTH,
 
  128                         SAMPLE_SERVER_DEFAULT_HEIGHT))
 
  132  rfx_context_set_mode(context->rfx_context, rlgr);
 
  134  if (!(context->nsc_context = nsc_context_new()))
 
  137  if (!(context->s = Stream_New(NULL, 65536)))
 
  140  context->icon_x = UINT32_MAX;
 
  141  context->icon_y = UINT32_MAX;
 
  142  context->vcm = WTSOpenServerA((LPSTR)client->context);
 
  144  if (!context->vcm || context->vcm == INVALID_HANDLE_VALUE)
 
  149  test_peer_context_free(client, ctx);
 
  153static BOOL test_peer_init(freerdp_peer* client)
 
  155  WINPR_ASSERT(client);
 
  157  client->ContextSize = 
sizeof(testPeerContext);
 
  158  client->ContextNew = test_peer_context_new;
 
  159  client->ContextFree = test_peer_context_free;
 
  160  return freerdp_peer_context_new(client);
 
  163static wStream* test_peer_stream_init(testPeerContext* context)
 
  165  WINPR_ASSERT(context);
 
  166  WINPR_ASSERT(context->s);
 
  168  Stream_Clear(context->s);
 
  169  Stream_SetPosition(context->s, 0);
 
  173static void test_peer_begin_frame(freerdp_peer* client)
 
  175  rdpUpdate* update = NULL;
 
  177  testPeerContext* context = NULL;
 
  179  WINPR_ASSERT(client);
 
  180  WINPR_ASSERT(client->context);
 
  182  update = client->context->update;
 
  183  WINPR_ASSERT(update);
 
  185  context = (testPeerContext*)client->context;
 
  186  WINPR_ASSERT(context);
 
  188  fm.frameAction = SURFACECMD_FRAMEACTION_BEGIN;
 
  189  fm.frameId = context->frame_id;
 
  190  WINPR_ASSERT(update->SurfaceFrameMarker);
 
  191  update->SurfaceFrameMarker(update->context, &fm);
 
  194static void test_peer_end_frame(freerdp_peer* client)
 
  196  rdpUpdate* update = NULL;
 
  198  testPeerContext* context = NULL;
 
  200  WINPR_ASSERT(client);
 
  202  context = (testPeerContext*)client->context;
 
  203  WINPR_ASSERT(context);
 
  205  update = client->context->update;
 
  206  WINPR_ASSERT(update);
 
  208  fm.frameAction = SURFACECMD_FRAMEACTION_END;
 
  209  fm.frameId = context->frame_id;
 
  210  WINPR_ASSERT(update->SurfaceFrameMarker);
 
  211  update->SurfaceFrameMarker(update->context, &fm);
 
  215static BOOL stream_surface_bits_supported(
const rdpSettings* settings)
 
  217  const UINT32 supported =
 
  219  return ((supported & SURFCMDS_STREAM_SURFACE_BITS) != 0);
 
  222static BOOL test_peer_draw_background(freerdp_peer* client, 
const RFX_RECT* rect)
 
  226  const UINT32 colorFormat = PIXEL_FORMAT_RGB24;
 
  227  const size_t bpp = FreeRDPGetBytesPerPixel(colorFormat);
 
  229  WINPR_ASSERT(client);
 
  231  testPeerContext* context = (testPeerContext*)client->context;
 
  232  WINPR_ASSERT(context);
 
  234  rdpSettings* settings = client->context->settings;
 
  235  WINPR_ASSERT(settings);
 
  237  rdpUpdate* update = client->context->update;
 
  238  WINPR_ASSERT(update);
 
  247  wStream* s = test_peer_stream_init(context);
 
  248  const size_t size = bpp * rect->width * rect->height;
 
  252  BYTE* rgb_data = malloc(size);
 
  255    WLog_ERR(TAG, 
"Problem allocating memory");
 
  259  memset(rgb_data, 0xA0, size);
 
  261  if (RemoteFxCodec && stream_surface_bits_supported(settings))
 
  263    WLog_DBG(TAG, 
"Using RemoteFX codec");
 
  264    rfx_context_set_pixel_format(context->rfx_context, colorFormat);
 
  266    WINPR_ASSERT(bpp <= UINT16_MAX);
 
  267    RFX_RECT rrect = { .x = 0, .y = 0, .width = rect->width, .height = rect->height };
 
  269    if (!rfx_compose_message(context->rfx_context, s, &rrect, 1, rgb_data, rect->width,
 
  270                             rect->height, (UINT32)(bpp * rect->width)))
 
  275    const UINT32 RemoteFxCodecId =
 
  277    WINPR_ASSERT(RemoteFxCodecId <= UINT16_MAX);
 
  278    cmd.bmp.codecID = (UINT16)RemoteFxCodecId;
 
  279    cmd.cmdType = CMDTYPE_STREAM_SURFACE_BITS;
 
  283    WLog_DBG(TAG, 
"Using NSCodec");
 
  284    nsc_context_set_parameters(context->nsc_context, NSC_COLOR_FORMAT, colorFormat);
 
  286    WINPR_ASSERT(bpp <= UINT16_MAX);
 
  287    nsc_compose_message(context->nsc_context, s, rgb_data, rect->width, rect->height,
 
  288                        (UINT32)(bpp * rect->width));
 
  290    WINPR_ASSERT(NSCodecId <= UINT16_MAX);
 
  291    cmd.bmp.codecID = (UINT16)NSCodecId;
 
  292    cmd.cmdType = CMDTYPE_SET_SURFACE_BITS;
 
  295  cmd.destLeft = rect->x;
 
  296  cmd.destTop = rect->y;
 
  297  cmd.destRight = rect->x + rect->width;
 
  298  cmd.destBottom = rect->y + rect->height;
 
  301  cmd.bmp.width = rect->width;
 
  302  cmd.bmp.height = rect->height;
 
  303  WINPR_ASSERT(Stream_GetPosition(s) <= UINT32_MAX);
 
  304  cmd.bmp.bitmapDataLength = (UINT32)Stream_GetPosition(s);
 
  305  cmd.bmp.bitmapData = Stream_Buffer(s);
 
  307  update->SurfaceBits(update->context, &cmd);
 
  314static int open_icon(
wImage* img)
 
  316  char* paths[] = { SAMPLE_RESOURCE_ROOT, 
"." };
 
  317  const char* names[] = { 
"test_icon.webp", 
"test_icon.png", 
"test_icon.jpg", 
"test_icon.bmp" };
 
  319  for (
size_t x = 0; x < ARRAYSIZE(paths); x++)
 
  321    const char* path = paths[x];
 
  322    if (!winpr_PathFileExists(path))
 
  325    for (
size_t y = 0; y < ARRAYSIZE(names); y++)
 
  327      const char* name = names[y];
 
  328      char* file = GetCombinedPath(path, name);
 
  329      int rc = winpr_image_read(img, file);
 
  335  WLog_ERR(TAG, 
"Unable to open test icon");
 
  339static BOOL test_peer_load_icon(freerdp_peer* client)
 
  341  testPeerContext* context = NULL;
 
  342  rdpSettings* settings = NULL;
 
  344  WINPR_ASSERT(client);
 
  346  context = (testPeerContext*)client->context;
 
  347  WINPR_ASSERT(context);
 
  349  settings = client->context->settings;
 
  350  WINPR_ASSERT(settings);
 
  355    WLog_ERR(TAG, 
"Client doesn't support RemoteFX or NSCodec");
 
  359  int rc = open_icon(context->image);
 
  364  if (!(context->bg_data = calloc(context->image->height, 3ULL * context->image->width)))
 
  367  memset(context->bg_data, 0xA0, 3ULL * context->image->height * context->image->width);
 
  370  context->bg_data = NULL;
 
  374static void test_send_cursor_update(freerdp_peer* client, UINT32 x, UINT32 y)
 
  376  WINPR_ASSERT(client);
 
  378  testPeerContext* context = (testPeerContext*)client->context;
 
  379  WINPR_ASSERT(context);
 
  381  rdpSettings* settings = client->context->settings;
 
  385  if (context->image->width < 1 || !context->activated)
 
  390                  .width = WINPR_ASSERTING_INT_CAST(UINT16, context->image->width),
 
  391                  .height = WINPR_ASSERTING_INT_CAST(UINT16, context->image->height) };
 
  395  if (context->icon_x + context->image->width > w)
 
  397  if (context->icon_y + context->image->height > h)
 
  399  if (x + context->image->width > w)
 
  401  if (y + context->image->height > h)
 
  405  if (RemoteFxCodec && stream_surface_bits_supported(settings))
 
  407    const UINT32 RemoteFxCodecId =
 
  409    WINPR_ASSERT(RemoteFxCodecId <= UINT16_MAX);
 
  410    cmd.bmp.codecID = (UINT16)RemoteFxCodecId;
 
  411    cmd.cmdType = CMDTYPE_STREAM_SURFACE_BITS;
 
  416    WINPR_ASSERT(NSCodecId <= UINT16_MAX);
 
  417    cmd.bmp.codecID = (UINT16)NSCodecId;
 
  418    cmd.cmdType = CMDTYPE_SET_SURFACE_BITS;
 
  421  wStream* s = test_peer_stream_init(context);
 
  424    const UINT32 colorFormat =
 
  425        context->image->bitsPerPixel > 24 ? PIXEL_FORMAT_BGRA32 : PIXEL_FORMAT_BGR24;
 
  429      rfx_context_set_pixel_format(context->rfx_context, colorFormat);
 
  430      rfx_compose_message(context->rfx_context, s, &rect, 1, context->image->data, rect.width,
 
  431                          rect.height, context->image->scanline);
 
  435      nsc_context_set_parameters(context->nsc_context, NSC_COLOR_FORMAT, colorFormat);
 
  436      nsc_compose_message(context->nsc_context, s, context->image->data, rect.width,
 
  437                          rect.height, context->image->scanline);
 
  443  cmd.destRight = x + rect.width;
 
  444  cmd.destBottom = y + rect.height;
 
  446  cmd.bmp.width = rect.width;
 
  447  cmd.bmp.height = rect.height;
 
  448  cmd.bmp.bitmapDataLength = (UINT32)Stream_GetPosition(s);
 
  449  cmd.bmp.bitmapData = Stream_Buffer(s);
 
  451  rdpUpdate* update = client->context->update;
 
  452  WINPR_ASSERT(update);
 
  453  WINPR_ASSERT(update->SurfaceBits);
 
  454  update->SurfaceBits(update->context, &cmd);
 
  459static void test_peer_draw_icon(freerdp_peer* client, UINT32 x, UINT32 y)
 
  461  WINPR_ASSERT(client);
 
  463  rdpSettings* settings = client->context->settings;
 
  464  WINPR_ASSERT(settings);
 
  469  test_peer_begin_frame(client);
 
  471  testPeerContext* context = (testPeerContext*)client->context;
 
  472  if ((context->icon_x != UINT32_MAX) && (context->icon_y != UINT32_MAX))
 
  474    RFX_RECT rect = { .x = WINPR_ASSERTING_INT_CAST(uint16_t, context->icon_x),
 
  475                    .y = WINPR_ASSERTING_INT_CAST(uint16_t, context->icon_y),
 
  476                    .width = WINPR_ASSERTING_INT_CAST(uint16_t, context->image->width),
 
  477                    .height = WINPR_ASSERTING_INT_CAST(uint16_t, context->image->height) };
 
  479    test_peer_draw_background(client, &rect);
 
  481  test_send_cursor_update(client, x, y);
 
  482  test_peer_end_frame(client);
 
  485static BOOL test_sleep_tsdiff(UINT32* old_sec, UINT32* old_usec, UINT32 new_sec, UINT32 new_usec)
 
  490  WINPR_ASSERT(old_sec);
 
  491  WINPR_ASSERT(old_usec);
 
  493  if ((*old_sec == 0) && (*old_usec == 0))
 
  496    *old_usec = new_usec;
 
  500  sec = new_sec - *old_sec;
 
  501  usec = new_usec - *old_usec;
 
  503  if ((sec < 0) || ((sec == 0) && (usec < 0)))
 
  505    WLog_ERR(TAG, 
"Invalid time stamp detected.");
 
  510  *old_usec = new_usec;
 
  519    Sleep((DWORD)sec * 1000);
 
  527static BOOL tf_peer_dump_rfx(freerdp_peer* client)
 
  531  UINT32 prev_seconds = 0;
 
  532  UINT32 prev_useconds = 0;
 
  533  rdpUpdate* update = NULL;
 
  534  rdpPcap* pcap_rfx = NULL;
 
  535  pcap_record record = { 0 };
 
  537  WINPR_ASSERT(client);
 
  538  WINPR_ASSERT(client->context);
 
  540  struct server_info* info = client->ContextExtra;
 
  543  s = Stream_New(NULL, 512);
 
  548  update = client->context->update;
 
  549  WINPR_ASSERT(update);
 
  551  pcap_rfx = pcap_open(info->test_pcap_file, FALSE);
 
  555  prev_seconds = prev_useconds = 0;
 
  557  while (pcap_has_next_record(pcap_rfx))
 
  559    if (!pcap_get_next_record_header(pcap_rfx, &record))
 
  562    if (!Stream_EnsureCapacity(s, record.length))
 
  565    record.data = Stream_Buffer(s);
 
  566    pcap_get_next_record_content(pcap_rfx, &record);
 
  567    Stream_SetPosition(s, Stream_Capacity(s));
 
  569    if (info->test_dump_rfx_realtime &&
 
  570        test_sleep_tsdiff(&prev_seconds, &prev_useconds, record.header.ts_sec,
 
  571                          record.header.ts_usec) == FALSE)
 
  574    WINPR_ASSERT(update->SurfaceCommand);
 
  575    update->SurfaceCommand(update->context, s);
 
  577    WINPR_ASSERT(client->CheckFileDescriptor);
 
  578    if (client->CheckFileDescriptor(client) != TRUE)
 
  584  Stream_Free(s, TRUE);
 
  585  pcap_close(pcap_rfx);
 
  589static DWORD WINAPI tf_debug_channel_thread_func(LPVOID arg)
 
  593  DWORD BytesReturned = 0;
 
  595  testPeerContext* context = (testPeerContext*)arg;
 
  597  WINPR_ASSERT(context);
 
  598  if (WTSVirtualChannelQuery(context->debug_channel, WTSVirtualFileHandle, &buffer,
 
  599                             &BytesReturned) == TRUE)
 
  601    fd = *((
void**)buffer);
 
  602    WTSFreeMemory(buffer);
 
  604    if (!(context->event = CreateWaitObjectEvent(NULL, TRUE, FALSE, fd)))
 
  608  wStream* s = Stream_New(NULL, 4096);
 
  612  if (!WTSVirtualChannelWrite(context->debug_channel, (PCHAR) 
"test1", 5, &written))
 
  619    HANDLE handles[MAXIMUM_WAIT_OBJECTS] = { 0 };
 
  621    handles[nCount++] = context->event;
 
  622    handles[nCount++] = freerdp_abort_event(&context->_p);
 
  623    handles[nCount++] = context->stopEvent;
 
  624    status = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE);
 
  633    Stream_SetPosition(s, 0);
 
  635    if (WTSVirtualChannelRead(context->debug_channel, 0, Stream_BufferAs(s, 
char),
 
  636                              (ULONG)Stream_Capacity(s), &BytesReturned) == FALSE)
 
  638      if (BytesReturned == 0)
 
  641      if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
 
  644      if (WTSVirtualChannelRead(context->debug_channel, 0, Stream_BufferAs(s, 
char),
 
  645                                (ULONG)Stream_Capacity(s), &BytesReturned) == FALSE)
 
  652    Stream_SetPosition(s, BytesReturned);
 
  653    WLog_DBG(TAG, 
"got %" PRIu32 
" bytes", BytesReturned);
 
  656  Stream_Free(s, TRUE);
 
  660static BOOL tf_peer_post_connect(freerdp_peer* client)
 
  662  testPeerContext* context = NULL;
 
  663  rdpSettings* settings = NULL;
 
  665  WINPR_ASSERT(client);
 
  667  context = (testPeerContext*)client->context;
 
  668  WINPR_ASSERT(context);
 
  670  settings = client->context->settings;
 
  671  WINPR_ASSERT(settings);
 
  679  WLog_DBG(TAG, 
"Client %s is activated (osMajorType %" PRIu32 
" osMinorType %" PRIu32 
")",
 
  680           client->local ? 
"(local)" : client->hostname,
 
  688    WLog_DBG(TAG, 
" and wants to login automatically as %s\\%s", Domain ? Domain : 
"",
 
  694  WLog_DBG(TAG, 
"Client requested desktop: %" PRIu32 
"x%" PRIu32 
"x%" PRIu32 
"",
 
  698#if (SAMPLE_SERVER_USE_CLIENT_RESOLUTION == 1) 
  700  if (!rfx_context_reset(context->rfx_context,
 
  705  WLog_DBG(TAG, 
"Using resolution requested by client.");
 
  707  client->freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth) =
 
  708      context->rfx_context->width;
 
  709  client->freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight) =
 
  710      context->rfx_context->height;
 
  711  WLog_DBG(TAG, 
"Resizing client to %" PRIu32 
"x%" PRIu32 
"",
 
  712           client->freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth),
 
  713           client->freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight));
 
  714  client->update->DesktopResize(client->update->context);
 
  719  if (!test_peer_load_icon(client))
 
  721    WLog_DBG(TAG, 
"Unable to load icon");
 
  725  if (WTSVirtualChannelManagerIsChannelJoined(context->vcm, 
"rdpdbg"))
 
  727    context->debug_channel = WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, 
"rdpdbg");
 
  729    if (context->debug_channel != NULL)
 
  731      WLog_DBG(TAG, 
"Open channel rdpdbg.");
 
  733      if (!(context->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
 
  735        WLog_ERR(TAG, 
"Failed to create stop event");
 
  739      if (!(context->debug_channel_thread =
 
  740                CreateThread(NULL, 0, tf_debug_channel_thread_func, (
void*)context, 0, NULL)))
 
  742        WLog_ERR(TAG, 
"Failed to create debug channel thread");
 
  743        (void)CloseHandle(context->stopEvent);
 
  744        context->stopEvent = NULL;
 
  750  if (WTSVirtualChannelManagerIsChannelJoined(context->vcm, RDPSND_CHANNEL_NAME))
 
  752    sf_peer_rdpsnd_init(context); 
 
  755  if (WTSVirtualChannelManagerIsChannelJoined(context->vcm, ENCOMSP_SVC_CHANNEL_NAME))
 
  757    sf_peer_encomsp_init(context); 
 
  761  sf_peer_audin_init(context); 
 
  763#if defined(CHANNEL_AINPUT_SERVER) 
  764  sf_peer_ainput_init(context);
 
  771static BOOL tf_peer_activate(freerdp_peer* client)
 
  773  testPeerContext* context = NULL;
 
  774  rdpSettings* settings = NULL;
 
  776  WINPR_ASSERT(client);
 
  778  context = (testPeerContext*)client->context;
 
  779  WINPR_ASSERT(context);
 
  781  settings = client->context->settings;
 
  782  WINPR_ASSERT(settings);
 
  784  struct server_info* info = client->ContextExtra;
 
  787  context->activated = TRUE;
 
  794  if (info->test_pcap_file != NULL)
 
  799    if (!tf_peer_dump_rfx(client))
 
  810    test_peer_begin_frame(client);
 
  811    test_peer_draw_background(client, &rect);
 
  812    test_peer_end_frame(client);
 
  818static BOOL tf_peer_synchronize_event(rdpInput* input, UINT32 flags)
 
  822  WLog_DBG(TAG, 
"Client sent a synchronize event (flags:0x%" PRIX32 
")", flags);
 
  826static BOOL tf_peer_keyboard_event(rdpInput* input, UINT16 flags, UINT8 code)
 
  828  freerdp_peer* client = NULL;
 
  829  rdpUpdate* update = NULL;
 
  830  rdpContext* context = NULL;
 
  831  testPeerContext* tcontext = NULL;
 
  832  rdpSettings* settings = NULL;
 
  836  context = input->context;
 
  837  WINPR_ASSERT(context);
 
  839  client = context->peer;
 
  840  WINPR_ASSERT(client);
 
  842  settings = context->settings;
 
  843  WINPR_ASSERT(settings);
 
  845  update = context->update;
 
  846  WINPR_ASSERT(update);
 
  848  tcontext = (testPeerContext*)context;
 
  849  WINPR_ASSERT(tcontext);
 
  851  WLog_DBG(TAG, 
"Client sent a keyboard event (flags:0x%04" PRIX16 
" code:0x%04" PRIX8 
")", flags,
 
  854  if (((flags & KBD_FLAGS_RELEASE) == 0) && (code == RDP_SCANCODE_KEY_G)) 
 
  866                                       SAMPLE_SERVER_DEFAULT_WIDTH))
 
  869                                       SAMPLE_SERVER_DEFAULT_HEIGHT))
 
  873    if (!rfx_context_reset(tcontext->rfx_context,
 
  878    WINPR_ASSERT(update->DesktopResize);
 
  879    update->DesktopResize(update->context);
 
  880    tcontext->activated = FALSE;
 
  882  else if (((flags & KBD_FLAGS_RELEASE) == 0) && code == RDP_SCANCODE_KEY_C) 
 
  884    if (tcontext->debug_channel)
 
  887      if (!WTSVirtualChannelWrite(tcontext->debug_channel, (PCHAR) 
"test2", 5, &written))
 
  891  else if (((flags & KBD_FLAGS_RELEASE) == 0) && code == RDP_SCANCODE_KEY_X) 
 
  893    WINPR_ASSERT(client->Close);
 
  894    client->Close(client);
 
  896  else if (((flags & KBD_FLAGS_RELEASE) == 0) && code == RDP_SCANCODE_KEY_R) 
 
  898    tcontext->audin_open = !tcontext->audin_open;
 
  900#if defined(CHANNEL_AINPUT_SERVER) 
  901  else if (((flags & KBD_FLAGS_RELEASE) == 0) && code == RDP_SCANCODE_KEY_I) 
 
  903    tcontext->ainput_open = !tcontext->ainput_open;
 
  906  else if (((flags & KBD_FLAGS_RELEASE) == 0) && code == RDP_SCANCODE_KEY_S) 
 
  913static BOOL tf_peer_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
 
  919           "Client sent a unicode keyboard event (flags:0x%04" PRIX16 
" code:0x%04" PRIX16 
")",
 
  924static BOOL tf_peer_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
 
  928  WINPR_ASSERT(input->context);
 
  930  WLog_DBG(TAG, 
"Client sent a mouse event (flags:0x%04" PRIX16 
" pos:%" PRIu16 
",%" PRIu16 
")",
 
  932  test_peer_draw_icon(input->context->peer, x + 10, y);
 
  936static UINT32 add(UINT32 old, UINT32 max, INT16 diff)
 
  944  return WINPR_ASSERTING_INT_CAST(uint32_t, val);
 
  947static BOOL tf_peer_rel_mouse_event(rdpInput* input, UINT16 flags, INT16 xDelta, INT16 yDelta)
 
  951  WINPR_ASSERT(input->context);
 
  956  static UINT32 xpos = 0;
 
  957  static UINT32 ypos = 0;
 
  959  xpos = add(xpos, w, xDelta);
 
  960  ypos = add(ypos, h, yDelta);
 
  963           "Client sent a relative mouse event (flags:0x%04" PRIX16 
" pos:%" PRId16 
",%" PRId16
 
  965           flags, xDelta, yDelta);
 
  966  test_peer_draw_icon(input->context->peer, xpos + 10, ypos);
 
  970static BOOL tf_peer_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
 
  974  WINPR_ASSERT(input->context);
 
  977           "Client sent an extended mouse event (flags:0x%04" PRIX16 
" pos:%" PRIu16 
",%" PRIu16
 
  980  test_peer_draw_icon(input->context->peer, x + 10, y);
 
  984static BOOL tf_peer_refresh_rect(rdpContext* context, BYTE count, 
const RECTANGLE_16* areas)
 
  986  WINPR_UNUSED(context);
 
  987  WINPR_ASSERT(context);
 
  988  WINPR_ASSERT(areas || (count == 0));
 
  990  WLog_DBG(TAG, 
"Client requested to refresh:");
 
  992  for (BYTE i = 0; i < count; i++)
 
  994    WLog_DBG(TAG, 
"  (%" PRIu16 
", %" PRIu16 
") (%" PRIu16 
", %" PRIu16 
")", areas[i].left,
 
  995             areas[i].top, areas[i].right, areas[i].bottom);
 
 1001static BOOL tf_peer_suppress_output(rdpContext* context, BYTE allow, 
const RECTANGLE_16* area)
 
 1003  WINPR_UNUSED(context);
 
 1009             "Client restore output (%" PRIu16 
", %" PRIu16 
") (%" PRIu16 
", %" PRIu16 
").",
 
 1010             area->left, area->top, area->right, area->bottom);
 
 1014    WLog_DBG(TAG, 
"Client minimized and suppress output.");
 
 1020static int hook_peer_write_pdu(rdpTransport* transport, 
wStream* s)
 
 1027  rdpContext* context = transport_get_context(transport);
 
 1029  WINPR_ASSERT(context);
 
 1032  freerdp_peer* client = context->peer;
 
 1033  WINPR_ASSERT(client);
 
 1035  testPeerContext* peerCtx = (testPeerContext*)client->context;
 
 1036  WINPR_ASSERT(peerCtx);
 
 1037  WINPR_ASSERT(peerCtx->io.WritePdu);
 
 1046  CONNECTION_STATE state = freerdp_get_state(context);
 
 1047  if (state < CONNECTION_STATE_NEGO)
 
 1048    return peerCtx->io.WritePdu(transport, s);
 
 1050  ls = Stream_New(NULL, 4096);
 
 1054  while (stream_dump_get(context, &flags, ls, &offset, &ts) > 0)
 
 1058    if (flags & STREAM_MSG_SRV_TX)
 
 1060      if ((last_ts > 0) && (ts > last_ts))
 
 1062        UINT64 diff = ts - last_ts;
 
 1065          UINT32 d = diff > UINT32_MAX ? UINT32_MAX : (UINT32)diff;
 
 1071      rc = peerCtx->io.WritePdu(transport, ls);
 
 1075    Stream_SetPosition(ls, 0);
 
 1079  Stream_Free(ls, TRUE);
 
 1083static DWORD WINAPI test_peer_mainloop(LPVOID arg)
 
 1086  DWORD error = CHANNEL_RC_OK;
 
 1087  HANDLE handles[MAXIMUM_WAIT_OBJECTS] = { 0 };
 
 1090  testPeerContext* context = NULL;
 
 1091  rdpSettings* settings = NULL;
 
 1092  rdpInput* input = NULL;
 
 1093  rdpUpdate* update = NULL;
 
 1094  freerdp_peer* client = (freerdp_peer*)arg;
 
 1096  WINPR_ASSERT(client);
 
 1098  struct server_info* info = client->ContextExtra;
 
 1101  if (!test_peer_init(client))
 
 1103    freerdp_peer_free(client);
 
 1108  WINPR_ASSERT(client->context);
 
 1109  settings = client->context->settings;
 
 1110  WINPR_ASSERT(settings);
 
 1111  if (info->replay_dump)
 
 1118  rdpPrivateKey* key = freerdp_key_new_from_file_enc(info->key, NULL);
 
 1123  rdpCertificate* cert = freerdp_certificate_new_from_file(info->cert);
 
 1136                                   ENCRYPTION_LEVEL_CLIENT_COMPATIBLE))
 
 1154  client->PostConnect = tf_peer_post_connect;
 
 1155  client->Activate = tf_peer_activate;
 
 1157  WINPR_ASSERT(client->context);
 
 1158  input = client->context->input;
 
 1159  WINPR_ASSERT(input);
 
 1161  input->SynchronizeEvent = tf_peer_synchronize_event;
 
 1162  input->KeyboardEvent = tf_peer_keyboard_event;
 
 1163  input->UnicodeKeyboardEvent = tf_peer_unicode_keyboard_event;
 
 1164  input->MouseEvent = tf_peer_mouse_event;
 
 1165  input->RelMouseEvent = tf_peer_rel_mouse_event;
 
 1166  input->ExtendedMouseEvent = tf_peer_extended_mouse_event;
 
 1168  update = client->context->update;
 
 1169  WINPR_ASSERT(update);
 
 1171  update->RefreshRect = tf_peer_refresh_rect;
 
 1172  update->SuppressOutput = tf_peer_suppress_output;
 
 1177  WINPR_ASSERT(client->Initialize);
 
 1178  rc = client->Initialize(client);
 
 1182  context = (testPeerContext*)client->context;
 
 1183  WINPR_ASSERT(context);
 
 1185  if (info->replay_dump)
 
 1187    const rdpTransportIo* cb = freerdp_get_io_callbacks(client->context);
 
 1188    rdpTransportIo replay;
 
 1193    replay.WritePdu = hook_peer_write_pdu;
 
 1194    freerdp_set_io_callbacks(client->context, &replay);
 
 1197  WLog_INFO(TAG, 
"We've got a client %s", client->local ? 
"(local)" : client->hostname);
 
 1199  while (error == CHANNEL_RC_OK)
 
 1203      WINPR_ASSERT(client->GetEventHandles);
 
 1204      DWORD tmp = client->GetEventHandles(client, &handles[count], 32 - count);
 
 1208        WLog_ERR(TAG, 
"Failed to get FreeRDP transport event handles");
 
 1215    HANDLE channelHandle = WTSVirtualChannelManagerGetEventHandle(context->vcm);
 
 1216    handles[count++] = channelHandle;
 
 1217    status = WaitForMultipleObjects(count, handles, FALSE, INFINITE);
 
 1219    if (status == WAIT_FAILED)
 
 1221      WLog_ERR(TAG, 
"WaitForMultipleObjects failed (errno: %d)", errno);
 
 1225    WINPR_ASSERT(client->CheckFileDescriptor);
 
 1226    if (client->CheckFileDescriptor(client) != TRUE)
 
 1229    if (WTSVirtualChannelManagerCheckFileDescriptor(context->vcm) != TRUE)
 
 1233    if (WTSVirtualChannelManagerIsChannelJoined(context->vcm, DRDYNVC_SVC_CHANNEL_NAME))
 
 1235      switch (WTSVirtualChannelManagerGetDrdynvcState(context->vcm))
 
 1237        case DRDYNVC_STATE_NONE:
 
 1240        case DRDYNVC_STATE_INITIALIZED:
 
 1243        case DRDYNVC_STATE_READY:
 
 1246          if (sf_peer_audin_running(context) != context->audin_open)
 
 1248            if (!sf_peer_audin_running(context))
 
 1249              sf_peer_audin_start(context);
 
 1251              sf_peer_audin_stop(context);
 
 1254#if defined(CHANNEL_AINPUT_SERVER) 
 1255          if (sf_peer_ainput_running(context) != context->ainput_open)
 
 1257            if (!sf_peer_ainput_running(context))
 
 1258              sf_peer_ainput_start(context);
 
 1260              sf_peer_ainput_stop(context);
 
 1266        case DRDYNVC_STATE_FAILED:
 
 1273  WLog_INFO(TAG, 
"Client %s disconnected.", client->local ? 
"(local)" : client->hostname);
 
 1275  WINPR_ASSERT(client->Disconnect);
 
 1276  client->Disconnect(client);
 
 1278  freerdp_peer_context_free(client);
 
 1279  freerdp_peer_free(client);
 
 1283static BOOL test_peer_accepted(freerdp_listener* instance, freerdp_peer* client)
 
 1285  HANDLE hThread = NULL;
 
 1287  WINPR_UNUSED(instance);
 
 1289  WINPR_ASSERT(instance);
 
 1290  WINPR_ASSERT(client);
 
 1292  struct server_info* info = instance->info;
 
 1293  client->ContextExtra = info;
 
 1295  if (!(hThread = CreateThread(NULL, 0, test_peer_mainloop, (
void*)client, 0, NULL)))
 
 1298  (void)CloseHandle(hThread);
 
 1302static void test_server_mainloop(freerdp_listener* instance)
 
 1304  HANDLE handles[32] = { 0 };
 
 1308  WINPR_ASSERT(instance);
 
 1311    WINPR_ASSERT(instance->GetEventHandles);
 
 1312    count = instance->GetEventHandles(instance, handles, 32);
 
 1316      WLog_ERR(TAG, 
"Failed to get FreeRDP event handles");
 
 1320    status = WaitForMultipleObjects(count, handles, FALSE, INFINITE);
 
 1322    if (WAIT_FAILED == status)
 
 1324      WLog_ERR(TAG, 
"select failed");
 
 1328    WINPR_ASSERT(instance->CheckFileDescriptor);
 
 1329    if (instance->CheckFileDescriptor(instance) != TRUE)
 
 1331      WLog_ERR(TAG, 
"Failed to check FreeRDP file descriptor");
 
 1336  WINPR_ASSERT(instance->Close);
 
 1337  instance->Close(instance);
 
 1342  const char spcap[7];
 
 1343  const char sfast[7];
 
 1344  const char sport[7];
 
 1345  const char slocal_only[13];
 
 1346  const char scert[7];
 
 1348} options = { 
"--pcap=", 
"--fast", 
"--port=", 
"--local-only", 
"--cert=", 
"--key=" };
 
 1350WINPR_PRAGMA_DIAG_PUSH
 
 1351WINPR_PRAGMA_DIAG_IGNORED_FORMAT_NONLITERAL
 
 1352WINPR_ATTR_FORMAT_ARG(2, 0)
 
 1353static 
void print_entry(FILE* fp, WINPR_FORMAT_ARG const 
char* fmt, const 
char* what, 
size_t size)
 
 1355  char buffer[32] = { 0 };
 
 1356  strncpy(buffer, what, MIN(size, 
sizeof(buffer) - 1));
 
 1357  (void)fprintf(fp, fmt, buffer);
 
 1359WINPR_PRAGMA_DIAG_POP
 
 1361static int usage(
const char* app, 
const char* invalid)
 
 1365  (void)fprintf(fp, 
"Invalid argument '%s'\n", invalid);
 
 1366  (void)fprintf(fp, 
"Usage: %s <arg>[ <arg> ...]\n", app);
 
 1367  (void)fprintf(fp, 
"Arguments:\n");
 
 1368  print_entry(fp, 
"\t%s<pcap file>\n", options.spcap, 
sizeof(options.spcap));
 
 1369  print_entry(fp, 
"\t%s<cert file>\n", options.scert, 
sizeof(options.scert));
 
 1370  print_entry(fp, 
"\t%s<key file>\n", options.skey, 
sizeof(options.skey));
 
 1371  print_entry(fp, 
"\t%s\n", options.sfast, 
sizeof(options.sfast));
 
 1372  print_entry(fp, 
"\t%s<port>\n", options.sport, 
sizeof(options.sport));
 
 1373  print_entry(fp, 
"\t%s\n", options.slocal_only, 
sizeof(options.slocal_only));
 
 1377int main(
int argc, 
char* argv[])
 
 1380  BOOL started = FALSE;
 
 1382  freerdp_listener* instance = NULL;
 
 1384  char name[MAX_PATH] = { 0 };
 
 1386  BOOL localOnly = FALSE;
 
 1387  struct server_info info = { 0 };
 
 1388  const char* app = argv[0];
 
 1390  info.test_dump_rfx_realtime = TRUE;
 
 1394  for (
int i = 1; i < argc; i++)
 
 1396    char* arg = argv[i];
 
 1398    if (strncmp(arg, options.sfast, 
sizeof(options.sfast)) == 0)
 
 1399      info.test_dump_rfx_realtime = FALSE;
 
 1400    else if (strncmp(arg, options.sport, 
sizeof(options.sport)) == 0)
 
 1402      const char* sport = &arg[
sizeof(options.sport)];
 
 1403      port = strtol(sport, NULL, 10);
 
 1405      if ((port < 1) || (port > UINT16_MAX) || (errno != 0))
 
 1406        return usage(app, arg);
 
 1408    else if (strncmp(arg, options.slocal_only, 
sizeof(options.slocal_only)) == 0)
 
 1410    else if (strncmp(arg, options.spcap, 
sizeof(options.spcap)) == 0)
 
 1412      info.test_pcap_file = &arg[
sizeof(options.spcap)];
 
 1413      if (!winpr_PathFileExists(info.test_pcap_file))
 
 1414        return usage(app, arg);
 
 1416    else if (strncmp(arg, options.scert, 
sizeof(options.scert)) == 0)
 
 1418      info.cert = &arg[
sizeof(options.scert)];
 
 1419      if (!winpr_PathFileExists(info.cert))
 
 1420        return usage(app, arg);
 
 1422    else if (strncmp(arg, options.skey, 
sizeof(options.skey)) == 0)
 
 1424      info.key = &arg[
sizeof(options.skey)];
 
 1425      if (!winpr_PathFileExists(info.key))
 
 1426        return usage(app, arg);
 
 1429      return usage(app, arg);
 
 1432  WTSRegisterWtsApiFunctionTable(FreeRDP_InitWtsApi());
 
 1433  winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
 
 1434  instance = freerdp_listener_new();
 
 1440    info.cert = 
"server.crt";
 
 1442    info.key = 
"server.key";
 
 1444  instance->info = (
void*)&info;
 
 1445  instance->PeerAccepted = test_peer_accepted;
 
 1447  if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
 
 1451  (void)sprintf_s(name, 
sizeof(name), 
"tfreerdp-server.%ld", port);
 
 1452  file = GetKnownSubPath(KNOWN_PATH_TEMP, name);
 
 1459    WINPR_ASSERT(instance->OpenLocal);
 
 1460    started = instance->OpenLocal(instance, file);
 
 1464    WINPR_ASSERT(instance->Open);
 
 1465    started = instance->Open(instance, NULL, (UINT16)port);
 
 1472    test_server_mainloop(instance);
 
 1478  freerdp_listener_free(instance);
 
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
 
FREERDP_API BOOL freerdp_settings_set_string(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *param)
Sets a string settings value. The param is copied.
 
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
 
FREERDP_API BOOL freerdp_settings_set_pointer_len(rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id, const void *data, size_t len)
Set a pointer to value data.
 
FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 param)
Sets a UINT32 settings value.
 
FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.
 
FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL param)
Sets a BOOL settings value.