/*
 * PtokaX - hub server for Direct Connect peer to peer network.

 * Copyright (C) 2002-2005  Ptaczek, Ptaczek at PtokaX dot org
 * Copyright (C) 2004-2022  Petr Kozelka, PPK at PtokaX dot org

 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3
 * as published by the Free Software Foundation.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "stdinc.h"
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "GlobalDataQueue.h"
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include "colUsers.h"
#include "ProfileManager.h"
#include "ServerManager.h"
#include "SettingManager.h"
#include "User.h"
#include "utility.h"
#include "ZlibUtility.h"
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#ifdef _WIN32
#pragma hdrstop
#else
#define _countof(a) (sizeof(a)/sizeof(*(a)))
#endif
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GlobalDataQueue * GlobalDataQueue::m_Ptr = NULL;
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

GlobalDataQueue::GlobalDataQueue() : m_pCreatedGlobalQueues(NULL), m_pQueueItems(NULL), m_pSingleItems(NULL), m_bHaveItems(false)
{
	// OpList buffer
	m_OpListQueue.m_pBuffer = (char *)calloc(256, 1);
	if (m_OpListQueue.m_pBuffer == NULL)
	{
		AppendDebugLog("%s - [MEM] Cannot create m_OpListQueue\n");
		exit(EXIT_FAILURE);
	}
	m_OpListQueue.m_szLen = 0;
	m_OpListQueue.m_szSize = 255;

	// UserIP buffer
	m_UserIPQueue.m_pBuffer = (char *)calloc(256, 1);
	if (m_UserIPQueue.m_pBuffer == NULL)
	{
		AppendDebugLog("%s - [MEM] Cannot create m_UserIPQueue\n");
		exit(EXIT_FAILURE);
	}
	m_UserIPQueue.m_szLen = 0;
	m_UserIPQueue.m_szSize = 255;
	m_UserIPQueue.m_bHaveDollars = false;

	m_pNewQueueItems[0] = NULL;
	m_pNewQueueItems[1] = NULL;

	m_pNewSingleItems[0] = NULL;
	m_pNewSingleItems[1] = NULL;

	for (uint8_t ui8i = 0; ui8i < _countof(m_GlobalQueues); ui8i++)
	{
		m_GlobalQueues[ui8i].m_szLen = 0;
		m_GlobalQueues[ui8i].m_szSize = 255;
		m_GlobalQueues[ui8i].m_szZlen = 0;
		m_GlobalQueues[ui8i].m_szZsize = 255;

		m_GlobalQueues[ui8i].m_pBuffer = (char *)calloc(256, 1);
		m_GlobalQueues[ui8i].m_pZbuffer = (char *)calloc(256, 1);
		if (m_GlobalQueues[ui8i].m_pBuffer == NULL || m_GlobalQueues[ui8i].m_pZbuffer == NULL)
		{
			AppendDebugLog("%s - [MEM] Cannot create m_GlobalQueues[ui8i]\n");
			exit(EXIT_FAILURE);
		}

		m_GlobalQueues[ui8i].m_pNext = NULL;
		m_GlobalQueues[ui8i].m_bCreated = false;
		m_GlobalQueues[ui8i].m_bZlined = false;
	}
	m_exposer->RegisterCollectable(m_registry);
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

GlobalDataQueue::~GlobalDataQueue()
{
	free(m_OpListQueue.m_pBuffer);
	free(m_UserIPQueue.m_pBuffer);

	if (m_pNewSingleItems[0] != NULL)
	{
		SingleDataItem * pCur = NULL,
		                 * pNext = m_pNewSingleItems[0];

		while (pNext != NULL)
		{
			pCur = pNext;
			pNext = pCur->m_pNext;

			free(pCur->m_pData);
			delete pCur;
		}
	}

	if (m_pSingleItems != NULL)
	{
		SingleDataItem * pCur = NULL,
		                 * pNext = m_pSingleItems;

		while (pNext != NULL)
		{
			pCur = pNext;
			pNext = pCur->m_pNext;

			free(pCur->m_pData);
			delete pCur;
		}
	}

	if (m_pNewQueueItems[0] != NULL)
	{
		QueueItem * pCur = NULL,
		            * pNext = m_pNewQueueItems[0];

		while (pNext != NULL)
		{
			pCur = pNext;
			pNext = pCur->m_pNext;
			delete pCur;
		}
	}

	if (m_pQueueItems != NULL)
	{
		QueueItem * pCur = NULL,
		            * pNext = m_pQueueItems;

		while (pNext != NULL)
		{
			pCur = pNext;
			pNext = pCur->m_pNext;
			delete pCur;
		}
	}

	for (uint8_t ui8i = 0; ui8i < _countof(m_GlobalQueues); ui8i++)
	{
		free(m_GlobalQueues[ui8i].m_pBuffer);
		free(m_GlobalQueues[ui8i].m_pZbuffer);
	}
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

void GlobalDataQueue::AddQueueItem(const char * sCommand1, const size_t szLen1, const char * sCommand2, const size_t szLen2, const uint8_t ui8CmdType)
{
	QueueItem * pNewItem = new (std::nothrow) QueueItem;
	if (pNewItem == NULL)
	{
		AppendDebugLog("%s - [MEM] Cannot allocate pNewItem in GlobalDataQueue::AddQueueItem\n");
		return;
	}

	if (sCommand1 && szLen1)
	{
		pNewItem->m_pCommand[0] = std::string(sCommand1, szLen1);
	}
	if (sCommand2 != NULL && szLen2)
	{
		pNewItem->m_pCommand[1] = std::string(sCommand2, szLen2);
	}

	pNewItem->m_ui8CommandType = ui8CmdType;

	pNewItem->m_pNext = nullptr;

	if (m_pNewQueueItems[0] == NULL)
	{
		m_pNewQueueItems[0] = pNewItem;
		m_pNewQueueItems[1] = pNewItem;
	}
	else
	{
		m_pNewQueueItems[1]->m_pNext = pNewItem;
		m_pNewQueueItems[1] = pNewItem;
	}
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

// appends data to the m_OpListQueue
void GlobalDataQueue::OpListStore(const char * sNick)
{
	if (m_OpListQueue.m_szLen == 0)
	{
		int iLen = snprintf(m_OpListQueue.m_pBuffer, m_OpListQueue.m_szSize, "$OpList %s$$|", sNick);
		if (iLen <= 0)
		{
			m_OpListQueue.m_szLen = 0;
		}
		else
		{
			m_OpListQueue.m_szLen = iLen;
		}
	}
	else
	{
		size_t szNickLen = strlen(sNick) + 3;
		if (m_OpListQueue.m_szSize < m_OpListQueue.m_szLen + szNickLen)
		{
			size_t szAllignLen = Allign(m_OpListQueue.m_szLen + szNickLen);
			char * pOldBuf = m_OpListQueue.m_pBuffer;
			m_OpListQueue.m_pBuffer = (char *)realloc(pOldBuf, szAllignLen);
			if (m_OpListQueue.m_pBuffer == NULL)
			{
				m_OpListQueue.m_pBuffer = pOldBuf;

				AppendDebugLogFormat("[MEM] Cannot reallocate %zu bytes in GlobalDataQueue::OpListStore\n", szAllignLen);

				return;
			}
			m_OpListQueue.m_szSize = szAllignLen - 1;
		}

		int iDataLen = snprintf(m_OpListQueue.m_pBuffer + m_OpListQueue.m_szLen - 1, m_OpListQueue.m_szSize - (m_OpListQueue.m_szLen - 1), "%s$$|", sNick);
		if (iDataLen <= 0)
		{
			m_OpListQueue.m_pBuffer[m_OpListQueue.m_szLen - 1] = '|';
			m_OpListQueue.m_pBuffer[m_OpListQueue.m_szLen] = '\0';
		}
		else
		{
			m_OpListQueue.m_szLen += iDataLen - 1;
		}
	}
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

// appends data to the UserIPQueue
void GlobalDataQueue::UserIPStore(User * pUser)
{
	if (m_UserIPQueue.m_szLen == 0)
	{
		m_UserIPQueue.m_szLen = snprintf(m_UserIPQueue.m_pBuffer, m_UserIPQueue.m_szSize, "$UserIP %s %s|", pUser->m_sNick, pUser->m_sIP);
		if (m_UserIPQueue.m_szLen > 0)
		{
			m_UserIPQueue.m_bHaveDollars = false;
		}
		else
		{
			m_UserIPQueue.m_szLen = 0;
		}
	}
	else
	{
		size_t szLen = pUser->m_ui8NickLen + pUser->m_ui8IpLen + 4;
		if (m_UserIPQueue.m_szSize < m_UserIPQueue.m_szLen + szLen)
		{
			size_t szAllignLen = Allign(m_UserIPQueue.m_szLen + szLen);
			char * pOldBuf = m_UserIPQueue.m_pBuffer;
			m_UserIPQueue.m_pBuffer = (char *)realloc(pOldBuf, szAllignLen);
			if (m_UserIPQueue.m_pBuffer == NULL)
			{
				m_UserIPQueue.m_pBuffer = pOldBuf;

				AppendDebugLogFormat("[MEM] Cannot reallocate %zu bytes in GlobalDataQueue::UserIPStore\n", szAllignLen);

				return;
			}
			m_UserIPQueue.m_szSize = szAllignLen - 1;
		}

		if (m_UserIPQueue.m_bHaveDollars == false)
		{
			m_UserIPQueue.m_pBuffer[m_UserIPQueue.m_szLen - 1] = '$';
			m_UserIPQueue.m_pBuffer[m_UserIPQueue.m_szLen] = '$';
			m_UserIPQueue.m_bHaveDollars = true;
			m_UserIPQueue.m_szLen += 2;
		}

		int iDataLen = snprintf(m_UserIPQueue.m_pBuffer + m_UserIPQueue.m_szLen - 1, m_UserIPQueue.m_szSize - (m_UserIPQueue.m_szLen - 1), "%s %s$$|", pUser->m_sNick, pUser->m_sIP);
		if (iDataLen <= 0)
		{
			m_UserIPQueue.m_pBuffer[m_UserIPQueue.m_szLen - 1] = '|';
			m_UserIPQueue.m_pBuffer[m_UserIPQueue.m_szLen] = '\0';
		}
		else
		{
			m_UserIPQueue.m_szLen += iDataLen - 1;
		}
	}
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

void GlobalDataQueue::PrepareQueueItems()
{
	m_pQueueItems = m_pNewQueueItems[0];

	m_pNewQueueItems[0] = NULL;
	m_pNewQueueItems[1] = NULL;

	if (m_pQueueItems != NULL || m_OpListQueue.m_szLen != 0 || m_UserIPQueue.m_szLen != 0)
	{
		m_bHaveItems = true;
	}

	m_pSingleItems = m_pNewSingleItems[0];

	m_pNewSingleItems[0] = NULL;
	m_pNewSingleItems[1] = NULL;
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

void GlobalDataQueue::ClearQueues()
{
	m_bHaveItems = false;

	if (m_pCreatedGlobalQueues != NULL)
	{
		GlobalQueue * pCur = NULL,
		              * pNext = m_pCreatedGlobalQueues;

		while (pNext != NULL)
		{
			pCur = pNext;
			pNext = pCur->m_pNext;

			pCur->m_szLen = 0;
			pCur->clean(); // [+]FlylilinkDC++
			pCur->m_szZlen = 0;
			pCur->m_pNext = NULL;
			pCur->m_bCreated = false;
			pCur->m_bZlined = false;
		}
	}

	m_pCreatedGlobalQueues = NULL;

	m_OpListQueue.m_pBuffer[0] = '\0';
	m_OpListQueue.m_szLen = 0;

	m_UserIPQueue.m_pBuffer[0] = '\0';
	m_UserIPQueue.m_szLen = 0;

	if (m_pQueueItems != NULL)
	{
		QueueItem * pCur = NULL,
		            * pNext = m_pQueueItems;

		while (pNext != NULL)
		{
			pCur = pNext;
			pNext = pCur->m_pNext;

			delete pCur;
		}
	}

	m_pQueueItems = NULL;

	if (m_pSingleItems != NULL)
	{
		SingleDataItem * pCur = NULL,
		                 * pNext = m_pSingleItems;

		while (pNext != NULL)
		{
			pCur = pNext;
			pNext = pCur->m_pNext;

			free(pCur->m_pData);
			delete pCur;
		}
	}

	m_pSingleItems = nullptr;
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void GlobalDataQueue::AddSearchDataToQueue(const User * pUser, uint32_t ui32QueueType, const QueueItem * pCur) // FlylinkDC++
{
	if (pUser->m_ui64SharedSize)
	{
		AddDataToQueue(m_GlobalQueues[ui32QueueType], pCur->m_pCommand[0]);
	}
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

void GlobalDataQueue::ProcessQueues(User * pUser)
{
	uint32_t ui32QueueType = 0; // short myinfos
	uint16_t ui16QueueBits = 0;

	if (SettingManager::m_Ptr->m_ui8FullMyINFOOption == 1 && ProfileManager::m_Ptr->IsAllowed(pUser, ProfileManager::SENDFULLMYINFOS))
	{
		ui32QueueType = 1; // full myinfos
		ui16QueueBits |= BIT_LONG_MYINFO;
	}

	if (pUser->m_ui64SharedSize != 0)
	{
		if (((pUser->m_ui32BoolBits & User::BIT_IPV6) == User::BIT_IPV6) == true)
		{
			if (((pUser->m_ui32BoolBits & User::BIT_IPV4) == User::BIT_IPV4) == true)
			{
				if (((pUser->m_ui32BoolBits & User::BIT_IPV6_ACTIVE) == User::BIT_IPV6_ACTIVE) == true)
				{
					if (((pUser->m_ui32BoolBits & User::BIT_IPV4_ACTIVE) == User::BIT_IPV4_ACTIVE) == true)
					{
						ui32QueueType += 6; // all searches both ipv4 and ipv6
						ui16QueueBits |= BIT_ALL_SEARCHES_IPV64;
					}
					else
					{
						ui32QueueType += 14; // all searches ipv6 + active searches ipv4
						ui16QueueBits |= BIT_ALL_SEARCHES_IPV6_ACTIVE_IPV4;
					}
				}
				else
				{
					if (((pUser->m_ui32BoolBits & User::BIT_IPV4_ACTIVE) == User::BIT_IPV4_ACTIVE) == true)
					{
						ui32QueueType += 16; // active searches ipv6 + all searches ipv4
						ui16QueueBits |= BIT_ACTIVE_SEARCHES_IPV6_ALL_IPV4;
					}
					else
					{
						ui32QueueType += 12; // active searches both ipv4 and ipv6
						ui16QueueBits |= BIT_ACTIVE_SEARCHES_IPV64;
					}
				}
			}
			else
			{
				if (((pUser->m_ui32BoolBits & User::BIT_IPV6_ACTIVE) == User::BIT_IPV6_ACTIVE) == true)
				{
					ui32QueueType += 4; // all searches ipv6 only
					ui16QueueBits |= BIT_ALL_SEARCHES_IPV6;
				}
				else
				{
					ui32QueueType += 10; // active searches ipv6 only
					ui16QueueBits |= BIT_ACTIVE_SEARCHES_IPV6;
				}
			}
		}
		else
		{
			if (((pUser->m_ui32BoolBits & User::BIT_IPV4_ACTIVE) == User::BIT_IPV4_ACTIVE) == true)
			{
				ui32QueueType += 2; // all searches ipv4 only
				ui16QueueBits |= BIT_ALL_SEARCHES_IPV4;
			}
			else
			{
				ui32QueueType += 8; // active searches ipv4 only
				ui16QueueBits |= BIT_ACTIVE_SEARCHES_IPV4;
			}
		}
	}

	if (((pUser->m_ui32SupportBits & User::SUPPORTBIT_NOHELLO) == User::SUPPORTBIT_NOHELLO) == false)
	{
		ui32QueueType += 14; // send hellos
		ui16QueueBits |= BIT_HELLO;
	}

	if (((pUser->m_ui32BoolBits & User::BIT_OPERATOR) == User::BIT_OPERATOR) == true)
	{
		ui32QueueType += 28; // send operator data
		ui16QueueBits |= BIT_OPERATOR;
	}

	if (pUser->m_i32Profile != -1 && ((pUser->m_ui32SupportBits & User::SUPPORTBIT_USERIP2) == User::SUPPORTBIT_USERIP2) == true &&
	        ProfileManager::m_Ptr->IsAllowed(pUser, ProfileManager::SENDALLUSERIP) == true)
	{
		ui32QueueType += 56; // send userips
		ui16QueueBits |= BIT_USERIP;
	}

	if (m_GlobalQueues[ui32QueueType].m_bCreated == false)
	{
		if (m_pQueueItems != NULL)
		{
			QueueItem * pCur = NULL,
			            * pNext = m_pQueueItems;

			while (pNext != NULL)
			{
				pCur = pNext;
				pNext = pCur->m_pNext;

				switch (pCur->m_ui8CommandType)
				{
				case CMD_HELLO:
					if ((ui16QueueBits & BIT_HELLO) == BIT_HELLO)
					{
						AddDataToQueue(m_GlobalQueues[ui32QueueType], pCur->m_pCommand[0]);
					}
					break;
#ifdef USE_FLYLINKDC_EXT_JSON
				case CMD_EXTJSON:
					if (!pCur->m_pCommand[0].empty())
					{
						if (pUser->isSupportExtJSON())
						{
							AddDataToQueue(m_GlobalQueues[ui32QueueType], pCur->m_pCommand[0]);
						}
#ifdef _DEBUG
						else
						{
							int a = 0;
							a++;
						}
#endif
					}
					break;
#endif
				case CMD_MYINFO:
					if ((ui16QueueBits & BIT_LONG_MYINFO) == BIT_LONG_MYINFO)
					{
						AddDataToQueue(m_GlobalQueues[ui32QueueType], pCur->m_pCommand[1]);
						break;
					}

					AddDataToQueue(m_GlobalQueues[ui32QueueType], pCur->m_pCommand[0]);

					break;
				case CMD_OPS:
					if ((ui16QueueBits & BIT_OPERATOR) == BIT_OPERATOR)
					{
						AddDataToQueue(m_GlobalQueues[ui32QueueType], pCur->m_pCommand[0]);
					}
					break;
				case CMD_ACTIVE_SEARCH_V6:
					if (pUser->m_ui64SharedSize != 0 &&((ui16QueueBits & BIT_ALL_SEARCHES_IPV4) == BIT_ALL_SEARCHES_IPV4) == false &&
					        ((ui16QueueBits & BIT_ACTIVE_SEARCHES_IPV4) == BIT_ACTIVE_SEARCHES_IPV4) == false)
					{
						AddSearchDataToQueue(pUser, ui32QueueType, pCur); // [+]FlylinkDC++
					}
					break;
				case CMD_ACTIVE_SEARCH_V64:
					if (pUser->m_ui64SharedSize != 0 &&((ui16QueueBits & BIT_ALL_SEARCHES_IPV4) == BIT_ALL_SEARCHES_IPV4) == false &&
					        ((ui16QueueBits & BIT_ACTIVE_SEARCHES_IPV4) == BIT_ACTIVE_SEARCHES_IPV4) == false)
					{
						AddSearchDataToQueue(pUser, ui32QueueType, pCur); // [+]FlylinkDC++
					}
					else if (((ui16QueueBits & BIT_ALL_SEARCHES_IPV6) == BIT_ALL_SEARCHES_IPV6) == false &&
					         ((ui16QueueBits & BIT_ACTIVE_SEARCHES_IPV6) == BIT_ACTIVE_SEARCHES_IPV6) == false)
					{
						AddSearchDataToQueue(pUser, ui32QueueType, pCur); // [+]FlylinkDC++
					}
					break;
				case CMD_ACTIVE_SEARCH_V4:
					if (pUser->m_ui64SharedSize != 0 &&((ui16QueueBits & BIT_ALL_SEARCHES_IPV6) == BIT_ALL_SEARCHES_IPV6) == false &&
					        ((ui16QueueBits & BIT_ACTIVE_SEARCHES_IPV6) == BIT_ACTIVE_SEARCHES_IPV6) == false)
					{
						AddSearchDataToQueue(pUser, ui32QueueType, pCur); // [+]FlylinkDC++
					}
					break;
				case CMD_PASSIVE_SEARCH_V6:
					if (pUser->m_ui64SharedSize != 0 &&((ui16QueueBits & BIT_ALL_SEARCHES_IPV6) == BIT_ALL_SEARCHES_IPV6 || (ui16QueueBits & BIT_ALL_SEARCHES_IPV64) == BIT_ALL_SEARCHES_IPV64 ||
					                                    (ui16QueueBits & BIT_ALL_SEARCHES_IPV6_ACTIVE_IPV4) == BIT_ALL_SEARCHES_IPV6_ACTIVE_IPV4))
					{
						AddSearchDataToQueue(pUser, ui32QueueType, pCur); // [+]FlylinkDC++
					}
					break;
				case CMD_PASSIVE_SEARCH_V64:
					if (pUser->m_ui64SharedSize != 0 &&((ui16QueueBits & BIT_ALL_SEARCHES_IPV64) == BIT_ALL_SEARCHES_IPV64 || (ui16QueueBits & BIT_ALL_SEARCHES_IPV6) == BIT_ALL_SEARCHES_IPV6 ||
					                                    (ui16QueueBits & BIT_ALL_SEARCHES_IPV4) == BIT_ALL_SEARCHES_IPV4 || (ui16QueueBits & BIT_ACTIVE_SEARCHES_IPV6_ALL_IPV4) == BIT_ACTIVE_SEARCHES_IPV6_ALL_IPV4 ||
					                                    (ui16QueueBits & BIT_ALL_SEARCHES_IPV6_ACTIVE_IPV4) == BIT_ALL_SEARCHES_IPV6_ACTIVE_IPV4))
					{
						AddSearchDataToQueue(pUser, ui32QueueType, pCur); // [+]FlylinkDC++
					}
					break;
				case CMD_PASSIVE_SEARCH_V4:
					if (pUser->m_ui64SharedSize != 0 &&((ui16QueueBits & BIT_ALL_SEARCHES_IPV4) == BIT_ALL_SEARCHES_IPV4 || (ui16QueueBits & BIT_ALL_SEARCHES_IPV64) == BIT_ALL_SEARCHES_IPV64 ||
					                                    (ui16QueueBits & BIT_ACTIVE_SEARCHES_IPV6_ALL_IPV4) == BIT_ACTIVE_SEARCHES_IPV6_ALL_IPV4))
					{
						AddSearchDataToQueue(pUser, ui32QueueType, pCur); // [+]FlylinkDC++
					}
					break;
				case CMD_PASSIVE_SEARCH_V4_ONLY:
					if (pUser->m_ui64SharedSize != 0 &&(ui16QueueBits & BIT_ALL_SEARCHES_IPV4) == BIT_ALL_SEARCHES_IPV4)
					{
						AddSearchDataToQueue(pUser, ui32QueueType, pCur); // [+]FlylinkDC++
					}
					break;
				case CMD_PASSIVE_SEARCH_V6_ONLY:
					if (pUser->m_ui64SharedSize != 0 &&(ui16QueueBits & BIT_ALL_SEARCHES_IPV6) == BIT_ALL_SEARCHES_IPV6)
					{
						AddSearchDataToQueue(pUser, ui32QueueType, pCur); // [+]FlylinkDC++
					}
					break;
				case CMD_CHAT:
					AddDataToQueue(m_GlobalQueues[ui32QueueType], pCur->m_pCommand[0]);
					break;
				case CMD_HUBNAME:
				case CMD_QUIT:
				case CMD_LUA:
					AddDataToQueue(m_GlobalQueues[ui32QueueType], pCur->m_pCommand[0]);
					break;
				default:
					break; // should not happen ;)
				}
			}
		}

		if (m_OpListQueue.m_szLen != 0)
		{
			AddDataToQueue(m_GlobalQueues[ui32QueueType], m_OpListQueue.m_pBuffer, m_OpListQueue.m_szLen);
		}

		if (m_UserIPQueue.m_szLen != 0 && (ui16QueueBits & BIT_USERIP) == BIT_USERIP)
		{
			AddDataToQueue(m_GlobalQueues[ui32QueueType], m_UserIPQueue.m_pBuffer, m_UserIPQueue.m_szLen);
		}

		m_GlobalQueues[ui32QueueType].m_bCreated = true;
		m_GlobalQueues[ui32QueueType].m_pNext = m_pCreatedGlobalQueues;
		m_pCreatedGlobalQueues = &m_GlobalQueues[ui32QueueType];
	}

	if (m_GlobalQueues[ui32QueueType].m_szLen == 0)
	{
		if (ServerManager::m_ui8SrCntr == 0)
		{
			User::DeletePrcsdUsrCmd(pUser->m_pCmdActive6Search);
			User::DeletePrcsdUsrCmd(pUser->m_pCmdActive4Search);
		}

		return;
	}

	if (ServerManager::m_ui8SrCntr == 0)
	{
		if (pUser->m_ui64SharedSize == 0)
		{
			if (pUser->m_pCmdActive6Search != NULL)
			{
				User::DeletePrcsdUsrCmd(pUser->m_pCmdActive6Search);
				pUser->m_pCmdActive6Search = NULL;
			}

			if (pUser->m_pCmdActive4Search != NULL)
			{
				User::DeletePrcsdUsrCmd(pUser->m_pCmdActive4Search);
				pUser->m_pCmdActive4Search = NULL;
			}
		}
		else
		{
			if ((pUser->m_ui32BoolBits & User::BIT_IPV6) == User::BIT_IPV6)
			{
				if (((pUser->m_ui32SupportBits & User::SUPPORTBIT_ZPIPE) == User::SUPPORTBIT_ZPIPE) == true)
				{
					if (m_GlobalQueues[ui32QueueType].m_bZlined == false)
					{
						m_GlobalQueues[ui32QueueType].m_bZlined = true;
						m_GlobalQueues[ui32QueueType].m_pZbuffer = ZlibUtility::m_Ptr->CreateZPipe(m_GlobalQueues[ui32QueueType].m_pBuffer, m_GlobalQueues[ui32QueueType].m_szLen,
						        m_GlobalQueues[ui32QueueType].m_pZbuffer, m_GlobalQueues[ui32QueueType].m_szZlen, m_GlobalQueues[ui32QueueType].m_szZsize);
					}

					size_t szSearchLens = 0;
					if (pUser->m_pCmdActive6Search != NULL)
					{
						szSearchLens += pUser->m_pCmdActive6Search->m_ui32Len;
					}
					if (pUser->m_pCmdActive4Search != NULL)
					{
						szSearchLens += pUser->m_pCmdActive4Search->m_ui32Len;
					}

					if (m_GlobalQueues[ui32QueueType].m_szZlen != 0 && (m_GlobalQueues[ui32QueueType].m_szZlen <= (m_GlobalQueues[ui32QueueType].m_szLen - szSearchLens)))
					{
						pUser->PutInSendBuf(m_GlobalQueues[ui32QueueType].m_pZbuffer, m_GlobalQueues[ui32QueueType].m_szZlen);
						ServerManager::m_ui64BytesSentSaved += (m_GlobalQueues[ui32QueueType].m_szLen - m_GlobalQueues[ui32QueueType].m_szZlen);

						if (pUser->m_pCmdActive6Search != NULL)
						{
							User::DeletePrcsdUsrCmd(pUser->m_pCmdActive6Search);
							pUser->m_pCmdActive6Search = NULL;
						}

						if (pUser->m_pCmdActive4Search != NULL)
						{
							User::DeletePrcsdUsrCmd(pUser->m_pCmdActive4Search);
							pUser->m_pCmdActive4Search = NULL;
						}

						return;
					}
				}

				uint32_t ui32SbLen = pUser->m_ui32SendBufDataLen;
				pUser->PutInSendBuf(m_GlobalQueues[ui32QueueType].m_pBuffer, m_GlobalQueues[ui32QueueType].m_szLen);

				// PPK ... check if adding of searchs not cause buffer overflow !
				if (pUser->m_ui32SendBufDataLen <= ui32SbLen)
				{
					ui32SbLen = 0;
				}

				if (pUser->m_pCmdActive6Search != NULL)
				{
					pUser->RemFromSendBuf(pUser->m_pCmdActive6Search->m_sCommand, pUser->m_pCmdActive6Search->m_ui32Len, ui32SbLen);

					User::DeletePrcsdUsrCmd(pUser->m_pCmdActive6Search);
					pUser->m_pCmdActive6Search = NULL;
				}

				if (pUser->m_pCmdActive4Search != NULL)
				{
					pUser->RemFromSendBuf(pUser->m_pCmdActive4Search->m_sCommand, pUser->m_pCmdActive4Search->m_ui32Len, ui32SbLen);

					User::DeletePrcsdUsrCmd(pUser->m_pCmdActive4Search);
					pUser->m_pCmdActive4Search = NULL;
				}

				return;
			}
			else
			{
				if (pUser->m_pCmdActive4Search != NULL)
				{
					if (((pUser->m_ui32SupportBits & User::SUPPORTBIT_ZPIPE) == User::SUPPORTBIT_ZPIPE) == true)
					{
						if (m_GlobalQueues[ui32QueueType].m_bZlined == false)
						{
							m_GlobalQueues[ui32QueueType].m_bZlined = true;
							m_GlobalQueues[ui32QueueType].m_pZbuffer = ZlibUtility::m_Ptr->CreateZPipe(m_GlobalQueues[ui32QueueType].m_pBuffer, m_GlobalQueues[ui32QueueType].m_szLen,
							        m_GlobalQueues[ui32QueueType].m_pZbuffer, m_GlobalQueues[ui32QueueType].m_szZlen, m_GlobalQueues[ui32QueueType].m_szZsize);
						}

						if (m_GlobalQueues[ui32QueueType].m_szZlen != 0 && (m_GlobalQueues[ui32QueueType].m_szZlen <= (m_GlobalQueues[ui32QueueType].m_szLen - pUser->m_pCmdActive4Search->m_ui32Len)))
						{
							pUser->PutInSendBuf(m_GlobalQueues[ui32QueueType].m_pZbuffer, m_GlobalQueues[ui32QueueType].m_szZlen);
							ServerManager::m_ui64BytesSentSaved += (m_GlobalQueues[ui32QueueType].m_szLen - m_GlobalQueues[ui32QueueType].m_szZlen);

							User::DeletePrcsdUsrCmd(pUser->m_pCmdActive4Search);
							pUser->m_pCmdActive4Search = NULL;

							return;
						}
					}

					uint32_t ui32SbLen = pUser->m_ui32SendBufDataLen;
					pUser->PutInSendBuf(m_GlobalQueues[ui32QueueType].m_pBuffer, m_GlobalQueues[ui32QueueType].m_szLen);

					// PPK ... check if adding of searchs not cause buffer overflow !
					if (pUser->m_ui32SendBufDataLen <= ui32SbLen)
					{
						ui32SbLen = 0;
					}

					pUser->RemFromSendBuf(pUser->m_pCmdActive4Search->m_sCommand, pUser->m_pCmdActive4Search->m_ui32Len, ui32SbLen);

					User::DeletePrcsdUsrCmd(pUser->m_pCmdActive4Search);
					pUser->m_pCmdActive4Search = NULL;

					return;
				}
			}
		}
	}

	if (((pUser->m_ui32SupportBits & User::SUPPORTBIT_ZPIPE) == User::SUPPORTBIT_ZPIPE) == true)
	{
		if (m_GlobalQueues[ui32QueueType].m_bZlined == false)
		{
			m_GlobalQueues[ui32QueueType].m_bZlined = true;
			m_GlobalQueues[ui32QueueType].m_pZbuffer = ZlibUtility::m_Ptr->CreateZPipe(m_GlobalQueues[ui32QueueType].m_pBuffer, m_GlobalQueues[ui32QueueType].m_szLen, m_GlobalQueues[ui32QueueType].m_pZbuffer,
			        m_GlobalQueues[ui32QueueType].m_szZlen, m_GlobalQueues[ui32QueueType].m_szZsize);
		}

		if (m_GlobalQueues[ui32QueueType].m_szZlen != 0)
		{
			pUser->PutInSendBuf(m_GlobalQueues[ui32QueueType].m_pZbuffer, m_GlobalQueues[ui32QueueType].m_szZlen);
			ServerManager::m_ui64BytesSentSaved += (m_GlobalQueues[ui32QueueType].m_szLen - m_GlobalQueues[ui32QueueType].m_szZlen);

			return;
		}
	}

	pUser->PutInSendBuf(m_GlobalQueues[ui32QueueType].m_pBuffer, m_GlobalQueues[ui32QueueType].m_szLen);
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

void GlobalDataQueue::ProcessSingleItems(User * pUser) const
{
	size_t szLen = 0, szWanted = 0;
	int iRet = 0;

	SingleDataItem * pCur = NULL,
	                 * pNext = m_pSingleItems;

	while (pNext != NULL)
	{
		pCur = pNext;
		pNext = pCur->m_pNext;

		if (pCur->m_pFromUser != pUser)
		{
			switch (pCur->m_ui8Type)
			{
			case SI_PM2ALL:   // send PM to ALL
			{
				szWanted = szLen + pCur->m_szDataLen + pUser->m_ui8NickLen + 13;
				if (ServerManager::m_szGlobalBufferSize < szWanted)
				{
					if (CheckAndResizeGlobalBuffer(szWanted) == false)
					{
						AppendDebugLogFormat("[MEM] Cannot reallocate %zu bytes in GlobalDataQueue::ProcessSingleItems\n", Allign(szWanted));
						break;
					}
				}
				iRet = snprintf(ServerManager::m_pGlobalBuffer + szLen, ServerManager::m_szGlobalBufferSize - szLen, "$To: %s From: ", pUser->m_sNick);
				if (iRet > 0)
				{
					szLen += iRet;

					memcpy(ServerManager::m_pGlobalBuffer + szLen, pCur->m_pData, pCur->m_szDataLen);
					szLen += pCur->m_szDataLen;
					ServerManager::m_pGlobalBuffer[szLen] = '\0';
				}

				break;
			}
			case SI_PM2OPS:   // send PM only to operators
			{
				if (((pUser->m_ui32BoolBits & User::BIT_OPERATOR) == User::BIT_OPERATOR) == true)
				{
					szWanted = szLen + pCur->m_szDataLen + pUser->m_ui8NickLen + 13;
					if (ServerManager::m_szGlobalBufferSize < szWanted)
					{
						if (CheckAndResizeGlobalBuffer(szWanted) == false)
						{
							AppendDebugLogFormat("[MEM] Cannot reallocate %zu bytes in GlobalDataQueue::ProcessSingleItems1\n", Allign(szWanted));
							break;
						}
					}
					iRet = snprintf(ServerManager::m_pGlobalBuffer + szLen, ServerManager::m_szGlobalBufferSize - szLen, "$To: %s From: ", pUser->m_sNick);
					if (iRet > 0)
					{
						szLen += iRet;

						memcpy(ServerManager::m_pGlobalBuffer + szLen, pCur->m_pData, pCur->m_szDataLen);
						szLen += pCur->m_szDataLen;
						ServerManager::m_pGlobalBuffer[szLen] = '\0';
					}
				}
				break;
			}
			case SI_OPCHAT:   // send OpChat only to allowed users...
			{
				if (ProfileManager::m_Ptr->IsAllowed(pUser, ProfileManager::ALLOWEDOPCHAT) == true)
				{
					szWanted = szLen + pCur->m_szDataLen + pUser->m_ui8NickLen + 13;
					if (ServerManager::m_szGlobalBufferSize < szWanted)
					{
						if (CheckAndResizeGlobalBuffer(szWanted) == false)
						{
							AppendDebugLogFormat("[MEM] Cannot reallocate %zu bytes in GlobalDataQueue::ProcessSingleItems2\n", Allign(szWanted));
							break;
						}
					}
					iRet = snprintf(ServerManager::m_pGlobalBuffer + szLen, ServerManager::m_szGlobalBufferSize - szLen, "$To: %s From: ", pUser->m_sNick);
					if (iRet > 0)
					{
						szLen += iRet;

						memcpy(ServerManager::m_pGlobalBuffer + szLen, pCur->m_pData, pCur->m_szDataLen);
						szLen += pCur->m_szDataLen;
						ServerManager::m_pGlobalBuffer[szLen] = '\0';
					}
				}
				break;
			}
			case SI_TOPROFILE:   // send data only to given profile...
			{
				if (pUser->m_i32Profile == pCur->m_i32Profile)
				{
					szWanted = szLen + pCur->m_szDataLen;
					if (ServerManager::m_szGlobalBufferSize < szWanted)
					{
						if (CheckAndResizeGlobalBuffer(szWanted) == false)
						{
							AppendDebugLogFormat("[MEM] Cannot reallocate %zu bytes in GlobalDataQueue::ProcessSingleItems3\n", Allign(szWanted));
							break;
						}
					}
					memcpy(ServerManager::m_pGlobalBuffer + szLen, pCur->m_pData, pCur->m_szDataLen);
					szLen += pCur->m_szDataLen;
					ServerManager::m_pGlobalBuffer[szLen] = '\0';
				}
				break;
			}
			case SI_PM2PROFILE:   // send pm only to given profile...
			{
				if (pUser->m_i32Profile == pCur->m_i32Profile)
				{
					szWanted = szLen + pCur->m_szDataLen + pUser->m_ui8NickLen + 13;
					if (ServerManager::m_szGlobalBufferSize < szWanted)
					{
						if (CheckAndResizeGlobalBuffer(szWanted) == false)
						{
							AppendDebugLogFormat("[MEM] Cannot reallocate %zu bytes in GlobalDataQueue::ProcessSingleItems4\n", Allign(szWanted));
							break;
						}
					}
					iRet = snprintf(ServerManager::m_pGlobalBuffer + szLen, ServerManager::m_szGlobalBufferSize - szLen, "$To: %s From: ", pUser->m_sNick);
					if (iRet > 0)
					{
						szLen += iRet;

						memcpy(ServerManager::m_pGlobalBuffer + szLen, pCur->m_pData, pCur->m_szDataLen);
						szLen += pCur->m_szDataLen;
						ServerManager::m_pGlobalBuffer[szLen] = '\0';
					}
				}
				break;
			}
			default:
				break;
			}
		}
	}

	if (szLen != 0)
	{
		pUser->SendCharDelayed(ServerManager::m_pGlobalBuffer, szLen);
	}

	ReduceGlobalBuffer();
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

void GlobalDataQueue::SingleItemStore(const char * sData, const size_t szDataLen, User * pFromUser, const int32_t i32Profile, const uint8_t ui8Type)
{
	SingleDataItem * pNewItem = new (std::nothrow) SingleDataItem;
	if (pNewItem == NULL)
	{
		AppendDebugLog("%s - [MEM] Cannot allocate pNewItem in GlobalDataQueue::SingleItemStore\n");
		return;
	}

	if (sData != NULL)
	{
		pNewItem->m_pData = (char *)malloc(szDataLen + 1);
		if (pNewItem->m_pData == NULL)
		{
			delete pNewItem;

			AppendDebugLogFormat("[MEM] Cannot allocate %zu bytes in GlobalDataQueue::SingleItemStore\n", szDataLen+1);

			return;
		}

		memcpy(pNewItem->m_pData, sData, szDataLen);
		pNewItem->m_pData[szDataLen] = '\0';
	}
	else
	{
		pNewItem->m_pData = NULL;
	}

	pNewItem->m_szDataLen = szDataLen;

	pNewItem->m_pFromUser = pFromUser;

	pNewItem->m_ui8Type = ui8Type;

	pNewItem->m_pPrev = NULL;
	pNewItem->m_pNext = NULL;

	pNewItem->m_i32Profile = i32Profile;

	if (m_pNewSingleItems[0] == NULL)
	{
		m_pNewSingleItems[0] = pNewItem;
		m_pNewSingleItems[1] = pNewItem;
	}
	else
	{
		pNewItem->m_pPrev = m_pNewSingleItems[1];
		m_pNewSingleItems[1]->m_pNext = pNewItem;
		m_pNewSingleItems[1] = pNewItem;
	}
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

void GlobalDataQueue::SendFinalQueue()
{
	if (m_pQueueItems != NULL)
	{
		QueueItem * pCur = NULL,
		            * pNext = m_pQueueItems;

		while (pNext != NULL)
		{
			pCur = pNext;
			pNext = pCur->m_pNext;

			switch (pCur->m_ui8CommandType)
			{
			case CMD_OPS:
			case CMD_CHAT:
			case CMD_LUA:
				AddDataToQueue(m_GlobalQueues[0], pCur->m_pCommand[0]);
				break;
			default:
				break;
			}
		}
	}

	if (m_pNewQueueItems[0] != NULL)
	{
		QueueItem * pCur = NULL,
		            * pNext = m_pNewQueueItems[0];

		while (pNext != NULL)
		{
			pCur = pNext;
			pNext = pCur->m_pNext;

			switch (pCur->m_ui8CommandType)
			{
			case CMD_OPS:
			case CMD_CHAT:
			case CMD_LUA:
				AddDataToQueue(m_GlobalQueues[0], pCur->m_pCommand[0]);
				break;
			default:
				break;
			}
		}
	}

	if (m_GlobalQueues[0].m_szLen == 0)
	{
		return;
	}

	m_GlobalQueues[0].m_pZbuffer = ZlibUtility::m_Ptr->CreateZPipe(m_GlobalQueues[0].m_pBuffer, m_GlobalQueues[0].m_szLen, m_GlobalQueues[0].m_pZbuffer, m_GlobalQueues[0].m_szZlen, m_GlobalQueues[0].m_szZsize);

	User * pCur = NULL,
	       * pNext = Users::m_Ptr->m_pUserListS;

	while (pNext != NULL)
	{
		pCur = pNext;
		pNext = pCur->m_pNext;

		if (m_GlobalQueues[0].m_szZlen != 0)
		{
			pCur->PutInSendBuf(m_GlobalQueues[0].m_pZbuffer, m_GlobalQueues[0].m_szZlen);
			ServerManager::m_ui64BytesSentSaved += (m_GlobalQueues[0].m_szLen - m_GlobalQueues[0].m_szZlen);
		}
		else
		{
			pCur->PutInSendBuf(m_GlobalQueues[0].m_pBuffer, m_GlobalQueues[0].m_szLen);
		}
	}
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void GlobalDataQueue::AddDataToQueue(GlobalQueue &pQueue, const std::string& sData)
{
	if (!sData.empty())
	{
		AddDataToQueue(pQueue, sData.c_str(), sData.size());
	}
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void GlobalDataQueue::AddDataToQueue(GlobalQueue &rQueue, const char * sData, const size_t szLen)
{
	if (rQueue.m_szSize < (rQueue.m_szLen + szLen))
	{
		size_t szAllignLen = Allign(rQueue.m_szLen + szLen);
		char * pOldBuf = rQueue.m_pBuffer;

		rQueue.m_pBuffer = (char *)realloc(pOldBuf, szAllignLen);
		if (rQueue.m_pBuffer == NULL)
		{
			rQueue.m_pBuffer = pOldBuf;

			AppendDebugLogFormat("[MEM] Cannot reallocate %zu bytes in GlobalDataQueue::AddDataToQueue\n", szAllignLen);
			return;
		}

		rQueue.m_szSize = szAllignLen - 1;
	}

	memcpy(rQueue.m_pBuffer + rQueue.m_szLen, sData, szLen);
	rQueue.m_szLen += szLen;
	rQueue.m_pBuffer[rQueue.m_szLen] = '\0';
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

void * GlobalDataQueue::GetLastQueueItem()
{
	return m_pNewQueueItems[1];
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

void * GlobalDataQueue::GetFirstQueueItem()
{
	return m_pNewQueueItems[0];
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

void * GlobalDataQueue::InsertBlankQueueItem(void * pAfterItem, const uint8_t ui8CmdType)
{
	QueueItem * pNewItem = new (std::nothrow) QueueItem;
	if (pNewItem == NULL)
	{
		AppendDebugLog("%s - [MEM] Cannot allocate pNewItem in GlobalDataQueue::InsertBlankQueueItem\n");
		return NULL;
	}

	pNewItem->m_ui8CommandType = ui8CmdType;

	if (pAfterItem == m_pNewQueueItems[0])
	{
		pNewItem->m_pNext = m_pNewQueueItems[0];
		m_pNewQueueItems[0] = pNewItem;
		return pNewItem;
	}

	QueueItem * pCur = NULL,
	            * pNext = m_pNewQueueItems[0];

	while (pNext != NULL)
	{
		pCur = pNext;
		pNext = pCur->m_pNext;

		if (pCur == pAfterItem)
		{
			if (pCur->m_pNext == NULL)
			{
				m_pNewQueueItems[1] = pNewItem;
			}

			pNewItem->m_pNext = pCur->m_pNext;
			pCur->m_pNext = pNewItem;
			return pNewItem;
		}
	}

	pNewItem->m_pNext = NULL;

	if (m_pNewQueueItems[0] == NULL)
	{
		m_pNewQueueItems[0] = pNewItem;
		m_pNewQueueItems[1] = pNewItem;
	}
	else
	{
		m_pNewQueueItems[1]->m_pNext = pNewItem;
		m_pNewQueueItems[1] = pNewItem;
	}

	return pNewItem;
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

void GlobalDataQueue::FillBlankQueueItem(const char * sCommand, const size_t szLen, void * pVoidQueueItem)
{
	QueueItem * pQueueItem = reinterpret_cast<QueueItem *>(pVoidQueueItem);
	if (szLen)
	{
		pQueueItem->m_pCommand[0] = std::string(sCommand,szLen);
	}
	else
	{
		pQueueItem->m_pCommand[0].clear();
	}
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

void GlobalDataQueue::StatusMessageFormat(const char * sFrom, const char * sFormatMsg, ...)
{
	int iMsgLen = 0;

	if (SettingManager::m_Ptr->m_bBools[SETBOOL_SEND_STATUS_MESSAGES_AS_PM] == true)
	{
		iMsgLen = snprintf(ServerManager::m_pGlobalBuffer, ServerManager::m_szGlobalBufferSize, "%s $", SettingManager::m_Ptr->m_sPreTexts[SettingManager::SETPRETXT_HUB_SEC]);
		if (iMsgLen <= 0)
		{
			AppendDebugLogFormat("[ERR] snprintf wrong value %d in GlobalDataQueue::StatusMessageFormat from: %s\n", iMsgLen, sFrom);
			return;
		}
	}

	va_list vlArgs;
	va_start(vlArgs, sFormatMsg);

	int iRet = vsnprintf(ServerManager::m_pGlobalBuffer + iMsgLen, ServerManager::m_szGlobalBufferSize - iMsgLen, sFormatMsg, vlArgs);

	va_end(vlArgs);

	if (iRet <= 0)
	{
		AppendDebugLogFormat("[ERR] vsnprintf wrong value %d in GlobalDataQueue::StatusMessageFormat from: %s\n", iRet, sFrom);
		return;
	}

	iMsgLen += iRet;

	if (SettingManager::m_Ptr->m_bBools[SETBOOL_SEND_STATUS_MESSAGES_AS_PM] == true)
	{
		SingleItemStore(ServerManager::m_pGlobalBuffer, iMsgLen, NULL, 0, GlobalDataQueue::SI_PM2OPS);
	}
	else
	{
		AddQueueItem(ServerManager::m_pGlobalBuffer, iMsgLen, NULL, 0, GlobalDataQueue::CMD_OPS);
	}
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

V1042 This file is marked with copyleft license, which requires you to open the derived source code.

V1037 Two or more case-branches perform the same actions. Check lines: 602, 607