예제 #1
0
void EncodeClassName( char *name, char *identifier )
{
    RakNet::BitStream bitStream;
    int index = 0;
    unsigned char byte;

    while ( index < MAXIMUM_CLASS_IDENTIFIER_LENGTH - 1 )
    {
        if ( name[ index ] == 0 )
            break;

        // This should generate a unique identifier for any realistic class name that is 5/8th the length of the actual name and weakly encrypts and compresses it
        if ( name[ index ] >= 'a' && name[ index ] <= 'z' )
            byte = name[ index ] - 'a';
        else if ( name[ index ] >= 'A' && name[ index ] <= 'Z' )
            byte = name[ index ] - 'A';
        else if ( name[ index ] >= '0' && name[ index ] <= '9' )
            byte = name[ index ] - '0';
        else
            byte = name[ index ] << 3;

        bitStream.WriteBits( ( unsigned char* ) & byte, 5 );

        index++;
    }

#ifdef _DEBUG
    memset( identifier, 0, MAXIMUM_CLASS_IDENTIFIER_LENGTH );

#endif

    identifier[ 0 ] = ( char ) ( bitStream.GetNumberOfBytesUsed() );

    memcpy( identifier + 1, bitStream.GetData(), bitStream.GetNumberOfBytesUsed() );
}
예제 #2
0
		void Server::UpdatePingResponse()
		{
			ECS::Entity* serverInfoEntity = m_world->GetTagManager()->GetEntityByTag("ServerInformation");
			Network::ServerInformationComponent* serverInfo = m_world->GetEntityManager()->GetComponent<Network::ServerInformationComponent>(serverInfoEntity);

			RakNet::BitStream bs;
			serverInfo->Information.Serialize(true, &bs);

			const unsigned char* data = bs.GetData();
			unsigned int size = bs.GetNumberOfBytesUsed();

			m_peer->SetOfflinePingResponse((const char*)bs.GetData(), bs.GetNumberOfBytesUsed());
		}
void TwoWayAuthentication::PushToUser(MessageID messageId, RakNet::RakString password, RakNet::AddressOrGUID remoteSystem)
{
	RakNet::BitStream output;
	output.Write(messageId);
	if (password.IsEmpty()==false)
		output.Write(password);
	Packet *p = AllocatePacketUnified(output.GetNumberOfBytesUsed());
	p->systemAddress=remoteSystem.systemAddress;
	p->systemAddress.systemIndex=(SystemIndex)-1;
	p->guid=remoteSystem.rakNetGuid;
	p->wasGeneratedLocally=true;
	memcpy(p->data, output.GetData(), output.GetNumberOfBytesUsed());
	rakPeerInterface->PushBackPacket(p, true);
}
예제 #4
0
void UploadInstanceToCloud(RakNet::CloudClient *cloudClient, RakNet::RakNetGUID serverGuid)
{
    RakNet::CloudKey cloudKey(CLOUD_CLIENT_PRIMARY_KEY,0);
    RakNet::BitStream bs;
    bs.Write("Hello World"); // This could be anything such as player list, game name, etc.
    cloudClient->Post(&cloudKey, bs.GetData(), bs.GetNumberOfBytesUsed(), serverGuid);
}
예제 #5
0
void Network::send_input(){
    if(status=="client"){
        if(game.in_progress){
            if(commands_this_second<rate_commands && ++counter_commands>=(uint32_t)ceil(UPDATE_RATE/(double)rate_commands)){
                counter_commands=0;

                commands_this_second++;

                RakNet::BitStream bitstream;
                bitstream.Write((RakNet::MessageID)ID_GAME_INPUT);

                bitstream.WriteCompressed((int)command_buffer.size());
                for(int i=0;i<command_buffer.size();i++){
                    bitstream.WriteCompressed((RakNet::RakString)command_buffer[i].c_str());
                }
                command_buffer.clear();

                bitstream.WriteCompressed((int)game.command_states.size());
                for(int i=0;i<game.command_states.size();i++){
                    bitstream.WriteCompressed((RakNet::RakString)game.command_states[i].c_str());
                }

                stat_counter_bytes_sent+=bitstream.GetNumberOfBytesUsed();
                peer->Send(&bitstream,HIGH_PRIORITY,RELIABLE_ORDERED,ORDERING_CHANNEL_INPUT,server_id,false);
            }
        }
    }
}
예제 #6
0
void NatTypeDetectionClient::OnTestPortRestricted(Packet *packet)
{
	RakNet::BitStream bsIn(packet->data,packet->length,false);
	bsIn.IgnoreBytes(sizeof(MessageID));
	RakNet::RakString s3p4StrAddress;
	bsIn.Read(s3p4StrAddress);
	unsigned short s3p4Port;
	bsIn.Read(s3p4Port);

	DataStructures::List<RakNetSocket2* > sockets;
	rakPeerInterface->GetSockets(sockets);
	SystemAddress s3p4Addr = sockets[0]->GetBoundAddress();
	s3p4Addr.FromStringExplicitPort(s3p4StrAddress.C_String(), s3p4Port);

	// Send off the RakNet socket to the specified address, message is unformatted
	// Server does this twice, so don't have to unduly worry about packetloss
	RakNet::BitStream bsOut;
	bsOut.Write((MessageID) NAT_TYPE_PORT_RESTRICTED);
	bsOut.Write(rakPeerInterface->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS));
//	SocketLayer::SendTo_PC( sockets[0], (const char*) bsOut.GetData(), bsOut.GetNumberOfBytesUsed(), s3p4Addr, __FILE__, __LINE__ );

	RNS2_SendParameters bsp;
	bsp.data = (char*) bsOut.GetData();
	bsp.length = bsOut.GetNumberOfBytesUsed();
	bsp.systemAddress=s3p4Addr;
	sockets[0]->Send(&bsp, _FILE_AND_LINE_);

}
예제 #7
0
파일: Router2.cpp 프로젝트: BillXu/Project
void Router2::SendOOBFromSpecifiedSocket(OutOfBandIdentifiers oob, SystemAddress sa, SOCKET socket)
{
	RakNet::BitStream bs;
	rakPeerInterface->WriteOutOfBandHeader(&bs);
	bs.Write((unsigned char) oob);
	SocketLayer::SendTo_PC( socket, (const char*) bs.GetData(), bs.GetNumberOfBytesUsed(), sa, __FILE__, __LINE__  );
}
예제 #8
0
SQLite3ServerPlugin::SQLExecThreadOutput ExecStatementThread(SQLite3ServerPlugin::SQLExecThreadInput threadInput, bool *returnOutput, void* perThreadData)
{
	unsigned int queryId;
	RakNet::RakString dbIdentifier;
	RakNet::RakString inputStatement;
	RakNet::BitStream bsIn((unsigned char*) threadInput.data, threadInput.length, false);
	bsIn.IgnoreBytes(sizeof(MessageID));
	bsIn.Read(queryId);
	bsIn.Read(dbIdentifier);
	bsIn.Read(inputStatement);
	// bool isRequest;
	// bsIn.Read(isRequest);
	bsIn.IgnoreBits(1);

	char *errorMsg;
	RakNet::RakString errorMsgStr;
	SQLite3Table outputTable;					
	sqlite3_exec(threadInput.dbHandle, inputStatement.C_String(), PerRowCallback, &outputTable, &errorMsg);
	if (errorMsg)
	{
		errorMsgStr=errorMsg;
		sqlite3_free(errorMsg);
	}

	RakNet::BitStream bsOut;
	bsOut.Write((MessageID)ID_SQLite3_EXEC);
	bsOut.Write(queryId);
	bsOut.Write(dbIdentifier);
	bsOut.Write(inputStatement);
	bsOut.Write(false);
	bsOut.Write(errorMsgStr);
	outputTable.Serialize(&bsOut);

	// Free input data
	rakFree_Ex(threadInput.data,__FILE__,__LINE__);

	// Copy to output data
	SQLite3ServerPlugin::SQLExecThreadOutput threadOutput;
	threadOutput.data=(char*) rakMalloc_Ex(bsOut.GetNumberOfBytesUsed(),__FILE__,__LINE__);
	memcpy(threadOutput.data,bsOut.GetData(),bsOut.GetNumberOfBytesUsed());
	threadOutput.length=bsOut.GetNumberOfBytesUsed();
	threadOutput.sender=threadInput.sender;	
	// SendUnified(&bsOut, MEDIUM_PRIORITY,RELIABLE_ORDERED,0,packet->systemAddress,false);

	*returnOutput=true;
	return threadOutput;
}
예제 #9
0
void ServerInfo::writeToBitstream(RakNet::BitStream& stream)
{
	stream.Write(activegames);
	stream.Write(name, sizeof(name));
	stream.Write(waitingplayers);
	stream.Write(description, sizeof(description));
	assert( stream.GetNumberOfBytesUsed() == BLOBBY_SERVER_PRESENT_PACKET_SIZE);
}
예제 #10
0
void FileListTransfer::PushReference(SystemAddress systemAddress)
{
	// Was previously using GetStatistics to get outgoing buffer size, but TCP with UnifiedSend doesn't have this
	unsigned int i=0;
	unsigned int bytesRead;	
	char *dataBlocks[2];
	int lengths[2];
	RakNet::BitStream outBitstream;
	while (i < filesToPush.Size())
	{
		if (filesToPush[i].systemAddress==systemAddress)
		{
			outBitstream.Reset();
			outBitstream.Write((MessageID)ID_FILE_LIST_REFERENCE_PUSH);
			outBitstream.Write(filesToPush[i].fileListNode.context);
			outBitstream.Write(filesToPush[i].setID);
			stringCompressor->EncodeString(filesToPush[i].fileListNode.filename, 512, &outBitstream);
			outBitstream.WriteCompressed(filesToPush[i].setIndex);
			outBitstream.WriteCompressed(filesToPush[i].fileListNode.dataLengthBytes); // Original length in bytes

			// Read and send chunk. If done, delete at this index
			void *buff = rakMalloc_Ex(filesToPush[i].chunkSize, __FILE__, __LINE__);
			if (buff==0)
			{
				notifyOutOfMemory(__FILE__, __LINE__);
				continue;
			}
			bytesRead=filesToPush[i].incrementalReadInterface->GetFilePart(filesToPush[i].fileListNode.fullPathToFile, filesToPush[i].currentOffset, filesToPush[i].chunkSize, buff, filesToPush[i].fileListNode.context);
			outBitstream.WriteCompressed(filesToPush[i].currentOffset);
			filesToPush[i].currentOffset+=bytesRead;
			outBitstream.WriteCompressed(bytesRead);
			bool done = bytesRead!=filesToPush[i].chunkSize;
			outBitstream.Write(done);

			if (callback)
			{
				callback->OnFilePush(filesToPush[i].fileListNode.filename, filesToPush[i].fileListNode.fileLengthBytes, filesToPush[i].currentOffset-bytesRead, bytesRead, done, filesToPush[i].systemAddress);
			}

			dataBlocks[0]=(char*) outBitstream.GetData();
			lengths[0]=outBitstream.GetNumberOfBytesUsed();
			dataBlocks[1]=(char*) buff;
			lengths[1]=bytesRead;
			//rakPeerInterface->SendList(dataBlocks,lengths,2,filesToPush[i].packetPriority, RELIABLE_ORDERED, filesToPush[i].orderingChannel, filesToPush[i].systemAddress, false);
			SendListUnified(dataBlocks,lengths,2,filesToPush[i].packetPriority, RELIABLE_ORDERED, filesToPush[i].orderingChannel, filesToPush[i].systemAddress, false);
			if (done)
			{
				// Done
				RakNet::OP_DELETE_ARRAY(filesToPush[i].fileListNode.filename, __FILE__, __LINE__);
				filesToPush.RemoveAtIndex(i);
			}
			rakFree_Ex(buff, __FILE__, __LINE__ );
			return;
		}			
		else
			i++;
	}	
}
예제 #11
0
void Network::send_connected(){
    if(status=="client"){
        RakNet::BitStream bitstream;
        bitstream.Write((RakNet::MessageID)ID_GAME_CONNECTED);

        stat_counter_bytes_sent+=bitstream.GetNumberOfBytesUsed();
        peer->Send(&bitstream,MEDIUM_PRIORITY,RELIABLE_ORDERED,ORDERING_CHANNEL_CONNECTION,server_id,false);
    }
}
예제 #12
0
void NetworkEngine::updatePingResponse()
{
	RakNet::BitStream data;

	if(isLobby())
	{
		data.Write1();
		unsigned char numPlayers = (unsigned char) peer->NumberOfConnections();
		data.Write(numPlayers);
		std::cout << "Total players: " << (unsigned int) numPlayers << std::endl;
		peer->SetOfflinePingResponse((char *)data.GetData(), data.GetNumberOfBytesUsed());
	} else
	{
		data.Write0();
	}

	peer->SetOfflinePingResponse((char *)data.GetData(), data.GetNumberOfBytesUsed());
}
void CloudServerHelper::OnConnectionCountChange(RakPeerInterface *rakPeer, CloudClient *cloudClient)
{
	RakNet::BitStream bs;
	CloudKey cloudKey(CLOUD_SERVER_CONNECTION_COUNT_PRIMARY_KEY,0);
	unsigned short numberOfSystems;
	rakPeer->GetConnectionList(0, &numberOfSystems);
	bs.Write(numberOfSystems);
	cloudClient->Post(&cloudKey, bs.GetData(), bs.GetNumberOfBytesUsed(), rakPeer->GetMyGUID());
}
SQLLogResult SQLiteClientLoggerPlugin::SqlLog( bool isFunctionCall, const char *tableName, const char *columnNames, const char *file, const int line, const ParameterListHelper &parameterList )
{
	if (recursiveCheck==true)
		return SQLLR_RECURSION;
	recursiveCheck=true;

	RakNet::BitStream bitStream;
	SerializeHeader(&bitStream, isFunctionCall, tableName, columnNames, file, line, parameterList.paramCount);
//	int i;
	//for (i=0; i < parameterList.paramCount; i++)
	//	parameterList.parms[i].Serialize(&bitStream);
	if (parameterList.paramCount>=1)
		parameterList.p0.Serialize(&bitStream);
	if (parameterList.paramCount>=2)
		parameterList.p1.Serialize(&bitStream);
	if (parameterList.paramCount>=3)
		parameterList.p2.Serialize(&bitStream);
	if (parameterList.paramCount>=4)
		parameterList.p3.Serialize(&bitStream);
	if (parameterList.paramCount>=5)
		parameterList.p4.Serialize(&bitStream);
	if (parameterList.paramCount>=6)
		parameterList.p5.Serialize(&bitStream);
	if (parameterList.paramCount>=7)
		parameterList.p6.Serialize(&bitStream);
	if (parameterList.paramCount>=8)
		parameterList.p7.Serialize(&bitStream);
	if (parameterList.paramCount>=9)
		parameterList.p8.Serialize(&bitStream);
	if (parameterList.paramCount>=10)
		parameterList.p9.Serialize(&bitStream);
	if (parameterList.paramCount>=11)
		parameterList.p10.Serialize(&bitStream);
	if (parameterList.paramCount>=12)
		parameterList.p11.Serialize(&bitStream);
	if (parameterList.paramCount>=13)
		parameterList.p12.Serialize(&bitStream);
	if (parameterList.paramCount>=14)
		parameterList.p13.Serialize(&bitStream);
	if (parameterList.paramCount>=15)
		parameterList.p14.Serialize(&bitStream);


	if (memoryConstraint!=0 && tcpInterface)
	{
		if (tcpInterface->GetOutgoingDataBufferSize(serverAddress)+bitStream.GetNumberOfBytesUsed()>=memoryConstraint)
		{
			recursiveCheck=false;
			return SQLLR_WOULD_EXCEED_MEMORY_CONSTRAINT;
		}
	}

	SendUnified(&bitStream, LOW_PRIORITY, RELIABLE_ORDERED, 1, serverAddress, false);
	recursiveCheck=false;
	return SQLLR_OK;
}
예제 #15
0
bool SystemAddressList::Save(const char *filename)
{
	RakNet::BitStream temp;
	Serialize(&temp);
	FILE *fp = fopen(filename, "wb");
	if (fp)
	{
		fwrite(temp.GetData(), (size_t) temp.GetNumberOfBytesUsed(), 1, fp);
		fclose(fp);
		return true;
	}
	return false;
}
예제 #16
0
void Network::send_client_data(bool first_send){
    if(status=="client"){
        char ordering_channel=ORDERING_CHANNEL_CLIENT_DATA;
        if(first_send){
            ordering_channel=ORDERING_CHANNEL_CONNECTION;
        }

        RakNet::BitStream bitstream;
        bitstream.Write((RakNet::MessageID)ID_GAME_CLIENT_DATA);

        bitstream.WriteCompressed(first_send);
        bitstream.WriteCompressed((RakNet::RakString)game.option_name.c_str());
        bitstream.WriteCompressed(rate_bytes);
        bitstream.WriteCompressed(rate_updates);

        stat_counter_bytes_sent+=bitstream.GetNumberOfBytesUsed();
        peer->Send(&bitstream,MEDIUM_PRIORITY,RELIABLE_ORDERED,ordering_channel,server_id,false);
    }
}
void NatTypeDetectionClient::OnTestPortRestricted(Packet *packet)
{
	RakNet::BitStream bsIn(packet->data,packet->length,false);
	bsIn.IgnoreBytes(sizeof(MessageID));
	RakNet::RakString s3p4StrAddress;
	bsIn.Read(s3p4StrAddress);
	unsigned short s3p4Port;
	bsIn.Read(s3p4Port);
	SystemAddress s3p4Addr(s3p4StrAddress.C_String(), s3p4Port);

	DataStructures::List<RakNetSmartPtr<RakNetSocket> > sockets;
	rakPeerInterface->GetSockets(sockets);

	// Send off the RakNet socket to the specified address, message is unformatted
	// Server does this twice, so don't have to unduly worry about packetloss
	RakNet::BitStream bsOut;
	bsOut.Write((MessageID) NAT_TYPE_PORT_RESTRICTED);
	bsOut.Write(rakPeerInterface->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS));
	SocketLayer::Instance()->SendTo_PC( sockets[0]->s, (const char*) bsOut.GetData(), bsOut.GetNumberOfBytesUsed(), s3p4Addr.binaryAddress, s3p4Addr.port);
}
예제 #18
0
void RakVoice::SetLoopbackMode(bool enabled)
{
	if (enabled)
	{
		Packet p;
		RakNet::BitStream out;
		out.Write((unsigned char)ID_RAKVOICE_OPEN_CHANNEL_REQUEST);
		out.Write((int32_t)sampleRate);
		p.data=out.GetData();
		p.systemAddress=UNASSIGNED_SYSTEM_ADDRESS;
		p.guid=UNASSIGNED_RAKNET_GUID;
		p.length=out.GetNumberOfBytesUsed();
		OpenChannel(&p);
	}
	else
	{
		FreeChannelMemory(UNASSIGNED_RAKNET_GUID);
	}
	loopbackMode=enabled;
}
void NatPunchthroughClient::SendOutOfBand(SystemAddress sa, MessageID oobId)
{
	if (sa==UNASSIGNED_SYSTEM_ADDRESS)
		return;
	if (sa.GetPort()==0)
		return;

	RakNet::BitStream oob;
	oob.Write(oobId);
	oob.Write(sp.sessionId);
//	RakAssert(sp.sessionId<100);
	if (oobId==ID_NAT_ESTABLISH_BIDIRECTIONAL)
		oob.Write(sa.GetPort());
	char ipAddressString[32];
	sa.ToString(false, ipAddressString);
	rakPeerInterface->SendOutOfBand((const char*) ipAddressString,sa.GetPort(),(const char*) oob.GetData(),oob.GetNumberOfBytesUsed());

	if (natPunchthroughDebugInterface)
	{
		sa.ToString(true,ipAddressString);
		char guidString[128];
		sp.targetGuid.ToString(guidString);

		if (oobId==ID_NAT_ESTABLISH_UNIDIRECTIONAL)
			natPunchthroughDebugInterface->OnClientMessage(RakNet::RakString("Sent OOB ID_NAT_ESTABLISH_UNIDIRECTIONAL to guid %s, system address %s.", guidString, ipAddressString));
		else
			natPunchthroughDebugInterface->OnClientMessage(RakNet::RakString("Sent OOB ID_NAT_ESTABLISH_BIDIRECTIONAL to guid %s, system address %s.", guidString, ipAddressString));
	}
}
PluginReceiveResult NatPunchthroughClient::OnReceive(Packet *packet)
{
	switch (packet->data[0])
	{
	case ID_NAT_GET_MOST_RECENT_PORT:
		{
			OnGetMostRecentPort(packet);
			return RR_STOP_PROCESSING_AND_DEALLOCATE;
		}
	case ID_NAT_PUNCHTHROUGH_FAILED:
	case ID_NAT_PUNCHTHROUGH_SUCCEEDED:
		if (packet->wasGeneratedLocally==false)
			return RR_STOP_PROCESSING_AND_DEALLOCATE;
		break;
	case ID_NAT_RESPOND_BOUND_ADDRESSES:
		{
			RakNet::BitStream bs(packet->data,packet->length,false);
			bs.IgnoreBytes(sizeof(MessageID));
			unsigned char boundAddressCount;
			bs.Read(boundAddressCount);
			if (boundAddressCount<2)
			{
				if (natPunchthroughDebugInterface)
					natPunchthroughDebugInterface->OnClientMessage("INCAPABLE_PORT_STRIDE");

				hasPortStride=INCAPABLE_PORT_STRIDE;
				SendQueuedOpenNAT();
			}
			SystemAddress boundAddresses[MAXIMUM_NUMBER_OF_INTERNAL_IDS];
			for (int i=0; i < boundAddressCount && i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
			{
				bs.Read(boundAddresses[i]);
				if (boundAddresses[i]!=packet->systemAddress)
				{
					RakNet::BitStream outgoingBs;
					outgoingBs.Write((MessageID)ID_NAT_PING);
					uint16_t externalPort = rakPeerInterface->GetExternalID(packet->systemAddress).GetPort();
					outgoingBs.Write( externalPort );
					rakPeerInterface->SendOutOfBand((const char*) boundAddresses[i].ToString(false),boundAddresses[i].GetPort(),(const char*) outgoingBs.GetData(),outgoingBs.GetNumberOfBytesUsed());
					break;
				}
			}
		}
		break;		
	case ID_OUT_OF_BAND_INTERNAL:
		if (packet->length>=2 && packet->data[1]==ID_NAT_PONG)
		{
			RakNet::BitStream bs(packet->data,packet->length,false);
			bs.IgnoreBytes(sizeof(MessageID)*2);
			uint16_t externalPort;
			bs.Read(externalPort);
			uint16_t externalPort2;
			bs.Read(externalPort2);
			portStride = externalPort2 - externalPort;
			hasPortStride=HAS_PORT_STRIDE;

			if (natPunchthroughDebugInterface)
				natPunchthroughDebugInterface->OnClientMessage(RakString("HAS_PORT_STRIDE %i. Server first external port %i. Server second external port %i.", portStride, externalPort, externalPort2));

			SendQueuedOpenNAT();
			return RR_STOP_PROCESSING_AND_DEALLOCATE;
		}
		else if (packet->length>=2 &&
			(packet->data[1]==ID_NAT_ESTABLISH_UNIDIRECTIONAL || packet->data[1]==ID_NAT_ESTABLISH_BIDIRECTIONAL) &&
			sp.nextActionTime!=0)
		{
			RakNet::BitStream bs(packet->data,packet->length,false);
			bs.IgnoreBytes(2);
			uint16_t sessionId;
			bs.Read(sessionId);
//			RakAssert(sessionId<100);
			if (sessionId!=sp.sessionId)
				break;

			char ipAddressString[32];
			packet->systemAddress.ToString(true,ipAddressString);
			// sp.targetGuid==packet->guid is because the internal IP addresses reported may include loopbacks not reported by RakPeer::IsLocalIP()
			if (packet->data[1]==ID_NAT_ESTABLISH_UNIDIRECTIONAL && sp.targetGuid==packet->guid)
			{
				if (natPunchthroughDebugInterface)
				{
					char guidString[128];
					sp.targetGuid.ToString(guidString);
					natPunchthroughDebugInterface->OnClientMessage(RakNet::RakString("Received ID_NAT_ESTABLISH_UNIDIRECTIONAL from guid %s, system address %s.", guidString, ipAddressString));
				}
				if (sp.testMode!=SendPing::PUNCHING_FIXED_PORT)
				{
					sp.testMode=SendPing::PUNCHING_FIXED_PORT;
					sp.retryCount+=sp.attemptCount*pc.UDP_SENDS_PER_PORT_EXTERNAL;
					sp.targetAddress=packet->systemAddress;
					// Keeps trying until the other side gives up too, in case it is unidirectional
					sp.punchingFixedPortAttempts=pc.UDP_SENDS_PER_PORT_EXTERNAL*(pc.MAX_PREDICTIVE_PORT_RANGE+1);
				}

				SendOutOfBand(sp.targetAddress,ID_NAT_ESTABLISH_BIDIRECTIONAL);
			}
			else if (packet->data[1]==ID_NAT_ESTABLISH_BIDIRECTIONAL &&
				sp.targetGuid==packet->guid)
			{
				// They send back our port
				unsigned short ourExternalPort;
				bs.Read(ourExternalPort);
				if (nextExternalPort==0)
				{
					nextExternalPort=ourExternalPort;
				}
				else
				{
					if (sp.testMode!=SendPing::TESTING_INTERNAL_IPS && sp.testMode!=SendPing::WAITING_FOR_INTERNAL_IPS_RESPONSE)
					{
						if (hasPortStride!=HAS_PORT_STRIDE)
						{
							portStride = ourExternalPort - nextExternalPort;
							hasPortStride=HAS_PORT_STRIDE;

							if (natPunchthroughDebugInterface)
							{
								natPunchthroughDebugInterface->OnClientMessage(RakString("Estimated port stride from incoming connection at %i", portStride));
							}

							SendQueuedOpenNAT();
						}

						nextExternalPort += portStride * (pc.MAX_PREDICTIVE_PORT_RANGE+1);

						if (natPunchthroughDebugInterface)
						{
							natPunchthroughDebugInterface->OnClientMessage(RakString("Estimated next external port %i", nextExternalPort));
						}
					}
				}
				SendOutOfBand(packet->systemAddress,ID_NAT_ESTABLISH_BIDIRECTIONAL);

				// Tell the user about the success
				sp.targetAddress=packet->systemAddress;
				PushSuccess();
				//UpdateGroupPunchOnNatResult(sp.facilitator, sp.targetGuid, sp.targetAddress, 1);
				OnReadyForNextPunchthrough();
				bool removedFromFailureQueue=RemoveFromFailureQueue();

				if (natPunchthroughDebugInterface)
				{
					char guidString[128];
					sp.targetGuid.ToString(guidString);
					if (removedFromFailureQueue)
						natPunchthroughDebugInterface->OnClientMessage(RakNet::RakString("Punchthrough to guid %s, system address %s succeeded on 2nd attempt.", guidString, ipAddressString));
					else
						natPunchthroughDebugInterface->OnClientMessage(RakNet::RakString("Punchthrough to guid %s, system address %s succeeded on 1st attempt.", guidString, ipAddressString));
				}
			}

	//		mostRecentNewExternalPort=packet->systemAddress.GetPort();
		}
		return RR_STOP_PROCESSING_AND_DEALLOCATE;
	case ID_NAT_ALREADY_IN_PROGRESS:
		{
			RakNet::BitStream incomingBs(packet->data, packet->length, false);
			incomingBs.IgnoreBytes(sizeof(MessageID));
			RakNetGUID targetGuid;
			incomingBs.Read(targetGuid);
			// Don't update group, just use later message
			// UpdateGroupPunchOnNatResult(packet->systemAddress, targetGuid, UNASSIGNED_SYSTEM_ADDRESS, 2);
			if (natPunchthroughDebugInterface)
			{
				char guidString[128];
				targetGuid.ToString(guidString);
				natPunchthroughDebugInterface->OnClientMessage(RakNet::RakString("Punchthrough retry to guid %s failed due to ID_NAT_ALREADY_IN_PROGRESS. Returning failure.", guidString));
			}

		}
		break;
	case ID_NAT_TARGET_NOT_CONNECTED:
	case ID_NAT_CONNECTION_TO_TARGET_LOST:
	case ID_NAT_TARGET_UNRESPONSIVE:
		{
			const char *reason;
			if (packet->data[0]==ID_NAT_TARGET_NOT_CONNECTED)
				reason=(char *)"ID_NAT_TARGET_NOT_CONNECTED";
			else if (packet->data[0]==ID_NAT_CONNECTION_TO_TARGET_LOST)
				reason=(char *)"ID_NAT_CONNECTION_TO_TARGET_LOST";
			else
				reason=(char *)"ID_NAT_TARGET_UNRESPONSIVE";


			RakNet::BitStream incomingBs(packet->data, packet->length, false);
			incomingBs.IgnoreBytes(sizeof(MessageID));

			RakNetGUID targetGuid;
			incomingBs.Read(targetGuid);
			//UpdateGroupPunchOnNatResult(packet->systemAddress, targetGuid, UNASSIGNED_SYSTEM_ADDRESS, 2);

			if (packet->data[0]==ID_NAT_CONNECTION_TO_TARGET_LOST ||
				packet->data[0]==ID_NAT_TARGET_UNRESPONSIVE)
			{
				uint16_t sessionId;
				incomingBs.Read(sessionId);
				if (sessionId!=sp.sessionId)
					break;
			}

			unsigned int i;
			for (i=0; i < failedAttemptList.Size(); i++)
			{
				if (failedAttemptList[i].guid==targetGuid)
				{
					if (natPunchthroughDebugInterface)
					{
						char guidString[128];
						targetGuid.ToString(guidString);
						natPunchthroughDebugInterface->OnClientMessage(RakNet::RakString("Punchthrough retry to guid %s failed due to %s.", guidString, reason));

					}

					// If the retry target is not connected, or loses connection, or is not responsive, then previous failures cannot be retried.

					// Don't need to return failed, the other messages indicate failure anyway
					/*
					Packet *p = AllocatePacketUnified(sizeof(MessageID));
					p->data[0]=ID_NAT_PUNCHTHROUGH_FAILED;
					p->systemAddress=failedAttemptList[i].addr;
					p->systemAddress.systemIndex=(SystemIndex)-1;
					p->guid=failedAttemptList[i].guid;
					rakPeerInterface->PushBackPacket(p, false);
					*/

					failedAttemptList.RemoveAtIndexFast(i);
					break;
				}
			}

			if (natPunchthroughDebugInterface)
			{
				char guidString[128];
				targetGuid.ToString(guidString);
				natPunchthroughDebugInterface->OnClientMessage(RakNet::RakString("Punchthrough attempt to guid %s failed due to %s.", guidString, reason));
			}

			// Stop trying punchthrough
			sp.nextActionTime=0;

			/*
			RakNet::BitStream bs(packet->data, packet->length, false);
			bs.IgnoreBytes(sizeof(MessageID));
			RakNetGUID failedSystem;
			bs.Read(failedSystem);
			bool deletedFirst=false;
			unsigned int i=0;
			while (i < pendingOpenNAT.Size())
			{
				if (pendingOpenNAT[i].destination==failedSystem)
				{
					if (i==0)
						deletedFirst=true;
					pendingOpenNAT.RemoveAtIndex(i);
				}
				else
					i++;
			}
			// Failed while in progress. Go to next in attempt queue
			if (deletedFirst && pendingOpenNAT.Size())
			{
				SendPunchthrough(pendingOpenNAT[0].destination, pendingOpenNAT[0].facilitator);
				sp.nextActionTime=0;
			}
			*/
		}
		break;
	case ID_TIMESTAMP:
		if (packet->data[sizeof(MessageID)+sizeof(RakNet::Time)]==ID_NAT_CONNECT_AT_TIME)
		{
			OnConnectAtTime(packet);
			return RR_STOP_PROCESSING_AND_DEALLOCATE;
		}
		break;
	}
	return RR_CONTINUE_PROCESSING;
}
PluginReceiveResult NatPunchthroughServer::OnReceive(Packet *packet)
{
	switch (packet->data[0])
	{
	case ID_NAT_PUNCHTHROUGH_REQUEST:
		OnNATPunchthroughRequest(packet);
		return RR_STOP_PROCESSING_AND_DEALLOCATE;
	case ID_NAT_GET_MOST_RECENT_PORT:
		OnGetMostRecentPort(packet);
		return RR_STOP_PROCESSING_AND_DEALLOCATE;
	case ID_NAT_CLIENT_READY:
		OnClientReady(packet);
		return RR_STOP_PROCESSING_AND_DEALLOCATE;
	case ID_NAT_REQUEST_BOUND_ADDRESSES:
		{
			RakNet::BitStream outgoingBs;
			outgoingBs.Write((MessageID)ID_NAT_RESPOND_BOUND_ADDRESSES);
			
			if (boundAddresses[0]==UNASSIGNED_SYSTEM_ADDRESS)
			{
				DataStructures::List<RakNetSocket2* > sockets;
				rakPeerInterface->GetSockets(sockets);
				for (int i=0; i < sockets.Size() && i < MAXIMUM_NUMBER_OF_INTERNAL_IDS; i++)
				{
					boundAddresses[i]=sockets[i]->GetBoundAddress();
					boundAddressCount++;
				}
			}

			outgoingBs.Write(boundAddressCount);
			for (int i=0; i < boundAddressCount; i++)
			{
				outgoingBs.Write(boundAddresses[i]);
			}

			rakPeerInterface->Send(&outgoingBs,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->systemAddress,false);
		}
		return RR_STOP_PROCESSING_AND_DEALLOCATE;
	case ID_NAT_PING:
		{
		}
		return RR_STOP_PROCESSING_AND_DEALLOCATE;
	case ID_OUT_OF_BAND_INTERNAL:
		if (packet->length>=2 && packet->data[1]==ID_NAT_PING)
		{
			RakNet::BitStream bs(packet->data,packet->length,false);
			bs.IgnoreBytes(sizeof(MessageID)*2);
			uint16_t externalPort;
			bs.Read(externalPort);

			RakNet::BitStream outgoingBs;
			outgoingBs.Write((MessageID)ID_NAT_PONG);
			outgoingBs.Write(externalPort);
			uint16_t externalPort2 = packet->systemAddress.GetPort();
			outgoingBs.Write(externalPort2);
			rakPeerInterface->SendOutOfBand((const char*) packet->systemAddress.ToString(false),packet->systemAddress.GetPort(),(const char*) outgoingBs.GetData(),outgoingBs.GetNumberOfBytesUsed());

			return RR_STOP_PROCESSING_AND_DEALLOCATE;
		}
	}
	return RR_CONTINUE_PROCESSING;
}
void NatTypeDetectionServer::Update(void)
{
	int i=0;
	RakNet::TimeMS time = RakNet::GetTimeMS();
	RakNet::BitStream bs;
	SystemAddress boundAddress;

	// Only socket that receives messages is s3p4, to see if the external address is different than that of the connection to rakPeerInterface
	char data[ MAXIMUM_MTU_SIZE ];
	int len;
	SystemAddress senderAddr;
	len=NatTypeRecvFrom(data, s3p4, senderAddr);
	// Client is asking us if this is port restricted. Only client requests of this type come in on s3p4
	while (len>0 && data[0]==NAT_TYPE_PORT_RESTRICTED)
	{
		RakNet::BitStream bsIn((unsigned char*) data,len,false);
		RakNetGUID senderGuid;
		bsIn.IgnoreBytes(sizeof(MessageID));
		bool readSuccess = bsIn.Read(senderGuid);
		RakAssert(readSuccess);
		if (readSuccess)
		{
			unsigned int i = GetDetectionAttemptIndex(senderGuid);
			if (i!=(unsigned int)-1)
			{
				bs.Reset();
				bs.Write((unsigned char) ID_NAT_TYPE_DETECTION_RESULT);
				// If different, then symmetric
				if (senderAddr!=natDetectionAttempts[i].systemAddress)
				{
					printf("Determined client is symmetric\n");
					bs.Write((unsigned char) NAT_TYPE_SYMMETRIC);
				}
				else
				{
					// else port restricted
					printf("Determined client is port restricted\n");
					bs.Write((unsigned char) NAT_TYPE_PORT_RESTRICTED);
				}

				rakPeerInterface->Send(&bs,HIGH_PRIORITY,RELIABLE,0,natDetectionAttempts[i].systemAddress,false);

				// Done
				natDetectionAttempts.RemoveAtIndexFast(i);
			}
			else
			{
		//		RakAssert("i==0 in Update when looking up GUID in NatTypeDetectionServer.cpp. Either a bug or a late resend" && 0);
			}
		}
		else
		{
		//	RakAssert("Didn't read GUID in Update in NatTypeDetectionServer.cpp. Message format error" && 0);
		}

		len=NatTypeRecvFrom(data, s3p4, senderAddr);
	}


	while (i < (int) natDetectionAttempts.Size())
	{
		if (time > natDetectionAttempts[i].nextStateTime)
		{
			natDetectionAttempts[i].detectionState=(NATDetectionState)((int)natDetectionAttempts[i].detectionState+1);
			natDetectionAttempts[i].nextStateTime=time+natDetectionAttempts[i].timeBetweenAttempts;
			SystemAddress saOut;
			unsigned char c;
			bs.Reset();
			switch (natDetectionAttempts[i].detectionState)
			{
			case STATE_TESTING_NONE_1:
			case STATE_TESTING_NONE_2:
				c = NAT_TYPE_NONE;
				printf("Testing NAT_TYPE_NONE\n");
				// S4P5 sends to C2. If arrived, no NAT. Done. (Else S4P5 potentially banned, do not use again).
				saOut=natDetectionAttempts[i].systemAddress;
				saOut.SetPort(natDetectionAttempts[i].c2Port);
				SocketLayer::SendTo_PC( s4p5, (const char*) &c, 1, saOut, __FILE__, __LINE__  );
				break;
			case STATE_TESTING_FULL_CONE_1:
			case STATE_TESTING_FULL_CONE_2:
				printf("Testing NAT_TYPE_FULL_CONE\n");
				rakPeerInterface->WriteOutOfBandHeader(&bs);
				bs.Write((unsigned char) ID_NAT_TYPE_DETECT);
				bs.Write((unsigned char) NAT_TYPE_FULL_CONE);
				// S2P3 sends to C1 (Different address, different port, to previously used port on client). If received, Full-cone nat. Done.  (Else S2P3 potentially banned, do not use again).
				saOut=natDetectionAttempts[i].systemAddress;
				saOut.SetPort(natDetectionAttempts[i].systemAddress.GetPort());
				SocketLayer::SendTo_PC( s2p3, (const char*) bs.GetData(), bs.GetNumberOfBytesUsed(), saOut, __FILE__, __LINE__  );
				break;
			case STATE_TESTING_ADDRESS_RESTRICTED_1:
			case STATE_TESTING_ADDRESS_RESTRICTED_2:
				printf("Testing NAT_TYPE_ADDRESS_RESTRICTED\n");
				rakPeerInterface->WriteOutOfBandHeader(&bs);
				bs.Write((unsigned char) ID_NAT_TYPE_DETECT);
				bs.Write((unsigned char) NAT_TYPE_ADDRESS_RESTRICTED);
				// S1P2 sends to C1 (Same address, different port, to previously used port on client). If received, address-restricted cone nat. Done.
				saOut=natDetectionAttempts[i].systemAddress;
				saOut.SetPort(natDetectionAttempts[i].systemAddress.GetPort());
				SocketLayer::SendTo_PC( s1p2, (const char*) bs.GetData(), bs.GetNumberOfBytesUsed(), saOut, __FILE__, __LINE__  );
				break;
			case STATE_TESTING_PORT_RESTRICTED_1:
			case STATE_TESTING_PORT_RESTRICTED_2:
				// C1 sends to S3P4. If address of C1 as seen by S3P4 is the same as the address of C1 as seen by S1P1, then port-restricted cone nat. Done
				printf("Testing NAT_TYPE_PORT_RESTRICTED\n");
				bs.Write((unsigned char) ID_NAT_TYPE_DETECTION_REQUEST);
				bs.Write(RakString::NonVariadic(s3p4Address));
				bs.Write(s3p4Port);
				rakPeerInterface->Send(&bs,HIGH_PRIORITY,RELIABLE,0,natDetectionAttempts[i].systemAddress,false);
				break;
			default:
				printf("Warning, exceeded final check STATE_TESTING_PORT_RESTRICTED_2.\nExpected that client would have sent NAT_TYPE_PORT_RESTRICTED on s3p4.\nDefaulting to Symmetric\n");
				bs.Write((unsigned char) ID_NAT_TYPE_DETECTION_RESULT);
				bs.Write((unsigned char) NAT_TYPE_SYMMETRIC);
				rakPeerInterface->Send(&bs,HIGH_PRIORITY,RELIABLE,0,natDetectionAttempts[i].systemAddress,false);
				natDetectionAttempts.RemoveAtIndexFast(i);
				i--;
				break;
			}

		}
		i++;
	}
}
예제 #23
0
void NatPunchthroughClient::SendOutOfBand(SystemAddress sa, MessageID oobId)
{
	if (sa==UNASSIGNED_SYSTEM_ADDRESS)
		return;
	if (sa.GetPort()==0)
		return;

	RakNet::BitStream oob;
	oob.Write(oobId);
	oob.Write(sp.sessionId);
//	RakAssert(sp.sessionId<100);
	if (oobId==ID_NAT_ESTABLISH_BIDIRECTIONAL)
		oob.Write(sa.GetPort());
	char ipAddressString[32];
	sa.ToString(false, ipAddressString);
	rakPeerInterface->SendOutOfBand((const char*) ipAddressString,sa.GetPort(),(const char*) oob.GetData(),oob.GetNumberOfBytesUsed());

	if (natPunchthroughDebugInterface)
	{
		sa.ToString(true,ipAddressString);
		char guidString[128];
		sp.targetGuid.ToString(guidString);

		// server - diff = my time
		// server = myTime + diff
		RakNet::Time clockDifferential = rakPeerInterface->GetClockDifferential(sp.facilitator);
		RakNet::Time serverTime = RakNet::GetTime() + clockDifferential;

		if (oobId==ID_NAT_ESTABLISH_UNIDIRECTIONAL)
			natPunchthroughDebugInterface->OnClientMessage(RakNet::RakString("%I64d: %s: OOB ID_NAT_ESTABLISH_UNIDIRECTIONAL to guid %s, system address %s.\n", serverTime, TestModeToString(sp.testMode), guidString, ipAddressString));
		else
			natPunchthroughDebugInterface->OnClientMessage(RakNet::RakString("%I64d: %s: OOB ID_NAT_ESTABLISH_BIDIRECTIONAL to guid %s, system address %s.\n", serverTime, TestModeToString(sp.testMode), guidString, ipAddressString));
	}
}
예제 #24
0
const char *EmailSender::Send(const char *hostAddress, unsigned short hostPort, const char *sender, const char *recipient, const char *senderName, const char *recipientName, const char *subject, const char *body, FileList *attachedFiles, bool doPrintf, const char *password)
{
	RakNet::Packet *packet;
	char query[1024];
	TCPInterface tcpInterface;
	SystemAddress emailServer;
	if (tcpInterface.Start(0, 0)==false)
		return "Unknown error starting TCP";
	emailServer=tcpInterface.Connect(hostAddress, hostPort,true);
	if (emailServer==UNASSIGNED_SYSTEM_ADDRESS)
		return "Failed to connect to host";
#if  OPEN_SSL_CLIENT_SUPPORT==1
	tcpInterface.StartSSLClient(emailServer);
#endif
	RakNet::TimeMS timeoutTime = RakNet::GetTimeMS()+3000;
	packet=0;
	while (RakNet::GetTimeMS() < timeoutTime)
	{
		packet = tcpInterface.Receive();
		if (packet)
		{
			if (doPrintf)
				RAKNET_DEBUG_PRINTF("%s", packet->data);
			break;
		}
		RakSleep(250);
	}

	if (packet==0)
		return "Timeout while waiting for initial data from server.";
	
	tcpInterface.Send("EHLO\r\n", 6, emailServer,false);
	const char *response;
	bool authenticate=false;
#ifdef _MSC_VER
#pragma warning(disable:4127)   // conditional expression is constant
#endif
	while (1)
	{
		response=GetResponse(&tcpInterface, emailServer, doPrintf);

		if (response!=0 && strcmp(response, "AUTHENTICATE")==0)
		{
			authenticate=true;
			break;
		}

		// Something other than continue?
		if (response!=0 && strcmp(response, "CONTINUE")!=0)
			return response;

		// Success?
		if (response==0)
			break;
	}

	if (authenticate)
	{
		sprintf(query, "EHLO %s\r\n", sender);
		tcpInterface.Send(query, (unsigned int)strlen(query), emailServer,false);
		response=GetResponse(&tcpInterface, emailServer, doPrintf);
		if (response!=0)
			return response;
		if (password==0)
			return "Password needed";
		char *outputData = RakNet::OP_NEW_ARRAY<char >((const int) (strlen(sender)+strlen(password)+2)*3, _FILE_AND_LINE_ );
		RakNet::BitStream bs;
		char zero=0;
		bs.Write(&zero,1);
		bs.Write(sender,(const unsigned int)strlen(sender));
		//bs.Write("*****@*****.**",(const unsigned int)strlen("*****@*****.**"));
		bs.Write(&zero,1);
		bs.Write(password,(const unsigned int)strlen(password));
		bs.Write(&zero,1);
		//bs.Write("not.my.real.password",(const unsigned int)strlen("not.my.real.password"));
		Base64Encoding((const char*)bs.GetData(), bs.GetNumberOfBytesUsed(), outputData);
		sprintf(query, "AUTH PLAIN %s", outputData);
		tcpInterface.Send(query, (unsigned int)strlen(query), emailServer,false);
		response=GetResponse(&tcpInterface, emailServer, doPrintf);
		if (response!=0)
			return response;
	}


	if (sender)
		sprintf(query, "MAIL From: <%s>\r\n", sender);
	else
		sprintf(query, "MAIL From: <>\r\n");
	tcpInterface.Send(query, (unsigned int)strlen(query), emailServer,false);
	response=GetResponse(&tcpInterface, emailServer, doPrintf);
	if (response!=0)
		return response;

	if (recipient)
		sprintf(query, "RCPT TO: <%s>\r\n", recipient);
	else
		sprintf(query, "RCPT TO: <>\r\n");
	tcpInterface.Send(query, (unsigned int)strlen(query), emailServer,false);
	response=GetResponse(&tcpInterface, emailServer, doPrintf);
	if (response!=0)
		return response;

	tcpInterface.Send("DATA\r\n", (unsigned int)strlen("DATA\r\n"), emailServer,false);

	// Wait for 354...

	response=GetResponse(&tcpInterface, emailServer, doPrintf);
	if (response!=0)
		return response;

	if (subject)
	{
		sprintf(query, "Subject: %s\r\n", subject);
		tcpInterface.Send(query, (unsigned int)strlen(query), emailServer,false);
	}
	if (senderName)
	{
		sprintf(query, "From: %s\r\n", senderName);
		tcpInterface.Send(query, (unsigned int)strlen(query), emailServer,false);
	}
	if (recipientName)
	{
		sprintf(query, "To: %s\r\n", recipientName);
		tcpInterface.Send(query, (unsigned int)strlen(query), emailServer,false);
	}

	const int boundarySize=60;
	char boundary[boundarySize+1];
	int i,j;
	if (attachedFiles && attachedFiles->fileList.Size())
	{
		rakNetRandom.SeedMT((unsigned int) RakNet::GetTimeMS());
		// Random multipart message boundary
		for (i=0; i < boundarySize; i++)
			boundary[i]=Base64Map()[rakNetRandom.RandomMT()%64];
		boundary[boundarySize]=0;
	}

	sprintf(query, "MIME-version: 1.0\r\n");
	tcpInterface.Send(query, (unsigned int)strlen(query), emailServer,false);

	if (attachedFiles && attachedFiles->fileList.Size())
	{
		sprintf(query, "Content-type: multipart/mixed; BOUNDARY=\"%s\"\r\n\r\n", boundary);
		tcpInterface.Send(query, (unsigned int)strlen(query), emailServer,false);

		sprintf(query, "This is a multi-part message in MIME format.\r\n\r\n--%s\r\n", boundary);
		tcpInterface.Send(query, (unsigned int)strlen(query), emailServer,false);
	}
	
	sprintf(query, "Content-Type: text/plain; charset=\"US-ASCII\"\r\n\r\n");
	tcpInterface.Send(query, (unsigned int)strlen(query), emailServer,false);

	// Write the body of the email, doing some lame shitty shit where I have to make periods at the start of a newline have a second period.
	char *newBody;
	int bodyLength;
	bodyLength=(int)strlen(body);
	newBody = (char*) rakMalloc_Ex( bodyLength*3, _FILE_AND_LINE_ );
	if (bodyLength>0)
		newBody[0]=body[0];
	for (i=1, j=1; i < bodyLength; i++)
	{
		// Transform \n . \r \n into \n . . \r \n
		if (i < bodyLength-2 &&
			body[i-1]=='\n' &&
			body[i+0]=='.' &&
			body[i+1]=='\r' &&
			body[i+2]=='\n')
		{
			newBody[j++]='.';
			newBody[j++]='.';
			newBody[j++]='\r';
			newBody[j++]='\n';
			i+=2;
		}
		// Transform \n . . \r \n into \n . . . \r \n
		// Having to process .. is a bug in the mail server - the spec says ONLY \r\n.\r\n should be transformed
		else if (i <= bodyLength-3 &&
			body[i-1]=='\n' &&
			body[i+0]=='.' &&
			body[i+1]=='.' &&
			body[i+2]=='\r' &&
			body[i+3]=='\n')
		{
			newBody[j++]='.';
			newBody[j++]='.';
			newBody[j++]='.';
			newBody[j++]='\r';
			newBody[j++]='\n';
			i+=3;
		}
		// Transform \n . \n into \n . . \r \n (this is a bug in the mail server - the spec says do not count \n alone but it does)
		else if (i < bodyLength-1 &&
			body[i-1]=='\n' &&
			body[i+0]=='.' &&
			body[i+1]=='\n')
		{
			newBody[j++]='.';
			newBody[j++]='.';
			newBody[j++]='\r';
			newBody[j++]='\n';
			i+=1;
		}
		// Transform \n . . \n into \n . . . \r \n (this is a bug in the mail server - the spec says do not count \n alone but it does)
		// In fact having to process .. is a bug too - because the spec says ONLY \r\n.\r\n should be transformed
		else if (i <= bodyLength-2 &&
			body[i-1]=='\n' &&
			body[i+0]=='.' &&
			body[i+1]=='.' &&
			body[i+2]=='\n')
		{
			newBody[j++]='.';
			newBody[j++]='.';
			newBody[j++]='.';
			newBody[j++]='\r';
			newBody[j++]='\n';
			i+=2;
		}
		else
			newBody[j++]=body[i];
	}
	
	newBody[j++]='\r';
	newBody[j++]='\n';
	tcpInterface.Send(newBody, j, emailServer,false);

	rakFree_Ex(newBody, _FILE_AND_LINE_ );
	int outputOffset;

	// What a pain in the rear.  I have to map the binary to printable characters using 6 bits per character.
	if (attachedFiles && attachedFiles->fileList.Size())
	{
		for (i=0; i < (int) attachedFiles->fileList.Size(); i++)
		{
			// Write boundary
			sprintf(query, "\r\n--%s\r\n", boundary);
			tcpInterface.Send(query, (unsigned int)strlen(query), emailServer,false);

			sprintf(query, "Content-Type: APPLICATION/Octet-Stream; SizeOnDisk=%i; name=\"%s\"\r\nContent-Transfer-Encoding: BASE64\r\nContent-Description: %s\r\n\r\n", attachedFiles->fileList[i].dataLengthBytes, attachedFiles->fileList[i].filename.C_String(), attachedFiles->fileList[i].filename.C_String());
			tcpInterface.Send(query, (unsigned int)strlen(query), emailServer,false);

			newBody = (char*) rakMalloc_Ex( (size_t) (attachedFiles->fileList[i].dataLengthBytes*3)/2, _FILE_AND_LINE_ );

			outputOffset=Base64Encoding(attachedFiles->fileList[i].data, (int) attachedFiles->fileList[i].dataLengthBytes, newBody);

			// Send the base64 mapped file.
			tcpInterface.Send(newBody, outputOffset, emailServer,false);
			rakFree_Ex(newBody, _FILE_AND_LINE_ );

		}

		// Write last boundary
		sprintf(query, "\r\n--%s--\r\n", boundary);
		tcpInterface.Send(query, (unsigned int)strlen(query), emailServer,false);
	}


	sprintf(query, "\r\n.\r\n");
	tcpInterface.Send(query, (unsigned int)strlen(query), emailServer,false);
	response=GetResponse(&tcpInterface, emailServer, doPrintf);
	if (response!=0)
		return response;

	tcpInterface.Send("QUIT\r\n", (unsigned int)strlen("QUIT\r\n"), emailServer,false);

	RakSleep(30);
	if (doPrintf)
	{
		packet = tcpInterface.Receive();
		while (packet)
		{
			RAKNET_DEBUG_PRINTF("%s", packet->data);
			packet = tcpInterface.Receive();
		}
	}
	tcpInterface.Stop();
	return 0; // Success
}
예제 #25
0
void ReplicaObject::writeToPacket(RakNet::BitStream * packet, REPLICA_PACKET_TYPE packetType){
	if (packetType == REPLICA_PACKET_TYPE::REPLICA_CONSTRUCTION_PACKET){
		packet->Write(this->objid);
		packet->Write(this->LOT);

		packet->Write((unsigned char)this->name.size());
		for (unsigned int k = 0; k < this->name.size(); k++){
			packet->Write(this->name.at(k));
		}

		packet->Write(3025001UL);
		//packet->Write(0UL); // time_since_created_on_server (possibly)
		packet->Write(false); // Compressed info... to be added later
		packet->Write(trigger_id); // trigger_id
		packet->Write((bool)(spawnerObjID > 0));
		if (spawnerObjID > 0) { std::cout << "Writing spawnerObjID" << std::endl; packet->Write(spawnerObjID); } // spawnerObjID
		packet->Write((bool)(spawner_node_id >= 0));
		if (spawner_node_id >= 0) { std::cout << "Writing spawner_node_id" << std::endl; packet->Write(spawner_node_id); } // spawnerNodeID
		packet->Write((bool)(floatData >= 0.0));
		if (floatData >= 0.0) { std::cout << "Writing floatData" << std::endl; packet->Write(floatData); } // Unknown floatData
		packet->Write((bool)(objectWorldState >= 0));
		if (objectWorldState >= 0) { std::cout << "Writing objectWorldState" << std::endl; packet->Write(objectWorldState); } // objectWorldState
		packet->Write(this->gmlevel > 0);
		if (this->gmlevel > 0){ std::cout << "Writing gmlevel" << std::endl; packet->Write(this->gmlevel); } // gmlevel
	}
	packet->Write(true);
	packet->Write(false);
	packet->Write(false);

	for (std::vector<ReplicaComponent *>::iterator it = components.begin(); it != components.end(); ++it){
		(*it)->writeToPacket(packet, packetType);
	}

	if (packetType == REPLICA_PACKET_TYPE::REPLICA_CONSTRUCTION_PACKET) {
		/*RakNet::BitStream bs;
		bs.Write((char)0x24);
		bs.Write((bool)true);
		bs.Write((short)280);
		bs.Write(packet);

		std::stringstream ss;
		ss << "ReplicaPacket_" << i << ".bin";
		i++;

		SavePacket(ss.str(), (char*)bs.GetData(), bs.GetNumberOfBytesUsed());*/

		RakNet::BitStream bs;
		bs.Write((char)0x27);
		bs.Write((short)48608);
		bs.Write(false);
		bs.Write(false);
		bs.Write(false);
		bs.Write(false);
		bs.Write(false);
		bs.Write(false);
		bs.Write(false);
		bs.Write(true);
		bs.Write((long)1);
		bs.Write((long long)1152921504606847070);

		std::stringstream ss;
		ss << "ReplicaPacket_" << i << ".bin";
		i++;

		SavePacket(ss.str(), (char*)bs.GetData(), bs.GetNumberOfBytesUsed());
	}
}
예제 #26
0
void RPC4::CallLoopback( const char* uniqueID, RakNet::BitStream * bitStream )
{
	Packet *p=0;

	DataStructures::HashIndex skhi = registeredNonblockingFunctions.GetIndexOf(uniqueID);

	if (skhi.IsInvalid()==true)
	{
		if (rakPeerInterface) 
			p=AllocatePacketUnified(sizeof(MessageID)+sizeof(unsigned char)+(unsigned int) strlen(uniqueID)+1);
#if _RAKNET_SUPPORT_PacketizedTCP==1 && _RAKNET_SUPPORT_TCPInterface==1
		else
			p=packetizedTCP->AllocatePacket(sizeof(MessageID)+sizeof(unsigned char)+(unsigned int) strlen(uniqueID)+1);
#endif

		if (rakPeerInterface)
			p->guid=rakPeerInterface->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS);
#if _RAKNET_SUPPORT_PacketizedTCP==1 && _RAKNET_SUPPORT_TCPInterface==1
		else
			p->guid=UNASSIGNED_RAKNET_GUID;
#endif

		p->systemAddress=UNASSIGNED_SYSTEM_ADDRESS;
		p->systemAddress.systemIndex=(SystemIndex)-1;
		p->data[0]=ID_RPC_REMOTE_ERROR;
		p->data[1]=RPC_ERROR_FUNCTION_NOT_REGISTERED;
		strcpy((char*) p->data+2, uniqueID);
		
		PushBackPacketUnified(p,false);

		return;
	}

	RakNet::BitStream out;
	out.Write((MessageID) ID_RPC_PLUGIN);
	out.Write((MessageID) ID_RPC4_CALL);
	out.WriteCompressed(uniqueID);
	out.Write(false); // nonblocking
	if (bitStream)
	{
		bitStream->ResetReadPointer();
        out.AlignWriteToByteBoundary();
		out.Write(bitStream);
	}
	if (rakPeerInterface) 
		p=AllocatePacketUnified(out.GetNumberOfBytesUsed());
#if _RAKNET_SUPPORT_PacketizedTCP==1 && _RAKNET_SUPPORT_TCPInterface==1
	else
		p=packetizedTCP->AllocatePacket(out.GetNumberOfBytesUsed());
#endif

	if (rakPeerInterface)
		p->guid=rakPeerInterface->GetGuidFromSystemAddress(UNASSIGNED_SYSTEM_ADDRESS);
#if _RAKNET_SUPPORT_PacketizedTCP==1 && _RAKNET_SUPPORT_TCPInterface==1
	else
		p->guid=UNASSIGNED_RAKNET_GUID;
#endif
	p->systemAddress=UNASSIGNED_SYSTEM_ADDRESS;
	p->systemAddress.systemIndex=(SystemIndex)-1;
	memcpy(p->data,out.GetData(),out.GetNumberOfBytesUsed());
	PushBackPacketUnified(p,false);
	return;
}
// 0=failed, 1=success, 2=ignore
void NatPunchthroughClient::UpdateGroupPunchOnNatResult(SystemAddress facilitator, RakNetGUID targetSystem, SystemAddress targetSystemAddress, int result)
{
	GroupPunchRequest *gpr;
	unsigned long i,j,k;
	i=0;
	while (i < groupPunchRequests.Size())
	{
		gpr = groupPunchRequests[i];
		if (gpr->facilitator==facilitator)
		{
			j=0;
			while (j < gpr->pendingList.Size())
			{
				if (gpr->pendingList[j]==targetSystem)
				{
					if (result==0)
					{
						gpr->failedList.Push(targetSystem, _FILE_AND_LINE_);
					}
					else if (result==1)
					{
						gpr->passedListGuid.Push(targetSystem, _FILE_AND_LINE_);
						gpr->passedListAddress.Push(targetSystemAddress, _FILE_AND_LINE_);
					}
					else
					{
						gpr->ignoredList.Push(targetSystem, _FILE_AND_LINE_);
					}
					gpr->pendingList.RemoveAtIndex(j);
				}
				else
					j++;
			}
		}
		if (gpr->pendingList.Size()==0)
		{
			RakNet::BitStream output;
			if (gpr->failedList.Size()==0)
			{
				output.Write(ID_NAT_GROUP_PUNCH_SUCCEEDED);
			}
			else
			{
				output.Write(ID_NAT_GROUP_PUNCH_FAILED);
			}

			output.WriteCasted<unsigned char>(gpr->passedListGuid.Size());
			for (k=0; k < gpr->passedListGuid.Size(); k++)
			{
				output.Write(gpr->passedListGuid[k]);
				output.Write(gpr->passedListAddress[k]);
			}
			output.WriteCasted<unsigned char>(gpr->ignoredList.Size());
			for (k=0; k < gpr->ignoredList.Size(); k++)
			{
				output.Write(gpr->ignoredList[k]);
			}
			output.WriteCasted<unsigned char>(gpr->failedList.Size());
			for (k=0; k < gpr->failedList.Size(); k++)
			{
				output.Write(gpr->failedList[k]);
			}			

			Packet *p = AllocatePacketUnified(output.GetNumberOfBytesUsed());
			p->systemAddress=gpr->facilitator;
			p->systemAddress.systemIndex=(SystemIndex)-1;
			p->guid=rakPeerInterface->GetGuidFromSystemAddress(gpr->facilitator);
			p->wasGeneratedLocally=true;
			memcpy(p->data, output.GetData(), output.GetNumberOfBytesUsed());
			rakPeerInterface->PushBackPacket(p, true);

			groupPunchRequests.RemoveAtIndex(i);
			RakNet::OP_DELETE(gpr, _FILE_AND_LINE_);
		}
		else
			i++;
	}
}
예제 #28
0
void CConsole::SendRules(char* queryData, SOCKET socket, const sockaddr_in* to, int tolen)
{
	const char* varName;
	char varValue[1024];

	std::map<std::string, consoleVarStruct*>::iterator itor;

	uint16_t svrRuleCount = 0;
	for (itor = varMap.begin(); itor != varMap.end(); itor++)
		if (itor->second->varFlags & CONSOLE_VARFLAG_RULE)
			svrRuleCount++;

	uint16_t rulesLen = 13 + (svrRuleCount * 62);

#ifndef _USE_BITSTREAMS
	char* dataBuf = new char[rulesLen];
	char* dataPtr = dataBuf;
	
	memcpy(dataBuf, queryData, 11);
	dataBuf += 11;
#else
	RakNet::BitStream rules;
	
	rules.Write((char*)queryData, 11);
	rules.Write(svrRuleCount);
#endif
#ifndef _USE_BITSTREAMS
	memcpy(dataBuf, &svrRuleCount, sizeof(uint16_t));
	dataBuf += sizeof(uint16_t);
#endif

	uint8_t varNameLen;

	for (itor = varMap.begin(); itor != varMap.end(); itor++)
	{
		if (itor->second->varFlags & 4)
		{
			varName = itor->first.c_str();
			switch (itor->second->varType)
			{
				case CONSOLE_VARTYPE_FLOAT:
					sprintf(varValue, "%f", *(float*)itor->second->varValue);
					break;
				case CONSOLE_VARTYPE_INT:
					sprintf(varValue, "%d", *(int*)itor->second->varValue);
					break;
				case CONSOLE_VARTYPE_BOOL:
					sprintf(varValue, "%d", *(bool*)itor->second->varValue);
					break;
				case CONSOLE_VARTYPE_STRING:
					strcpy(varValue, (char*)itor->second->varValue);
					break;
			}

			varNameLen = strlen(varName);
#ifdef _USE_BITSTREAMS
			rules.Write(varNameLen);
			rules.Write(varName, varNameLen);
#else
			memcpy(dataBuf, &varNameLen, sizeof(uint8_t));
			dataBuf += sizeof(uint8_t);
			memcpy(dataBuf, varName, varNameLen);
			dataBuf += varNameLen;
#endif
			varNameLen = strlen(varValue);
#ifdef _USE_BITSTREAMS
			rules.Write(varNameLen);
			rules.Write(varValue, varNameLen);
#else
			memcpy(dataBuf, &varNameLen, sizeof(uint8_t));
			dataBuf += sizeof(uint8_t);

			memcpy(dataBuf, varValue, varNameLen);
			dataBuf += varNameLen;
#endif
		}
	}
#ifdef _USE_BITSTREAMS
	sendto(socket, (char*)rules.GetData(), rules.GetNumberOfBytesUsed(), 0, (sockaddr*)to, tolen);
#else
	sendto(socket, dataPtr, (int)(dataBuf - dataPtr), 0, (sockaddr*)to, tolen);
	delete [] dataPtr;
#endif
}
예제 #29
0
void FileListTransfer::Send(FileList *fileList, RakPeerInterface *rakPeer, SystemAddress recipient, unsigned short setID, PacketPriority priority, char orderingChannel, bool compressData, IncrementalReadInterface *_incrementalReadInterface, unsigned int _chunkSize)
{
	(void) compressData;

	if (callback)
		fileList->SetCallback(callback);

	unsigned int i, totalLength;
	RakNet::BitStream outBitstream;
	bool sendReference;
	char *dataBlocks[2];
	int lengths[2];
	totalLength=0;
	for (i=0; i < fileList->fileList.Size(); i++)
	{
		const FileListNode &fileListNode = fileList->fileList[i];
		totalLength+=fileListNode.fileLengthBytes;
	}

	// Write the chunk header, which contains the frequency table, the total number of files, and the total number of bytes
	bool anythingToWrite;
	outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_HEADER);
	outBitstream.Write(setID);
	anythingToWrite=fileList->fileList.Size()>0;
	outBitstream.Write(anythingToWrite);
	if (anythingToWrite)
	{
		outBitstream.WriteCompressed(fileList->fileList.Size());
		outBitstream.WriteCompressed(totalLength);

		if (rakPeer)
			rakPeer->Send(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false);
		else
			SendUnified(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false);
	
		for (i=0; i < fileList->fileList.Size(); i++)
		{
			outBitstream.Reset();
			sendReference = fileList->fileList[i].isAReference && _incrementalReadInterface!=0;
			if (sendReference)
			{
				StoreForPush(fileList->fileList[i].context, setID, fileList->fileList[i].filename, fileList->fileList[i].fullPathToFile, i, fileList->fileList[i].fileLengthBytes, fileList->fileList[i].dataLengthBytes, recipient, priority, orderingChannel, _incrementalReadInterface, _chunkSize);
				continue;
			}

			outBitstream.Write((MessageID)ID_FILE_LIST_TRANSFER_FILE);
			
			outBitstream.Write(fileList->fileList[i].context);
			outBitstream.Write(setID);
			stringCompressor->EncodeString(fileList->fileList[i].filename, 512, &outBitstream);
			
			outBitstream.WriteCompressed(i);
			outBitstream.WriteCompressed(fileList->fileList[i].dataLengthBytes); // Original length in bytes

			outBitstream.AlignWriteToByteBoundary();

			dataBlocks[0]=(char*) outBitstream.GetData();
			lengths[0]=outBitstream.GetNumberOfBytesUsed();
			dataBlocks[1]=fileList->fileList[i].data;
			lengths[1]=fileList->fileList[i].dataLengthBytes;
			if (rakPeer)
				rakPeer->SendList(dataBlocks,lengths,2,priority, RELIABLE_ORDERED, orderingChannel, recipient, false);
			else
				SendListUnified(dataBlocks,lengths,2,priority, RELIABLE_ORDERED, orderingChannel, recipient, false);
		}
	}
	else
	{
		if (rakPeer)
			rakPeer->Send(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false);
		else
			SendUnified(&outBitstream, priority, RELIABLE_ORDERED, orderingChannel, recipient, false);
	}
}
예제 #30
0
void SendStatusPacket(RakPeerInterface *rakServer, const SystemAddress& systemAddress, UserSuccess loginStatus, string redirectIpAddress, ushort redirectPort, ushort extraDataLength) {
	RakNet::BitStream bitStream; // Create the bitStream

	// Always create the packet header
	CreatePacketHeader(ID_USER_PACKET_ENUM, 5, 0, &bitStream);

	LoginStatusPacket loginStatusPacket;

	// Set the loginStatus
	loginStatusPacket.loginStatus = loginStatus;

	// Set Talk_Like_A_Pirate_String
	loginStatusPacket.talkLikeAPirate = "Talk_Like_A_Pirate";
	loginStatusPacket.unknownString = "";

	// Set client version
	loginStatusPacket.clientVersion1 = 1;
	loginStatusPacket.clientVersion2 = 10;
	loginStatusPacket.clientVersion3 = 64;

	// This is unknown data...
	loginStatusPacket.unknown = "_";

	time_t t = time(NULL);
	unsigned int addr = systemAddress.binaryAddress;
	long long a = (long long)t * (long long)addr;
	std::string hash = md5(std::to_string(a));
	std::wstring key = StringToWString(hash, 33);

	// Get the user key
	loginStatusPacket.userKey = key;
	//loginStatusPacket.userKey = "0 9 4 e 7 0 1 a c 3 b 5 5 2 0 b 4 7 8 9 5 b 3 1 8 5 7 b f 1 c 3   ";

	// Set chat IPs/Port and the other IP
	loginStatusPacket.chatIp = "192.168.0.20"; //TODO: make dynamic
	loginStatusPacket.chatPort = 2003;
	loginStatusPacket.anotherIp = "192.168.0.20";

	loginStatusPacket.possibleGuid = "00000000-0000-0000-0000-000000000000";

	loginStatusPacket.zeroLong = 0;

	// Set localization
	loginStatusPacket.localizationChar[0] = 0x55;
	loginStatusPacket.localizationChar[1] = 0x53;
	loginStatusPacket.localizationChar[2] = 0x00;

	// Subscribed?
	loginStatusPacket.firstLoginSubscription = 1;
	loginStatusPacket.subscribed = 0;

	loginStatusPacket.zeroLongLong = 0;

	loginStatusPacket.redirectIp = redirectIpAddress;
	loginStatusPacket.redirectPort = redirectPort;

	// Sett the error msg and the error msg length
	// This message only shows
	loginStatusPacket.errorMsg = "";
	loginStatusPacket.errorMsgLength = loginStatusPacket.errorMsg.length();

	// Set the extraBytesLength to the one the user defined
	loginStatusPacket.extraBytesLength = extraDataLength;

	// ---- CREATE BITSTREAM ---- //
	// Write the connectionId to bitStream
	bitStream.Write(loginStatusPacket.loginStatus);

	// Write the "Talk_Like_A_Pirate" string to bitStream
	WriteStringToBitStream(loginStatusPacket.talkLikeAPirate.c_str(), 18, 33, &bitStream);

	// Write 7 blocks of data (length: 33) to bitStream
	// In the original login_status_ok.bin, these sometimes ended in
	// bytes other than 0x00, but losing that doesn't seem to have much of an effect... yet.
	for (int i = 0; i < 7; i++) {
		WriteStringToBitStream(loginStatusPacket.unknownString.c_str(), 0, 33, &bitStream);
	}

	// Write the clientVersion to bitStream (all 3 parts)
	bitStream.Write(loginStatusPacket.clientVersion1);
	bitStream.Write(loginStatusPacket.clientVersion2);
	bitStream.Write(loginStatusPacket.clientVersion3);

	// Write the userKey, redirectIp, and chatIp to bitStream
	//WriteStringToBitStream(loginStatusPacket.userKey.c_str(), 66, 66, &bitStream);
	PacketTools::WriteToPacket(&bitStream, loginStatusPacket.userKey, 33);
	WriteStringToBitStream(loginStatusPacket.redirectIp.c_str(), sizeof(loginStatusPacket.redirectIp), 33, &bitStream);
	WriteStringToBitStream(loginStatusPacket.chatIp.c_str(), sizeof(loginStatusPacket.chatIp), 33, &bitStream);
	
	// Write the redirectPort and the chatPort to bitStream
	bitStream.Write(loginStatusPacket.redirectPort);
	bitStream.Write(loginStatusPacket.chatPort);
	
	// Write seperate ip(?) and possibleGuid to bitStream
	WriteStringToBitStream(loginStatusPacket.anotherIp.c_str(), sizeof(loginStatusPacket.anotherIp), 33, &bitStream);
	WriteStringToBitStream(loginStatusPacket.possibleGuid.c_str(), 37, 37, &bitStream);
	
	// Write the zeroShort to the errorMsgLength to the bitStream
	bitStream.Write(loginStatusPacket.zeroLong);
	bitStream.Write(loginStatusPacket.localizationChar[0]);
	bitStream.Write(loginStatusPacket.localizationChar[1]);
	bitStream.Write(loginStatusPacket.localizationChar[2]);
	bitStream.Write(loginStatusPacket.firstLoginSubscription);
	bitStream.Write(loginStatusPacket.subscribed);
	bitStream.Write(loginStatusPacket.zeroLongLong);
	bitStream.Write(loginStatusPacket.errorMsgLength);
	
	// Write the error msg string to the bitStream
	WriteStringToBitStream(loginStatusPacket.errorMsg.c_str(), loginStatusPacket.errorMsgLength, 0, &bitStream);
	
	// Add extra bytes length
	bitStream.Write(loginStatusPacket.extraBytesLength);

	// Create extra packet data (even if not success, doesn't appear to
	// Do anything at the moment...)
	CreateExtraPacketDataSuccess(&bitStream);

	rakServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE_ORDERED, 0, systemAddress, false);
	SavePacketOverwrite("test_login.bin", (char*)bitStream.GetData(), bitStream.GetNumberOfBytesUsed());
}