Beispiel #1
0
void PrintStackTrace(int skipCount, const char* executableName)
{
	void* addresses[16];
	const int symbolCount = backtrace(addresses, UDT_COUNT_OF(addresses));
	if(skipCount >= symbolCount)
	{
		return;
	}

	char** const messages = backtrace_symbols(addresses, symbolCount);
	if(messages == NULL)
	{
		return;
	}

	printf("Stack trace:\n");
	for(int i = skipCount; i < symbolCount; ++i)
	{
		printf("#%d %s\n", i, messages[i]);

		if(executableName == NULL)
		{
			continue;
		}

		char callBuffer[256];
		sprintf(callBuffer,"addr2line %p -e %s", addresses[i], executableName);
		system(callBuffer);
	}

	free(messages);
}
Beispiel #2
0
void udtBaseParser::ResetForGamestateMessage()
{
	_inServerMessageSequence = -1;
	_inServerCommandSequence = -1;
	_inReliableSequenceAcknowledge = -1;
	_inClientNum = -1;
	_inChecksumFeed = -1;
	_inParseEntitiesNum = 0;
	_inServerTime = S32_MIN;
	_inLastSnapshotMessageNumber = S32_MIN;

	_outServerCommandSequence = 0;
	_outSnapshotsWritten = 0;
	_outWriteFirstMessage = false;
	_outWriteMessage = false;

	memset(_inEntityBaselines, 0, sizeof(_inEntityBaselines));
	memset(_inSnapshots, 0, sizeof(_inSnapshots));
	memset(_inConfigStrings, 0, sizeof(_inConfigStrings));
	for(u32 i = 0; i < (u32)UDT_COUNT_OF(_inEntityEventTimesMs); ++i)
	{
		_inEntityEventTimesMs[i] = S32_MIN;
	}

	_configStringAllocator.Clear();
	_tempAllocator.Clear();
	_privateTempAllocator.Clear();
}
static void UTF8_WriteCodePoint(u32& newLength, char* output, u32 codePoint, const char* input)
{
	for(u32 i = 0; i < (u32)UDT_COUNT_OF(ShortEscapeCodePoints); ++i)
	{
		if(codePoint == ShortEscapeCodePoints[i].CodePoint)
		{
			newLength = 2;
			output[0] = '\\';
			output[1] = ShortEscapeCodePoints[i].OutputChar;
			return;
		}
	}

	// Range: 0x0000 - 0x001F
	if(codePoint <= 0x001F)
	{
		newLength = 6;
		output[0] = '\\';
		output[1] = 'u';
		output[2] = HexDigits[(codePoint >> 12) & 15];
		output[3] = HexDigits[(codePoint >> 8) & 15];
		output[4] = HexDigits[(codePoint >> 4) & 15];
		output[5] = HexDigits[codePoint & 15];
		return;
	}
Beispiel #4
0
const udtString udtBaseParser::GetConfigString(s32 csIndex) const
{
	if(csIndex < 0 || csIndex >= (s32)UDT_COUNT_OF(_inConfigStrings))
	{
		return udtString::NewEmptyConstant();
	}

	return _inConfigStrings[csIndex];
}
Beispiel #5
0
void udtBaseParser::WriteBigConfigStringCommand(const udtString& csIndex, const udtString& csData)
{
	// Simple example:
	// cs idx "name0\value0\name1\value1\name2\value2\name3\value3"
	// becomes:
	// bcs0 idx "name0\value0\"
	// bcs1 idx "name1\value1\"
	// bcs1 idx "name2\value2\"
	// bcs2 idx "name3\value3"
	const u32 maxLengthPerCmd = MAX_STRING_CHARS - 2;
	const u32 perCmdOverhead = 8 + csIndex.GetLength();
	const u32 maxDataLength = maxLengthPerCmd - perCmdOverhead;
	u32 outputChunks = 0;
	for(u32 i = 2;; ++i)
	{
		const u32 perCmdData = (csData.GetLength() + i - 1) / i;
		if(perCmdData + perCmdOverhead <= maxLengthPerCmd)
		{
			outputChunks = i;
			break;
		}
	}

	u32 dataOffset = 0;
	for(u32 i = 0; i < outputChunks; ++i)
	{
		const char* bcsIdxRaw = i == 0 ? "0" : (i == outputChunks - 1 ? "2" : "1");
		const udtString data = udtString::NewSubstringRef(csData, dataOffset, bcsIdxRaw[0] == '2' ? (u32)~0 : maxDataLength);
		const udtString bcs = udtString::NewConstRef("bcs");
		const udtString bcsIdx = udtString::NewConstRef(bcsIdxRaw);
		const udtString space = udtString::NewConstRef(" ");
		const udtString quote = udtString::NewConstRef("\"");
		udtString command = udtString::NewEmpty(_tempAllocator, MAX_STRING_CHARS);
		const udtString* cmdPieces[] =
		{
			&bcs,
			&bcsIdx,
			&space,
			&csIndex,
			&space,
			&quote,
			&data,
			&quote
		};
		udtString::AppendMultiple(command, cmdPieces, (u32)UDT_COUNT_OF(cmdPieces));

		_outMsg.WriteByte(svc_serverCommand);
		_outMsg.WriteLong(_outServerCommandSequence);
		_outMsg.WriteString(command.GetPtr(), (s32)command.GetLength());

		++_outServerCommandSequence;
		dataOffset += maxDataLength;
	}

}
Beispiel #6
0
bool udtPath::Combine(udtString& combinedPath, udtVMLinearAllocator& allocator, const udtString& folderPath, const udtString& extra)
{
	const bool isSeparatorNeeded = !HasTrailingSeparator(folderPath);
	const udtString path = udtString::IsNullOrEmpty(folderPath) ? udtString::NewConstRef(".") : folderPath;
	const udtString separator = isSeparatorNeeded ? udtString::NewConstRef(GetSeparator()) : udtString::NewEmptyConstant();
	const udtString* strings[] =
	{
		&path,
		&separator,
		&extra
	};

	combinedPath = udtString::NewFromConcatenatingMultiple(allocator, strings, (u32)UDT_COUNT_OF(strings));

	return true;
}
static bool UTF8_NeedsEscaping(u32& newLength, u32 codePoint)
{
	for(u32 i = 0; i < (u32)UDT_COUNT_OF(ShortEscapeCodePoints); ++i)
	{
		if(codePoint == ShortEscapeCodePoints[i].CodePoint)
		{
			newLength = 2; // Of form: "\A".
			return true;
		}
	}

	// Range: 0x0000 - 0x001F
	if(codePoint <= 0x001F)
	{
		newLength = 6; // Of form: "\uABCD".
		return true;
	}

	return false;
}
Beispiel #8
0
UDT_API(s32) udtGetStringArray(udtStringArray::Id arrayId, const char*** elements, u32* elementCount)
{
	if(elements == NULL || elementCount == NULL)
	{
		return (s32)udtErrorCode::InvalidArgument;
	}

	switch(arrayId)
	{
		case udtStringArray::Weapons:
			*elements = WeaponNames;
			*elementCount = (u32)(UDT_COUNT_OF(WeaponNames) - 1);
			break;

		case udtStringArray::PowerUps:
			*elements = PowerUpNames;
			*elementCount = (u32)(UDT_COUNT_OF(PowerUpNames) - 1);
			break;

		case udtStringArray::MeansOfDeath:
			*elements = MeansOfDeathNames;
			*elementCount = (u32)(UDT_COUNT_OF(MeansOfDeathNames) - 1);
			break;

		case udtStringArray::PlayerMeansOfDeath:
			*elements = PlayerMeansOfDeathNames;
			*elementCount = (u32)(UDT_COUNT_OF(PlayerMeansOfDeathNames) - 1);
			break;

		case udtStringArray::Teams:
			*elements = TeamNames;
			*elementCount = (u32)(UDT_COUNT_OF(TeamNames) - 1);
			break;

		case udtStringArray::CutPatterns:
			*elements = CutPatternNames;
			*elementCount = (u32)(UDT_COUNT_OF(CutPatternNames) - 1);
			break;

		default:
			return (s32)udtErrorCode::InvalidArgument;
	}

	return (s32)udtErrorCode::None;
}
Beispiel #9
0
void udtBaseParser::WriteGameState()
{
	_outMsg.Init(_outMsgData, sizeof(_outMsgData));
	_outMsg.Bitstream();

	_outMsg.WriteLong(_inReliableSequenceAcknowledge);

	_outMsg.WriteByte(svc_gamestate);
	_outMsg.WriteLong(_outServerCommandSequence);
	++_outServerCommandSequence;

	_protocolConverter->StartGameState();
	
	// Config strings.
	for(u32 i = 0; i < (u32)UDT_COUNT_OF(_inConfigStrings); ++i)
	{
		const udtString& cs = _inConfigStrings[i];
		if(_outProtocol == _inProtocol && !udtString::IsNullOrEmpty(cs))
		{
			_outMsg.WriteByte(svc_configstring);
			_outMsg.WriteShort((s32)i);
			_outMsg.WriteBigString(cs.GetPtr(), cs.GetLength());
			continue;
		}

		udtVMScopedStackAllocator allocatorScope(_tempAllocator);
		
		udtConfigStringConversion outCs;
		_protocolConverter->ConvertConfigString(outCs, _tempAllocator, (s32)i, cs.GetPtr(), cs.GetLength());
		if(outCs.Index >= 0 && outCs.String.GetLength() > 0)
		{
			_outMsg.WriteByte(svc_configstring);
			_outMsg.WriteShort(outCs.Index);
			_outMsg.WriteBigString(outCs.String.GetPtr(), outCs.String.GetLength());
		}
	}

	idLargestEntityState nullState;
	Com_Memset(&nullState, 0, sizeof(nullState));
	
	// Baseline entities.
	for(s32 i = 0; i < ID_MAX_PARSE_ENTITIES; ++i)
	{
		// We delta from the null state because we write a full entity.
		const idEntityStateBase* const newState = GetBaseline(i);

		// Write the baseline entity if it's not filled with 0 integers.
		if(memcmp(&nullState, newState, _inProtocolSizeOfEntityState))
		{
			_outMsg.WriteByte(svc_baseline);

			// @NOTE: MSG_WriteBits is called in there with newState.number as an argument.
			idLargestEntityState newStateOutProto;
			_protocolConverter->ConvertEntityState(newStateOutProto, *newState);
			_outMsg.WriteDeltaEntity(&nullState, &newStateOutProto, true);
		}
	}
	
	_outMsg.WriteByte(svc_EOF);

	_outMsg.WriteLong(_inClientNum);
	_outMsg.WriteLong(_inChecksumFeed);

	_outMsg.WriteByte(svc_EOF);
}
Beispiel #10
0
bool udtBaseParser::ParseCommandString()
{
	s32 commandStringLength = 0;
	const s32 commandSequence = _inMsg.ReadLong();
	const char* const commandStringTemp = _inMsg.ReadString(commandStringLength);

	// Do we have it already?
	if(_inServerCommandSequence >= commandSequence) 
	{
		// Yes, don't bother processing it.
		return true;
	}
	
	// Copy the string to some temporary location.
	udtVMScopedStackAllocator scopedTempAllocator(_tempAllocator);
	udtString commandString = udtString::NewClone(_tempAllocator, commandStringTemp, (u32)commandStringLength);
	
	// We haven't, so let's store the last sequence number received.
	_inServerCommandSequence = commandSequence;

	bool plugInSkipsThisCommand = false;

tokenize:
	idTokenizer& tokenizer = _tokenizer;
	tokenizer.Tokenize(commandString.GetPtr());
	const int tokenCount = tokenizer.GetArgCount();
	const udtString commandName = (tokenCount > 0) ? tokenizer.GetArg(0) : udtString::NewEmptyConstant();
	s32 csIndex = -1;
	bool isConfigString = false;
	if(tokenCount == 3 && udtString::Equals(commandName, "cs"))
	{
		if(StringParseInt(csIndex, tokenizer.GetArgString(1)) && csIndex >= 0 && csIndex < (s32)UDT_COUNT_OF(_inConfigStrings))
		{
			isConfigString = true;

			const char* const csStringTemp = tokenizer.GetArgString(2);
			u32 csStringLength = (u32)strlen(csStringTemp);

			udtConfigStringConversion outCs;
			_protocolConverter->ConvertConfigString(outCs, _tempAllocator, csIndex, csStringTemp, csStringLength);
			if(outCs.NewString || outCs.Index != csIndex)
			{
				commandString = udtString::NewEmpty(_privateTempAllocator, 2 * BIG_INFO_STRING);
				sprintf(commandString.GetWritePtr(), "cs %d \"%s\"", outCs.Index, outCs.String.GetPtr());
				commandStringLength = (s32)strlen(commandString.GetPtr());
				csStringLength = outCs.String.GetLength();
			}

			// Copy the config string to some safe location.
			_inConfigStrings[csIndex] = udtString::NewClone(_configStringAllocator, csStringTemp, csStringLength);
		}
	}
	else if(tokenCount == 3 && udtString::Equals(commandName, "bcs0"))
	{
		// Start a new big config string.
		sprintf(_inBigConfigString, "cs %s \"%s", tokenizer.GetArgString(1), tokenizer.GetArgString(2));
		plugInSkipsThisCommand = true;
	}
	else if(tokenCount == 3 && udtString::Equals(commandName, "bcs1"))
	{
		// Append to current big config string.
		strcat(_inBigConfigString, tokenizer.GetArgString(2));
		plugInSkipsThisCommand = true;
	}
	else if(tokenCount == 3 && udtString::Equals(commandName, "bcs2"))
	{
		// Append to current big config string and finalize it.
		strcat(_inBigConfigString, tokenizer.GetArgString(2));
		strcat(_inBigConfigString, "\"");
		commandString = udtString::NewConstRef(_inBigConfigString);
		commandStringLength = (s32)strlen(_inBigConfigString);
		goto tokenize;
	}

	if(EnablePlugIns && !PlugIns.IsEmpty() && !plugInSkipsThisCommand)
	{
		udtCommandCallbackArg info;
		info.CommandSequence = commandSequence;
		info.String = commandString.GetPtr();
		info.StringLength = commandStringLength;
		info.ConfigStringIndex = csIndex;
		info.IsConfigString = isConfigString;
		info.IsEmptyConfigString = isConfigString ? udtString::IsNullOrEmpty(tokenizer.GetArg(2)) : false;

		for(u32 i = 0, count = PlugIns.GetSize(); i < count; ++i)
		{
			PlugIns[i]->ProcessCommandMessage(info, *this);
		}
	}

	if(ShouldWriteMessage())
	{
		if(csIndex >= 0 && commandStringLength >= MAX_STRING_CHARS)
		{
			WriteBigConfigStringCommand(tokenizer.GetArg(1), tokenizer.GetArg(2));
		}
		else if(commandStringLength < MAX_STRING_CHARS)
		{
			_outMsg.WriteByte(svc_serverCommand);
			_outMsg.WriteLong(_outServerCommandSequence);
			_outMsg.WriteString(commandString.GetPtr(), commandStringLength);
			++_outServerCommandSequence;
		}
		else
		{
			_outMsg.WriteByte(svc_nop);
		}
	}
	
	_privateTempAllocator.Clear();

	return true;
}