<commit_before>/**
 * FreeRDP: A Remote Desktop Protocol Implementation
 * Graphics Pipeline Extension
 *
 * Copyright 2013-2014 <NAME> <<EMAIL>>
 * Copyright 2015 Thincast Technologies GmbH
 * Copyright 2015 DI (FH) <NAME> <<EMAIL>>
 * Copyright 2016 Thincast Technologies GmbH
 * Copyright 2016 <NAME> <<EMAIL>>
 *
 * 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.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <assert.h>

#include <winpr/crt.h>
#include <winpr/wlog.h>
#include <winpr/print.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <winpr/stream.h>
#include <winpr/sysinfo.h>
#include <winpr/cmdline.h>
#include <winpr/collections.h>

#include <freerdp/addin.h>
#include <freerdp/channels/log.h>

#include "rdpgfx_common.h"
#include "rdpgfx_codec.h"

#include "rdpgfx_main.h"

#define TAG CHANNELS_TAG("rdpgfx.client")

/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
static UINT rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback)
{
	UINT error;
	UINT32 x;
	wStream* s;
	UINT16 index;
	RDPGFX_PLUGIN* gfx;
	RDPGFX_HEADER header;
	RDPGFX_CAPSET* capsSet;
	RDPGFX_CAPSET capsSets[RDPGFX_NUMBER_CAPSETS] = { 0 };
	RDPGFX_CAPS_ADVERTISE_PDU pdu;
	gfx = (RDPGFX_PLUGIN*) callback->plugin;
	header.flags = 0;
	header.cmdId = RDPGFX_CMDID_CAPSADVERTISE;
	pdu.capsSetCount = 0;
	pdu.capsSets = (RDPGFX_CAPSET*) capsSets;
	capsSet = &capsSets[pdu.capsSetCount++];
	capsSet->version = RDPGFX_CAPVERSION_8;
	capsSet->length = 4;
	capsSet->flags = 0;

	if (gfx->ThinClient)
		capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT;

	/* in CAPVERSION_8 the spec says that we should not have both
	 * thinclient and smallcache (and thinclient implies a small cache)
	 */
	if (gfx->SmallCache && !gfx->ThinClient)
		capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE;

	capsSet = &capsSets[pdu.capsSetCount++];
	capsSet->version = RDPGFX_CAPVERSION_81;
	capsSet->length = 4;
	capsSet->flags = 0;

	if (gfx->ThinClient)
		capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT;

	if (gfx->SmallCache)
		capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE;

#ifdef WITH_GFX_H264

	if (gfx->H264)
		capsSet->flags |= RDPGFX_CAPS_FLAG_AVC420_ENABLED;

#endif

	if (!gfx->H264 || gfx->AVC444)
	{
		UINT32 caps10Flags = 0;
		capsSet = &capsSets[pdu.capsSetCount++];
		capsSet->version = RDPGFX_CAPVERSION_10;
		capsSet->length = 4;

		if (gfx->SmallCache)
			caps10Flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE;

#ifdef WITH_GFX_H264

		if (!gfx->AVC444)
			caps10Flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED;

#else
		caps10Flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED;
#endif
		capsSet->flags = caps10Flags;
		capsSet = &capsSets[pdu.capsSetCount++];
		capsSet->version = RDPGFX_CAPVERSION_101;
		capsSet->length = 0x10;
		capsSet->flags = 0;
		capsSet = &capsSets[pdu.capsSetCount++];
		capsSet->version = RDPGFX_CAPVERSION_102;
		capsSet->length = 0x4;
		capsSet->flags = caps10Flags;

		if (gfx->ThinClient)
			caps10Flags |= RDPGFX_CAPS_FLAG_AVC_THINCLIENT;

		capsSet = &capsSets[pdu.capsSetCount++];
		capsSet->version = RDPGFX_CAPVERSION_103;
		capsSet->length = 0x4;
		capsSet->flags = caps10Flags & ~RDPGFX_CAPS_FLAG_SMALL_CACHE;
		capsSet = &capsSets[pdu.capsSetCount++];
		capsSet->version = RDPGFX_CAPVERSION_104;
		capsSet->length = 0x4;
		capsSet->flags = caps10Flags;
		capsSet = &capsSets[pdu.capsSetCount++];
		capsSet->version = RDPGFX_CAPVERSION_105;
		capsSet->length = 0x4;
		capsSet->flags = caps10Flags;

		/* TODO: Until  RDPGFX_MAP_SURFACE_TO_SCALED_OUTPUT_PDU and
		 * RDPGFX_MAP_SURFACE_TO_SCALED_WINDOW_PDU are not implemented do not
		 * announce the following version */
#if 0
		capsSet = &capsSets[pdu.capsSetCount++];
		capsSet->version = RDPGFX_CAPVERSION_106;
		capsSet->length = 0x4;
		capsSet->flags = caps10Flags;
#endif
	}

	header.pduLength = RDPGFX_HEADER_SIZE + 2;

	for (x = 0; x < pdu.capsSetCount; x++)
		header.pduLength += RDPGFX_CAPSET_BASE_SIZE + capsSets[x].length;

	WLog_Print(gfx->log, WLOG_DEBUG, "SendCapsAdvertisePdu %"PRIu16"", pdu.capsSetCount);
	s = Stream_New(NULL, header.pduLength);

	if (!s)
	{
		WLog_ERR(TAG, "Stream_New failed!");
		return CHANNEL_RC_NO_MEMORY;
	}

	if ((error = rdpgfx_write_header(s, &header)))
		goto fail;

	/* RDPGFX_CAPS_ADVERTISE_PDU */
	Stream_Write_UINT16(s, pdu.capsSetCount); /* capsSetCount (2 bytes) */
<commit_msg>Temporarily disable GFX version >= 10.3<commit_after>/**
 * FreeRDP: A Remote Desktop Protocol Implementation
 * Graphics Pipeline Extension
 *
 * Copyright 2013-2014 <NAME> <<EMAIL>>
 * Copyright 2015 Thincast Technologies GmbH
 * Copyright 2015 DI (FH) <NAME> <<EMAIL>>
 * Copyright 2016 Thincast Technologies GmbH
 * Copyright 2016 <NAME> <<EMAIL>>
 *
 * 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.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <assert.h>

#include <winpr/crt.h>
#include <winpr/wlog.h>
#include <winpr/print.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <winpr/stream.h>
#include <winpr/sysinfo.h>
#include <winpr/cmdline.h>
#include <winpr/collections.h>

#include <freerdp/addin.h>
#include <freerdp/channels/log.h>

#include "rdpgfx_common.h"
#include "rdpgfx_codec.h"

#include "rdpgfx_main.h"

#define TAG CHANNELS_TAG("rdpgfx.client")

/**
 * Function description
 *
 * @return 0 on success, otherwise a Win32 error code
 */
static UINT rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback)
{
	UINT error;
	UINT32 x;
	wStream* s;
	UINT16 index;
	RDPGFX_PLUGIN* gfx;
	RDPGFX_HEADER header;
	RDPGFX_CAPSET* capsSet;
	RDPGFX_CAPSET capsSets[RDPGFX_NUMBER_CAPSETS] = { 0 };
	RDPGFX_CAPS_ADVERTISE_PDU pdu;
	gfx = (RDPGFX_PLUGIN*) callback->plugin;
	header.flags = 0;
	header.cmdId = RDPGFX_CMDID_CAPSADVERTISE;
	pdu.capsSetCount = 0;
	pdu.capsSets = (RDPGFX_CAPSET*) capsSets;
	capsSet = &capsSets[pdu.capsSetCount++];
	capsSet->version = RDPGFX_CAPVERSION_8;
	capsSet->length = 4;
	capsSet->flags = 0;

	if (gfx->ThinClient)
		capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT;

	/* in CAPVERSION_8 the spec says that we should not have both
	 * thinclient and smallcache (and thinclient implies a small cache)
	 */
	if (gfx->SmallCache && !gfx->ThinClient)
		capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE;

	capsSet = &capsSets[pdu.capsSetCount++];
	capsSet->version = RDPGFX_CAPVERSION_81;
	capsSet->length = 4;
	capsSet->flags = 0;

	if (gfx->ThinClient)
		capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT;

	if (gfx->SmallCache)
		capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE;

#ifdef WITH_GFX_H264

	if (gfx->H264)
		capsSet->flags |= RDPGFX_CAPS_FLAG_AVC420_ENABLED;

#endif

	if (!gfx->H264 || gfx->AVC444)
	{
		UINT32 caps10Flags = 0;
		capsSet = &capsSets[pdu.capsSetCount++];
		capsSet->version = RDPGFX_CAPVERSION_10;
		capsSet->length = 4;

		if (gfx->SmallCache)
			caps10Flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE;

#ifdef WITH_GFX_H264

		if (!gfx->AVC444)
			caps10Flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED;

#else
		caps10Flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED;
#endif
		capsSet->flags = caps10Flags;
		capsSet = &capsSets[pdu.capsSetCount++];
		capsSet->version = RDPGFX_CAPVERSION_101;
		capsSet->length = 0x10;
		capsSet->flags = 0;
		capsSet = &capsSets[pdu.capsSetCount++];
		capsSet->version = RDPGFX_CAPVERSION_102;
		capsSet->length = 0x4;
		capsSet->flags = caps10Flags;

		if (gfx->ThinClient)
			caps10Flags |= RDPGFX_CAPS_FLAG_AVC_THINCLIENT;

		/* Reports from Remmina suggest that current H264 decoder settings do
		 * not work with newer GFX protocol versions.
		 * Need to investigate this.
		 * Until resolved, disable the newer protocol versions. */
#if 0
		capsSet = &capsSets[pdu.capsSetCount++];
		capsSet->version = RDPGFX_CAPVERSION_103;
		capsSet->length = 0x4;
		capsSet->flags = caps10Flags & ~RDPGFX_CAPS_FLAG_SMALL_CACHE;
		capsSet = &capsSets[pdu.capsSetCount++];
		capsSet->version = RDPGFX_CAPVERSION_104;
		capsSet->length = 0x4;
		capsSet->flags = caps10Flags;
		capsSet = &capsSets[pdu.capsSetCount++];
		capsSet->version = RDPGFX_CAPVERSION_105;
		capsSet->length = 0x4;
		capsSet->flags = caps10Flags;

		/* TODO: Until  RDPGFX_MAP_SURFACE_TO_SCALED_OUTPUT_PDU and
		 * RDPGFX_MAP_SURFACE_TO_SCALED_WINDOW_PDU are not implemented do not
		 * announce the following version */
#if 0
		capsSet = &capsSets[pdu.capsSetCount++];
		capsSet->version = RDPGFX_CAPVERSION_106;
		capsSet->length = 0x4;
		capsSet->flags = caps10Flags;
#endif
#endif
	}

	header.pduLength = RDPGFX_HEADER_SIZE + 2;

	for (x = 0; x < pdu.capsSetCount; x++)
		header.pduLength += RDPGFX_CAPSET_BASE_SIZE + capsSets[x].length;

	WLog_Print(gfx->log, WLOG_DEBUG, "SendCapsAdvertisePdu %"PRIu16"", pdu.capsSetCount);
	s = Stream_New(NULL, header.pduLength);

	if (!s)
	{
		WLog_ERR(TAG, "Stream_New failed!");
		return CHANNEL_RC_NO_MEMORY;
	}

	if ((error = rdpgfx_write_header(s, &header)))
		goto fail;

	/* RDPGFX_CAPS_ADVERTISE_PDU */
	Stream_Write_UINT16(s, pdu.capsSetCount); /* capsSetCount (2 bytes) */

{'fraction_non_alphanumeric': 0.11842766663315572, 'fraction_numerical': 0.02784759223886599, 'mean_word_length': 4.8209479227618495, 'pattern_counts': {'":': 0, '<': 47, '<?xml version=': 0, '>': 136, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2998268', 'n_tokens_mistral': 4181, 'n_tokens_neox': 3838, 'n_words': 821}