Example #1
0
void PHPDirectoryServer2::SendOperation(void)
{
	RakString outgoingMessageBody;
	char buff[64];

	outgoingMessageBody += GAME_PORT_COMMAND;
	outgoingMessageBody += '\001';
	outgoingMessageBody += Itoa(gamePortParam,buff,10);
	outgoingMessageBody += '\001';
	outgoingMessageBody += GAME_NAME_COMMAND;
	outgoingMessageBody += '\001';
	outgoingMessageBody += gameNameParam;

	for (unsigned i = 0; i < fields.Size(); i++)
	{
		RakString value = fields[i];
		value.URLEncode();
		outgoingMessageBody += RakString("\001%s\001%s",
			fields.GetKeyAtIndex(i).C_String(),
			value.C_String());
	}

	RakString postURL;
	postURL+=pathToPHP;
	postURL+=currentOperation;
	http->Post(postURL.C_String(), outgoingMessageBody, "application/x-www-form-urlencoded");

}
Example #2
0
void TestGet(void)
{
	printf("This is NOT a reliable way to download from a website. Use libcurl instead.\n");
	httpConnection->Init(tcp, "jenkinssoftware.com");
	httpConnection->Get("/trivia/ranking.php?t=single&places=6&top");
	while (1)
	{
		Packet *packet = tcp->Receive();
		if(packet)
		{
			//printf((char*) packet->data);
			httpConnection->ProcessTCPPacket(packet);
			tcp->DeallocatePacket(packet);
		}
		httpConnection->Update();

		if (httpConnection->IsBusy()==false)
		{
			RakString fileContents = httpConnection->Read();
			printf(fileContents.C_String());
			getche();
			return;
		}
		// Prevent 100% cpu usage
		RakSleep(30);
	}
}
Example #3
0
RakNet::RakString& RakString::URLEncode(void)
{
	RakString result;
	size_t strLen = strlen(sharedString->c_str);
	result.Allocate(strLen*3);
	char *output=result.sharedString->c_str;
	unsigned int outputIndex=0;
	unsigned i;
	char c;
	for (i=0; i < strLen; i++)
	{
		c=sharedString->c_str[i];
		if (
			(c<=47) ||
			(c>=58 && c<=64) ||
			(c>=91 && c<=96) ||
			(c>=123)
			)
		{
			RakNet::RakString tmp("%2X", c);
			output[outputIndex++]='%';
			output[outputIndex++]=tmp.sharedString->c_str[0];
			output[outputIndex++]=tmp.sharedString->c_str[1];
		}
		else
		{
			output[outputIndex++]=c;
		}
	}

	output[outputIndex]=0;

	*this = result;
	return *this;
}
// Print out a downloaded row (room) from a cloud query
void PrintRow(RakNet::CloudQueryRow *row)
{
	printf("Room at address %s, guid %s", row->clientSystemAddress.ToString(true), row->clientGUID.ToString());
	if (row->clientGUID==rakPeer->GetMyGUID())
		printf(" (Ourselves)");
	printf("\n");

	RakString roomName;
	DataStructures::List<NATTypeDetectionResult> natTypes;
	DeserializeFromBitStream(row, roomName, natTypes);
	printf("Room name: %s. Players: %i\n", roomName.C_String(), natTypes.Size());

#ifdef NAT_TYPE_DETECTION_SERVER
	// If NatTypeDetection is enabled, we can filter out rooms that cannot be joined
	bool joinable=true;
	for (unsigned int i=0; i < natTypes.Size(); i++)
	{
		if (CanConnect(game->myNatType, natTypes[i])==false)
		{
			joinable=false;
			break;
		}
	}

	printf("Joinable=%i\n", joinable);
#endif
}
Example #5
0
RakNet::RakString& RakString::URLDecode(void)
{
	RakString result;
	size_t strLen = strlen(sharedString->c_str);
	result.Allocate(strLen);
	char *output=result.sharedString->c_str;
	unsigned int outputIndex=0;
	char c;
	char hexDigits[2];
	char hexValues[2];
	unsigned int i;
	for (i=0; i < strLen; i++)
	{
		c=sharedString->c_str[i];
		if (c=='%')
		{
			hexDigits[0]=sharedString->c_str[++i];
			hexDigits[1]=sharedString->c_str[++i];
			
			if (hexDigits[0]==' ')
				hexValues[0]=0;
			
			if (hexDigits[0]>='A' && hexDigits[0]<='F')
				hexValues[0]=hexDigits[0]-'A'+10;
			if (hexDigits[0]>='a' && hexDigits[0]<='f')
				hexValues[0]=hexDigits[0]-'a'+10;
			else
				hexValues[0]=hexDigits[0]-'0';

			if (hexDigits[1]>='A' && hexDigits[1]<='F')
				hexValues[1]=hexDigits[1]-'A'+10;
			if (hexDigits[1]>='a' && hexDigits[1]<='f')
				hexValues[1]=hexDigits[1]-'a'+10;
			else
				hexValues[1]=hexDigits[1]-'0';

			output[outputIndex++]=hexValues[0]*16+hexValues[1];
		}
		else
		{
			output[outputIndex++]=c;
		}
	}

	output[outputIndex]=0;

	*this = result;
	return *this;
}
Example #6
0
void ReadChunkBlock( size_t &currentChunkSize, size_t &bytesReadSoFar, char *txtIn, RakString &txtOut)
{
	size_t bytesToRead;
	size_t sLen;
	
	do 
	{
		bytesToRead = currentChunkSize - bytesReadSoFar;
		sLen = strlen(txtIn);
		if (sLen < bytesToRead)
			bytesToRead = sLen;
		txtOut.AppendBytes(txtIn, bytesToRead);
		txtIn += bytesToRead;
		bytesReadSoFar += bytesToRead;
		if (*txtIn == 0)
		{
		//	currentChunkSize=0;
			return;
		}
		// char *newLine = strstr(txtIn, "\r\n");
		if (txtIn[0] && txtIn[0]=='\r' && txtIn[1] && txtIn[1]=='\n' )
			txtIn += 2; // Newline
		char *newLine;
		currentChunkSize = ReadChunkSize(txtIn, &newLine);
		RakAssert(currentChunkSize < 50000); // Sanity check
		if (currentChunkSize == 0)
			return;
		if (newLine == 0)
			return;
		bytesReadSoFar=0;
		txtIn = newLine + 2;
	} while (txtIn);
}
Example #7
0
RakString RakString::SubStr(unsigned int index, unsigned int count) const
{
	size_t length = GetLength();
	if (index >= length || count==0)
		return RakString();
	RakString copy;
	size_t numBytes = length-index;
	if (count < numBytes)
		numBytes=count;
	copy.Allocate(numBytes+1);
	size_t i;
	for (i=0; i < numBytes; i++)
		copy.sharedString->c_str[i]=sharedString->c_str[index+i];
	copy.sharedString->c_str[i]=0;
	return copy;
}
Example #8
0
void DebugTools::ShowError(RakString errorString,bool pause, unsigned int lineNum,const char *fileName)
{
	printf("%s\nFile:%s \nLine: %i\n",errorString.C_String(),fileName,lineNum);

	if (pause)
	{
		printf("Press enter to continue \n");
		std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
		char pauseChar = std::cin.get();
	}
}
Example #9
0
void UpdateCharacterVelocity(RakString name, RakString velX, RakString velY, RakString velZ, RakNet::RPC3* rpcFromNetwork){
	std::vector<RenderableChar*> characters = Game::getSingletonPtr()->GetCharacters();
	for (std::vector<RenderableChar*>::iterator i = characters.begin(); i != characters.end(); ++i) {
		if((*i)->GetNetworkName() == name.C_String()){
			(*i)->setVelX(atoi(velX));
			(*i)->setVelY(atoi(velY));
			(*i)->setVelZ(atoi(velZ));
			return;
		}
	}
}
Example #10
0
RakString RakString::FormatForGET(RakString &uri, unsigned int port)
{
	RakString out;
	RakString host;
	RakString remotePath;
	RakNet::RakString header;

	uri.SplitURI(header, host, remotePath);
	if (host.IsEmpty() || remotePath.IsEmpty())
		return out;

	out.Set("GET %s HTTP/1.0\r\n"
		"Host: %s:%i\r\n"
		"\r\n",
		remotePath.C_String(),
		host.C_String(),
		port);

	return out;
}
Example #11
0
NetworkMessage* NetworkUtils::DeSerialize( BitStream* bitStream )
{
    NetworkMessage* message = new NetworkMessage( );

    bitStream->Read( message->message );
    bitStream->Read( message->messageId );

    int parameterCount = 0;
    bitStream->Read( parameterCount );

    for( int i = 0; i < parameterCount; i++ )
    {
        RakString parameterId;
        bitStream->Read( parameterId );

        NetworkTypes networkType;
        bitStream->Read( networkType );

        switch ( networkType )
        {

        case NETWORKTYPE_STRING:
        {
            RakString parameter;
            bitStream->Read( parameter );
            message->parameters[ parameterId.C_String( ) ] = std::string( parameter.C_String( ) );

            break;
        }

        case NETWORKTYPE_VECTOR:
        {
            MathVector3 parameter;
            bitStream->Read( parameter );
            message->parameters[ parameterId.C_String( ) ] = parameter;

            break;
        }

        case NETWORKTYPE_QUATERNION:
        {
            MathQuaternion parameter;
            bitStream->Read( parameter );
            message->parameters[ parameterId.C_String( ) ] = parameter;

            break;
        }
        }

    }

    return message;
}
PluginReceiveResult FT_Node_Plugin::OnReceive(Packet *packet){

	if (resultHandler){
		RakString strLog;
		strLog.Set ( "FT_Node_Plugin::OnReceive :%d",  packet->data[0]);
		resultHandler->ReceiveLog(strLog);
	}

	if (packet->data[0] == ID_SERVER_LOGIN) {
		FT_MessageTypesNode  typeNode = (FT_MessageTypesNode)packet->data[1];

		if (resultHandler){
			RakString str;
			str.Set("FT_Node_Plugin::OnReceive data[0]: %d, data[1]: %d, typeNode: %d",packet->data[0],packet->data[1], typeNode );
			resultHandler->ReceiveLog(str);
		}

		UINT i = 0;
		for (; i < _Handlers.Size(); i++)
		{
			FT_Node_Process* handler = _Handlers[i];
			if (resultHandler){
				RakString str;
				str.Set("FT_Node_Plugin::OnReceive _Handler[%d].NodeType = %d", i, handler->GetNodeType() );
				resultHandler->ReceiveLog(str);
			}
			if (handler && handler->GetNodeType() == typeNode){
				BitStream bsIn(packet->data, packet->length, false);

				bsIn.IgnoreBytes(sizeof(RakNet::MessageID));
				bsIn.IgnoreBytes(sizeof(RakNet::MessageID));

				FT_Session session;
				// session.Serialize(false, &bsIn);

				// FT_UnitData unitData;
				// unitData.Serialize(false, &bsIn);

				if (!session.IsOutTime()){
					handler->OnProcess(session, &bsIn, packet->systemAddress);
				}
				else{
					handler->OnOutTime(session);
				}
				return RR_STOP_PROCESSING;
			}
		}
	}

	return RR_CONTINUE_PROCESSING;
}
Example #13
0
void UpdateCharacter(RakString name, RakString state, RakString velX, RakString velY, RakString velZ, RakString xPos, RakString yPos, RakString zPos, RakNet::RPC3* rpcFromNetwork){
	std::vector<RenderableChar*> characters = Game::getSingletonPtr()->GetCharacters();
	RenderableChar* localChar = Game::getSingletonPtr()->getLocalPlayer();
	for (std::vector<RenderableChar*>::iterator i = characters.begin(); i != characters.end(); ++i) {
		if((*i)->GetNetworkName() == name.C_String() && (*i)->GetNetworkName() != localChar->GetNetworkName()){
			(*i)->setVelX(atoi(velX));
			(*i)->setVelY(atoi(velY));
			(*i)->setVelZ(atoi(velZ));
			Ogre::Vector3 vec;
			vec.x = atoi(xPos);
			vec.y = atoi(yPos);
			vec.z = atoi(zPos);
			(*i)->SetPosition(vec/10000);
			//(*i)->translateX(vec.x - (*i)->getWorldPosition().x);
			//(*i)->translateY(vec.y - (*i)->getWorldPosition().y);
			(*i)->SetState((RenderableChar::STATE_TYPE)atoi(state));
			return;
		}
	}
}
Example #14
0
void SyncClients(RakString numberOfClientsStr){
	int numberOfClients = atoi(numberOfClientsStr.C_String());
	int numberOfChars = Game::getSingletonPtr()->GetCharacters().size();
	std::vector<RenderableChar*> characters = Game::getSingletonPtr()->GetCharacters();

	for(int i = 2; i <= numberOfClients; i++){
		std::stringstream ss;
		ss << "Client" << i;
		bool found = false;
		for(int j = 0; j < numberOfChars; j++){
			if(characters.at(j)->GetNetworkName()==ss.str()){
				found = true;
				break;
			}
		}
		if(!found){
			Game::getSingletonPtr()->CreateCharacter(ss.str().c_str());	
		}
	}
}
Example #15
0
int RakNet::RakString::RakStringComp( RakString const &key, RakString const &data )
{
	return key.StrCmp(data);
}
Example #16
0
bool RakString::operator >= ( const RakString& right ) const
{
	return strcmp(sharedString->c_str,right.C_String()) >= 0;
}
Example #17
0
unsigned long RakString::ToInteger(const RakString &rs)
{
	return RakString::ToInteger(rs.C_String());
}
Example #18
0
RakString RakString::FormatForDELETE(const char* uri, const char* extraHeaders)
{
	RakString out;
	RakString host;
	RakString remotePath;
	RakNet::RakString header;
	RakNet::RakString uriRs;
	uriRs = uri;

	uriRs.SplitURI(header, host, remotePath);
	if (host.IsEmpty() || remotePath.IsEmpty())
		return out;

	if (extraHeaders && extraHeaders[0])
	{
		out.Set("DELETE %s HTTP/1.1\r\n"
			"%s\r\n"
			"Content-Length: 0\r\n"
			"Host: %s\r\n"
			"Connection: close\r\n"
			"\r\n",
			remotePath.C_String(),
			extraHeaders,
			host.C_String());
	}
	else
	{
		out.Set("DELETE %s HTTP/1.1\r\n"
			"Content-Length: 0\r\n"
			"Host: %s\r\n"
			"Connection: close\r\n"
			"\r\n",
			remotePath.C_String(),
			host.C_String());
	}

	return out;
}
Example #19
0
RakNet::RakString RakString::FormatForPUTOrPost(const char* type, const char* uri, const char* contentType, const char* body, const char* extraHeaders)
{
	RakString out;
	RakString host;
	RakString remotePath;
	RakNet::RakString header;
	RakString uriRs;
	uriRs = uri;
	uriRs.SplitURI(header, host, remotePath);

	if (host.IsEmpty() || remotePath.IsEmpty())
		return out;

//	RakString bodyEncoded = body;
//	bodyEncoded.URLEncode();

	if (extraHeaders!=0 && extraHeaders[0])
	{
		out.Set("%s %s HTTP/1.1\r\n"
			"%s\r\n"
			"Host: %s\r\n"
			"Content-Type: %s\r\n"
			"Content-Length: %u\r\n"
			"\r\n"
			"%s",
			type,
			remotePath.C_String(),
			extraHeaders,
			host.C_String(),
			contentType,
			//bodyEncoded.GetLength(),
			//bodyEncoded.C_String());
			strlen(body),
			body);
	}
	else
	{
		out.Set("%s %s HTTP/1.1\r\n"
			"Host: %s\r\n"
			"Content-Type: %s\r\n"
			"Content-Length: %u\r\n"
			"\r\n"
			"%s",
			type,
			remotePath.C_String(),
			host.C_String(),
			contentType,
			//bodyEncoded.GetLength(),
			//bodyEncoded.C_String());
			strlen(body),
			body);
	}

	return out;
}
Example #20
0
void HTTPConnection::Update(void)
{
    SystemAddress sa;
    sa = tcp->HasCompletedConnectionAttempt();
    while (sa!=UNASSIGNED_SYSTEM_ADDRESS)
    {
//		printf("Connected\n");
        connectionState=CS_CONNECTED;
        server=sa;
        sa = tcp->HasCompletedConnectionAttempt();
    }

    sa = tcp->HasFailedConnectionAttempt();
    while (sa!=UNASSIGNED_SYSTEM_ADDRESS)
    {
        //printf("Failed connected\n");
        CloseConnection();
        sa = tcp->HasFailedConnectionAttempt();
    }

    sa = tcp->HasLostConnection();
    while (sa!=UNASSIGNED_SYSTEM_ADDRESS)
    {
        //printf("Lost connection\n");
        CloseConnection();
        sa = tcp->HasLostConnection();
    }


    switch (connectionState)
    {
    case CS_NONE:
    {
        if (outgoingCommand.IsEmpty())
            return;

        //printf("Connecting\n");
        server = tcp->Connect(host, port, false);
        connectionState = CS_CONNECTING;
    }
    break;
    case CS_DISCONNECTING:
    {
        if (tcp->ReceiveHasPackets()==false)
        {
            if (incomingData.IsEmpty()==false)
            {
                results.Push(incomingData, _FILE_AND_LINE_ );
            }
            incomingData.Clear();
            tcp->CloseConnection(server);
            connectionState=CS_NONE;
        }
    }
    break;
    case CS_CONNECTING:
    {
    }
    break;
    case CS_CONNECTED:
    {
        //printf("Connected\n");
        if (outgoingCommand.IsEmpty())
        {
            //printf("Closed connection (nothing to do)\n");
            CloseConnection();
            return;
        }

#if OPEN_SSL_CLIENT_SUPPORT==1
        tcp->StartSSLClient(server);
#endif

        //printf("Sending request\n");
        currentProcessingCommand = outgoingCommand.Pop();
        RakString request;
        if (currentProcessingCommand.isPost)
        {
            request.Set("POST %s HTTP/1.0\r\n"
                        "Host: %s:%i\r\n"
                        "Content-Type: %s\r\n"
                        "Content-Length: %u\r\n"
                        "\r\n"
                        "%s",
                        currentProcessingCommand.remotePath.C_String(),
                        host.C_String(),
                        port,
                        currentProcessingCommand.contentType.C_String(),
                        (unsigned) currentProcessingCommand.data.GetLength(),
                        currentProcessingCommand.data.C_String());
        }
        else
        {
            // request.Set("GET %s\r\n", host.C_String());
            // http://www.jenkinssoftware.com/forum/index.php?topic=4601.0;topicseen
            request.Set("GET %s HTTP/1.0\r\n"
                        "Host: %s:%i\r\n"
                        "\r\n",
                        currentProcessingCommand.remotePath.C_String(),
                        host.C_String(),
                        port);
        }

        //	printf(request.C_String());
        //		request.URLEncode();
        tcp->Send(request.C_String(), (unsigned int) request.GetLength(), server,false);
        connectionState=CS_PROCESSING;
    }
    break;
    case CS_PROCESSING:
    {
    }
    }

//	if (connectionState==CS_PROCESSING && currentProcessingCommand.data.IsEmpty()==false)
//		outgoingCommand.PushAtHead(currentProcessingCommand);
}
Example #21
0
RakString RakString::FormatForPOST(RakString &uri, RakString &contentType, unsigned int port, RakString &body)
{
	RakString out;
	RakString host;
	RakString remotePath;
	RakNet::RakString header;

	uri.SplitURI(header, host, remotePath);
	if (host.IsEmpty() || remotePath.IsEmpty())
		return out;
	
	out.Set("POST %s HTTP/1.0\r\n"
		"Host: %s:%i\r\n"
		"Content-Type: %s\r\n"
		"Content-Length: %u\r\n"
		"\r\n"
		"%s",
		remotePath.C_String(),
		host.C_String(),
		port,
		contentType.C_String(),
		body.GetLength(),
		body.C_String());

	return out;
}
Example #22
0
void Rackspace2::Update(void)
{
	RakString stringTransmitted;
	RakString hostTransmitted;
	RakString responseReceived;
	Packet *packet;
	SystemAddress sa;
	// This is kind of crappy, but for TCP plugins, always do HasCompletedConnectionAttempt, then Receive(), then HasFailedConnectionAttempt(),HasLostConnection()
	sa = tcp->HasCompletedConnectionAttempt();
	if (sa!=UNASSIGNED_SYSTEM_ADDRESS)
	{
		//printf("Rackspace2 TCP: Connected to %s\n", sa.ToString());
//		serverAddress = sa;
	}
	for (packet = tcp->Receive(); packet; tcp->DeallocatePacket(packet), packet = tcp->Receive())
		;
	sa = tcp->HasFailedConnectionAttempt();
	//if (sa!=UNASSIGNED_SYSTEM_ADDRESS)
	//	printf("Rackspace2 TCP: Failed connection attempt to %s\n", sa.ToString());
	sa = tcp->HasLostConnection();
	if (sa!=UNASSIGNED_SYSTEM_ADDRESS)
	{
		//printf("Rackspace2 TCP: Lost connection to %s\n", sa.ToString());
		//		serverAddress=UNASSIGNED_SYSTEM_ADDRESS;
	}

	SystemAddress hostReceived;
	int contentOffset;
	if (httpConnection2->GetResponse(stringTransmitted, hostTransmitted, responseReceived, hostReceived, contentOffset))
	{
		if (responseReceived.IsEmpty()==false)
		{
			static FILE *fp = fopen("responses.txt", "wt");
			fprintf(fp, responseReceived.C_String());
			fprintf(fp, "\n");
			if (contentOffset==-1)
			{
				if (eventCallback)
					eventCallback->OnResponse(R2RC_NO_CONTENT, responseReceived, contentOffset);
			}
			else
			{
				json_error_t error;

				json_t *root = json_loads(strstr(responseReceived.C_String() + contentOffset, "{"), JSON_REJECT_DUPLICATES | JSON_DISABLE_EOF_CHECK, &error);
				if (!root)
				{
					if (eventCallback)
						eventCallback->OnResponse(R2RC_BAD_JSON, responseReceived, contentOffset);
				}
				else
				{
					void *iter = json_object_iter(root);
					const char *firstKey = json_object_iter_key(iter);
					if (stricmp(firstKey, "unauthorized")==0)
					{
						if (eventCallback)
							eventCallback->OnResponse(R2RC_UNAUTHORIZED, responseReceived, contentOffset);					
					}
					else if (stricmp(firstKey, "itemNotFound")==0)
					{
						if (eventCallback)
							eventCallback->OnResponse(R2RC_404_NOT_FOUND, responseReceived, contentOffset);					
					}
					else if (stricmp(firstKey, "access")==0)
					{
						json_t *valAuthToken = json_object_get(json_object_get(json_object_get(root, "access"), "token"), "id");
						strcpy(X_Auth_Token, json_string_value(valAuthToken));

						json_t *valAccountNumber = json_object_get(json_object_get(json_object_get(json_object_get(root, "access"), "token"), "tenant"), "id");
						cloudAccountNumber = atoi(json_string_value(valAccountNumber));	

						if (reexecuteLastRequestOnAuth)
						{
							reexecuteLastRequestOnAuth=false;

							json_t *root = json_loads(__addOpLast_dataAsStr.C_String(), 0, &error);							
							AddOperation(__addOpLast_URL, __addOpLast_isPost, root, true);							
						}
						else
						{
							if (eventCallback)
								eventCallback->OnResponse(R2RC_AUTHENTICATED, responseReceived, contentOffset);
						}

					}
					else if (stricmp(firstKey, "domains")==0)
					{
						if (eventCallback)
							eventCallback->OnResponse(R2RC_GOT_DOMAINS, responseReceived, contentOffset);
					}
					else if (stricmp(firstKey, "records")==0)
					{
						if (eventCallback)
							eventCallback->OnResponse(R2RC_GOT_RECORDS, responseReceived, contentOffset);
					}
					else if (stricmp(firstKey, "servers")==0)
					{
						if (eventCallback)
							eventCallback->OnResponse(R2RC_GOT_SERVERS, responseReceived, contentOffset);
					}
					else if (stricmp(firstKey, "images")==0)
					{
						if (eventCallback)
							eventCallback->OnResponse(R2RC_GOT_IMAGES, responseReceived, contentOffset);
					}
					else if (stricmp(firstKey, "message")==0)
					{
						const char *message = json_string_value(json_object_iter_value(iter));

						if (strcmp(message, "Invalid authentication token. Please renew.")==0)
						{
							// Sets reexecuteLastRequestOnAuth to true
							// After authenticate completes, will rerun the last run command
							Reauthenticate();
						}
						else
						{
							if (eventCallback)
								eventCallback->OnMessage(message, responseReceived, stringTransmitted, contentOffset);
						}
					}
					else
					{
						if (eventCallback)
							eventCallback->OnResponse(R2RC_UNKNOWN, responseReceived, contentOffset);
					}
				}

				json_decref(root);
			}
		}
		else
		{
			if (eventCallback)
				eventCallback->OnEmptyResponse(stringTransmitted);
		}
	}
}
void UDPProxyCoordinator::OnForwardingReplyFromServerToCoordinator(Packet *packet)
{
    RakNet::BitStream incomingBs(packet->data, packet->length, false);
    incomingBs.IgnoreBytes(2);
    SenderAndTargetAddress sata;
    incomingBs.Read(sata.senderClientAddress);
    incomingBs.Read(sata.targetClientAddress);
    bool objectExists;
    unsigned int index = forwardingRequestList.GetIndexFromKey(sata, &objectExists);
    if (objectExists==false)
    {
        // The guy disconnected before the request finished
        return;
    }
    ForwardingRequest *fw = forwardingRequestList[index];
    sata.senderClientGuid = fw->sata.senderClientGuid;
    sata.targetClientGuid = fw->sata.targetClientGuid;

    RakString serverPublicIp;
    incomingBs.Read(serverPublicIp);

    if (serverPublicIp.IsEmpty())
    {
        char serverIP[64];
        packet->systemAddress.ToString(false,serverIP);
        serverPublicIp=serverIP;
    }

    UDPForwarderResult success;
    unsigned char c;
    incomingBs.Read(c);
    success=(UDPForwarderResult)c;

    unsigned short forwardingPort;
    incomingBs.Read(forwardingPort);

    RakNet::BitStream outgoingBs;
    if (success==UDPFORWARDER_SUCCESS)
    {
        outgoingBs.Write((MessageID)ID_UDP_PROXY_GENERAL);
        outgoingBs.Write((MessageID)ID_UDP_PROXY_FORWARDING_SUCCEEDED);
        outgoingBs.Write(sata.senderClientAddress);
        outgoingBs.Write(sata.targetClientAddress);
        outgoingBs.Write(sata.targetClientGuid);
        outgoingBs.Write(serverPublicIp);
        outgoingBs.Write(forwardingPort);
        rakPeerInterface->Send(&outgoingBs, MEDIUM_PRIORITY, RELIABLE_ORDERED, 0, fw->requestingAddress, false);

        outgoingBs.Reset();
        outgoingBs.Write((MessageID)ID_UDP_PROXY_GENERAL);
        outgoingBs.Write((MessageID)ID_UDP_PROXY_FORWARDING_NOTIFICATION);
        outgoingBs.Write(sata.senderClientAddress);
        outgoingBs.Write(sata.targetClientAddress);
        outgoingBs.Write(sata.targetClientGuid);
        outgoingBs.Write(serverPublicIp);
        outgoingBs.Write(forwardingPort);
        rakPeerInterface->Send(&outgoingBs, MEDIUM_PRIORITY, RELIABLE_ORDERED, 0, sata.targetClientAddress, false);

        // 05/18/09 Keep the entry around for some time after success, so duplicates are reported if attempting forwarding from the target system before notification of success
        fw->timeoutAfterSuccess=RakNet::GetTimeMS()+fw->timeoutOnNoDataMS;
        // forwardingRequestList.RemoveAtIndex(index);
        // RakNet::OP_DELETE(fw,_FILE_AND_LINE_);

        return;
    }
    else if (success==UDPFORWARDER_NO_SOCKETS)
    {
        // Try next server
        TryNextServer(sata, fw);
    }
    else
    {
        RakAssert(success==UDPFORWARDER_FORWARDING_ALREADY_EXISTS);

        // Return in progress
        outgoingBs.Write((MessageID)ID_UDP_PROXY_GENERAL);
        outgoingBs.Write((MessageID)ID_UDP_PROXY_IN_PROGRESS);
        outgoingBs.Write(sata.senderClientAddress);
        outgoingBs.Write(sata.targetClientAddress);
        outgoingBs.Write(sata.targetClientGuid);
        outgoingBs.Write(serverPublicIp);
        outgoingBs.Write(forwardingPort);
        rakPeerInterface->Send(&outgoingBs, MEDIUM_PRIORITY, RELIABLE_ORDERED, 0, fw->requestingAddress, false);
        forwardingRequestList.RemoveAtIndex(index);
        RakNet::OP_DELETE(fw,_FILE_AND_LINE_);
    }
}
void AutopatcherClient::Update(void)
{
	processThreadCompletionMutex.Lock();
	if (processThreadCompletion)
	{
		processThreadCompletion=false;
		processThreadCompletionMutex.Unlock();

		fileListTransfer->RemoveReceiver(serverId);

		// If redownload list, process it
		if (redownloadList.fileList.Size())
		{
			RakNet::BitStream outBitStream;
			AutopatcherClientCallback *transferCallback;
			transferCallback = RakNet::OP_NEW<AutopatcherClientCallback>( _FILE_AND_LINE_ );
			strcpy(transferCallback->applicationDirectory, applicationDirectory);
			transferCallback->onFileCallback=userCB;
			transferCallback->client=this;
			setId = fileListTransfer->SetupReceive(transferCallback, true, serverId);

			// Ask for patches for the files in the list that are different from what we have.
			outBitStream.Write((unsigned char)ID_AUTOPATCHER_GET_PATCH);
			outBitStream.Write(setId);
			double lastUpdateData=0;
			outBitStream.Write(lastUpdateData);
			StringCompressor::Instance()->EncodeString(applicationName, 512, &outBitStream);
			redownloadList.Serialize(&outBitStream);
			SendUnified(&outBitStream, priority, RELIABLE_ORDERED, orderingChannel, serverId, false);
			redownloadList.Clear();
		}
		else if (copyAndRestartList.fileList.Size())
		{
			Packet *p = AllocatePacketUnified(1);
			p->bitSize=p->length*8;
			p->data[0]=ID_AUTOPATCHER_RESTART_APPLICATION;
			p->systemAddress=serverId;
			p->systemAddress.systemIndex=serverIdIndex;
			PushBackPacketUnified(p,false);

			FILE *fp;
			fp = fopen(copyOnRestartOut, "wt");
			RakAssert(fp);
			if (fp)
			{
				fprintf(fp, "#Sleep 1000\n");
				unsigned i;
				for (i=0; i < copyAndRestartList.fileList.Size(); i++)
				{
#ifdef _WIN32
					fprintf(fp, "del /q \"%s%s\"\n", applicationDirectory, copyAndRestartList.fileList[i].filename.C_String());
					RakString sourceFn = copyAndRestartList.fileList[i].filename;
					RakString bareFilename = sourceFn;
					bareFilename.StartAfterLastCharacter('/');
					fprintf(fp, "rename \"%s%s%s\" \"%s\"\n", applicationDirectory, bareFilename.C_String(), COPY_ON_RESTART_EXTENSION, copyAndRestartList.fileList[i].filename.C_String());
#else
					fprintf(fp, "rm -f \"%s%s\"\n", applicationDirectory, copyAndRestartList.fileList[i].filename.C_String());
					fprintf(fp, "mv \"%s%s%s\" \"%s\"\n", applicationDirectory, copyAndRestartList.fileList[i].filename.C_String(), COPY_ON_RESTART_EXTENSION, copyAndRestartList.fileList[i].filename.C_String());
#endif
				}
#ifdef _WIN32
				fprintf(fp, "#CreateProcess \"%s\"\n", restartExe);
#else
				fprintf(fp, "chmod +x \"%s\"\n", restartExe);
				fprintf(fp, "#CreateProcess \"%s\" &\n", restartExe);
#endif
				fprintf(fp, "#DeleteThisFile\n");
				fclose(fp);
			}
		}
		else
		{
			Packet *p = AllocatePacketUnified(1);
			p->bitSize=p->length*8;
			p->data[0]=ID_AUTOPATCHER_FINISHED;
			p->systemAddress=serverId;
			p->systemAddress.systemIndex=serverIdIndex;
			PushBackPacketUnified(p,false);
		}
	}
	else
	{
		processThreadCompletionMutex.Unlock();
	}
}
// Demonstrates how to use the RPC4 plugin
void InGameChat(RakNet::BitStream *userData, Packet *packet)
{
	RakString rs;
	userData->Read(rs);
	printf("%s\n", rs.C_String());
}
Example #26
0
int RakString::StrNCmp(const RakString &rhs, size_t num) const
{
	return strncmp(sharedString->c_str, rhs.C_String(), num);
}
Example #27
0
int RakString::StrICmp(const RakString &rhs) const
{
	return _stricmp(sharedString->c_str, rhs.C_String());
}
Example #28
0
bool RPC3::SendCallOrSignal(RakString uniqueIdentifier, char parameterCount, RakNet::BitStream *serializedParameters, bool isCall)
{	
	SystemAddress systemAddr;
//	unsigned int outerIndex;
//	unsigned int innerIndex;

	if (uniqueIdentifier.IsEmpty())
		return false;

	RakNet::BitStream bs;
	if (outgoingTimestamp!=0)
	{
		bs.Write((MessageID)ID_TIMESTAMP);
		bs.Write(outgoingTimestamp);
	}
	bs.Write((MessageID)ID_AUTO_RPC_CALL);
	bs.Write(parameterCount);
	if (outgoingNetworkID!=UNASSIGNED_NETWORK_ID && isCall)
	{
		bs.Write(true);
		bs.Write(outgoingNetworkID);
	}
	else
	{
		bs.Write(false);
	}
	bs.Write(isCall);
	// This is so the call SetWriteOffset works
	bs.AlignWriteToByteBoundary();
	BitSize_t writeOffset = bs.GetWriteOffset();
	if (outgoingBroadcast)
	{
		unsigned systemIndex;
		for (systemIndex=0; systemIndex < rakPeerInterface->GetMaximumNumberOfPeers(); systemIndex++)
		{
			systemAddr=rakPeerInterface->GetSystemAddressFromIndex(systemIndex);
			if (systemAddr!=UNASSIGNED_SYSTEM_ADDRESS && systemAddr!=outgoingSystemAddress)
			{
// 				if (GetRemoteFunctionIndex(systemAddr, uniqueIdentifier, &outerIndex, &innerIndex, isCall))
// 				{
// 					// Write a number to identify the function if possible, for faster lookup and less bandwidth
// 					bs.Write(true);
// 					if (isCall)
// 						bs.WriteCompressed(remoteFunctions[outerIndex]->operator [](innerIndex).functionIndex);
// 					else
// 						bs.WriteCompressed(remoteSlots[outerIndex]->operator [](innerIndex).functionIndex);
// 				}
// 				else
// 				{
// 					bs.Write(false);
					stringCompressor->EncodeString(uniqueIdentifier, 512, &bs, 0);
//				}

				bs.WriteCompressed(serializedParameters->GetNumberOfBitsUsed());
				bs.WriteAlignedBytes((const unsigned char*) serializedParameters->GetData(), serializedParameters->GetNumberOfBytesUsed());
				SendUnified(&bs, outgoingPriority, outgoingReliability, outgoingOrderingChannel, systemAddr, false);

				// Start writing again after ID_AUTO_RPC_CALL
				bs.SetWriteOffset(writeOffset);
			}
		}
	}
	else
	{
		systemAddr = outgoingSystemAddress;
		if (systemAddr!=UNASSIGNED_SYSTEM_ADDRESS)
		{
// 			if (GetRemoteFunctionIndex(systemAddr, uniqueIdentifier, &outerIndex, &innerIndex, isCall))
// 			{
// 				// Write a number to identify the function if possible, for faster lookup and less bandwidth
// 				bs.Write(true);
// 				if (isCall)
// 					bs.WriteCompressed(remoteFunctions[outerIndex]->operator [](innerIndex).functionIndex);
// 				else
// 					bs.WriteCompressed(remoteSlots[outerIndex]->operator [](innerIndex).functionIndex);
// 			}
// 			else
// 			{
// 				bs.Write(false);
				stringCompressor->EncodeString(uniqueIdentifier, 512, &bs, 0);
//			}

			bs.WriteCompressed(serializedParameters->GetNumberOfBitsUsed());
			bs.WriteAlignedBytes((const unsigned char*) serializedParameters->GetData(), serializedParameters->GetNumberOfBytesUsed());
			SendUnified(&bs, outgoingPriority, outgoingReliability, outgoingOrderingChannel, systemAddr, false);
		}
		else
			return false;
	}
	return true;
}
int main()
{
	FullyConnectedMesh2 fcm2;
	ConnectionGraph2 cg2;
	rakPeer=RakNet::RakPeerInterface::GetInstance();
	rakPeer->AttachPlugin(&fcm2);
	rakPeer->AttachPlugin(&cg2);
	fcm2.SetAutoparticipateConnections(true);
	RakNet::SocketDescriptor sd;
	sd.socketFamily=AF_INET; // Only IPV4 supports broadcast on 255.255.255.255
	sd.port=60000;
	while (IRNS2_Berkley::IsPortInUse(sd.port, sd.hostAddress, sd.socketFamily, SOCK_DGRAM)==true)
		sd.port++;
	StartupResult sr = rakPeer->Startup(8,&sd,1);
	RakAssert(sr==RAKNET_STARTED);
	rakPeer->SetMaximumIncomingConnections(8);
	rakPeer->SetTimeoutTime(1000,RakNet::UNASSIGNED_SYSTEM_ADDRESS);
	printf("Our guid is %s\n", rakPeer->GetGuidFromSystemAddress(RakNet::UNASSIGNED_SYSTEM_ADDRESS).ToString());
	printf("Started on %s\n", rakPeer->GetMyBoundAddress().ToString(true));
	BitStream contextBs;
	contextBs.Write(RakString("Our guid is %s\n", rakPeer->GetGuidFromSystemAddress(RakNet::UNASSIGNED_SYSTEM_ADDRESS).ToString()));
	fcm2.SetMyContext(&contextBs);

//	PacketLogger packetLogger;
//	rakPeer->AttachPlugin(&packetLogger);
//	packetLogger.SetLogDirectMessages(false);

	bool quit=false;
	RakNet::Packet *packet;
	char ch;
	while (!quit)
	{
		for (packet = rakPeer->Receive(); packet; rakPeer->DeallocatePacket(packet), packet = rakPeer->Receive())
		{
			switch (packet->data[0])
			{
			case ID_DISCONNECTION_NOTIFICATION:
				// Connection lost normally
				printf("ID_DISCONNECTION_NOTIFICATION\n");
				break;


			case ID_NEW_INCOMING_CONNECTION:
				// Somebody connected.  We have their IP now
				printf("ID_NEW_INCOMING_CONNECTION from %s. guid=%s.\n", packet->systemAddress.ToString(true), packet->guid.ToString());
				break;

			case ID_CONNECTION_REQUEST_ACCEPTED:
				// Somebody connected.  We have their IP now
				printf("ID_CONNECTION_REQUEST_ACCEPTED from %s. guid=%s.\n", packet->systemAddress.ToString(true), packet->guid.ToString());
				break;


			case ID_CONNECTION_LOST:
				// Couldn't deliver a reliable packet - i.e. the other system was abnormally
				// terminated
				printf("ID_CONNECTION_LOST\n");
				break;

			case ID_ADVERTISE_SYSTEM:
				if (packet->guid!=rakPeer->GetMyGUID())
					rakPeer->Connect(packet->systemAddress.ToString(false), packet->systemAddress.GetPort(),0,0);
				break;

			case ID_FCM2_NEW_HOST:
				{
				if (packet->guid==rakPeer->GetMyGUID())
					printf("Got new host (ourselves)");
				else
					printf("Got new host %s, GUID=%s", packet->systemAddress.ToString(true), packet->guid.ToString());
					RakNet::BitStream bs(packet->data,packet->length,false);
					bs.IgnoreBytes(1);
					RakNetGUID oldHost;
					bs.Read(oldHost);
					// If oldHost is different then the current host, then we lost connection to the host
					if (oldHost!=UNASSIGNED_RAKNET_GUID)
						printf(". Oldhost Guid=%s\n", oldHost.ToString());
					else
						printf(". (First reported host)\n");
				}
				break;

// 			case ID_REMOTE_NEW_INCOMING_CONNECTION:
// 				{
// 					uint32_t count;
// 					RakNet::BitStream bsIn(packet->data, packet->length,false);
// 					bsIn.IgnoreBytes(1);
// 					bsIn.Read(count);
// 					SystemAddress sa;
// 					RakNetGUID guid;
// 					printf("ID_REMOTE_NEW_INCOMING_CONNECTION from %s\n", packet->systemAddress.ToString(true));
// 					for (uint32_t i=0; i < count; i++)
// 					{
// 						bsIn.Read(sa);
// 						bsIn.Read(guid);
// 
// 						printf("%s ", sa.ToString(true));
// 					}
// 					printf("\n");
// 				}
			}
		}

		if (kbhit())
		{
			ch=getch();
			if (ch==' ')
			{

				DataStructures::List<RakNetGUID> participantList;
				fcm2.GetParticipantList(participantList);
				printf("%i participants\n", participantList.Size());
				for (int i=0; i < participantList.Size(); i++)
				{
					BitStream userContext;
					fcm2.GetParticipantContext(participantList[i], &userContext);
					RakString str;
					userContext.Read(str);
					printf("%i. %s: %s", i+1, participantList[i].ToString(), str.C_String());
				}
			}
			if (ch=='q' || ch=='Q')
			{
				printf("Quitting.\n");
				quit=true;
			}
		}

		RakSleep(30);
		for (int i=0; i < 32; i++)
		{
			if (rakPeer->GetInternalID(RakNet::UNASSIGNED_SYSTEM_ADDRESS,0).GetPort()!=60000+i)
				rakPeer->AdvertiseSystem("255.255.255.255", 60000+i, 0,0,0);
		}
	}

	RakNet::RakPeerInterface::DestroyInstance(rakPeer);
	return 0;
}
int main(void)
{
	printf("Demonstrates networking elements for a P2P game on the PC, self-released,\nwith player hosted game servers\n");
	printf("Difficulty: Advanced\n\n");

	// ---------------------------------------------------------------------------------------------------------------------
	// Allocate plugins. See declaration in this file for description of each
	// ---------------------------------------------------------------------------------------------------------------------
	rakPeer=RakNet::RakPeerInterface::GetInstance();
	teamManager=TeamManager::GetInstance();
	fullyConnectedMesh2=FullyConnectedMesh2::GetInstance();
	networkIDManager = NetworkIDManager::GetInstance();
	cloudClient = CloudClient::GetInstance();
	natPunchthroughClient = NatPunchthroughClient::GetInstance();
#ifdef NAT_TYPE_DETECTION_SERVER
	natTypeDetectionClient = NatTypeDetectionClient::GetInstance();
#endif
	rpc4 = RPC4::GetInstance();
	readyEvent = ReadyEvent::GetInstance();
	replicaManager3=new SampleRM3;

	// ---------------------------------------------------------------------------------------------------------------------
	// Attach plugins
	// ---------------------------------------------------------------------------------------------------------------------
	rakPeer->AttachPlugin(fullyConnectedMesh2);
	rakPeer->AttachPlugin(teamManager);
	rakPeer->AttachPlugin(cloudClient);
	rakPeer->AttachPlugin(natPunchthroughClient);
#ifdef NAT_TYPE_DETECTION_SERVER
	rakPeer->AttachPlugin(natTypeDetectionClient);
#endif
	rakPeer->AttachPlugin(rpc4);
	rakPeer->AttachPlugin(readyEvent);
	rakPeer->AttachPlugin(replicaManager3);

	// ---------------------------------------------------------------------------------------------------------------------
	// Setup plugins: Disable automatically adding new connections. Allocate initial objects and register for replication
	// ---------------------------------------------------------------------------------------------------------------------
	// Allocate a world instance to be used for team operations
	teamManager->AddWorld(0);
	// Do not automatically count new connections
	teamManager->SetAutoManageConnections(false);
	
	// New connections do not count until after login.
	fullyConnectedMesh2->SetAutoparticipateConnections(false);	
		
	// Tell ReplicaManager3 which networkIDManager to use for object lookup, used for automatic serialization
	replicaManager3->SetNetworkIDManager(networkIDManager);
	// Do not automatically count new connections, but do drop lost connections automatically
	replicaManager3->SetAutoManageConnections(false,true);
	
	// Reference static game objects that always exist
	game = new Game;
	game->SetNetworkIDManager(networkIDManager);
	game->SetNetworkID(0);
	replicaManager3->Reference(game);

	// Setup my own user
	User *user = new User;
	user->SetNetworkIDManager(networkIDManager);
	user->userName = rakPeer->GetMyGUID().ToString();
	// Inform TeamManager of my user's team member info
	teamManager->GetWorldAtIndex(0)->ReferenceTeamMember(&user->tmTeamMember,user->GetNetworkID());

	// ---------------------------------------------------------------------------------------------------------------------
	// Startup RakNet on first available port
	// ---------------------------------------------------------------------------------------------------------------------
	RakNet::SocketDescriptor sd;
	sd.socketFamily=AF_INET; // Only IPV4 supports broadcast on 255.255.255.255
	sd.port=0;
	StartupResult sr = rakPeer->Startup(8,&sd,1);
	RakAssert(sr==RAKNET_STARTED);
	rakPeer->SetMaximumIncomingConnections(8);
	rakPeer->SetTimeoutTime(30000,RakNet::UNASSIGNED_SYSTEM_ADDRESS);
	printf("Our guid is %s\n", rakPeer->GetGuidFromSystemAddress(RakNet::UNASSIGNED_SYSTEM_ADDRESS).ToString());
	printf("Started on %s\n", rakPeer->GetMyBoundAddress().ToString(true));
	
	// Connect to master server
	game->EnterPhase(Game::CONNECTING_TO_SERVER);

	// ---------------------------------------------------------------------------------------------------------------------
	// Read packets loop
	// ---------------------------------------------------------------------------------------------------------------------
	char ch;
	Packet *packet;
	while (game->phase!=Game::EXIT_SAMPLE)
	{
		for (packet = rakPeer->Receive(); packet; rakPeer->DeallocatePacket(packet), packet = rakPeer->Receive())
		{
			switch (packet->data[0])
			{
			case ID_NEW_INCOMING_CONNECTION:
				{
					printf("ID_NEW_INCOMING_CONNECTION from %s. guid=%s.\n", packet->systemAddress.ToString(true), packet->guid.ToString());
				}
				break;
			case ID_CONNECTION_REQUEST_ACCEPTED:
				{
					printf("ID_CONNECTION_REQUEST_ACCEPTED from %s,guid=%s\n", packet->systemAddress.ToString(true), packet->guid.ToString());

					if (game->phase==Game::CONNECTING_TO_SERVER)
					{
						game->masterServerAddress=packet->systemAddress;
						game->masterServerGuid=packet->guid;

						// ---------------------------------------------------------------------------------------------------------------------
						// PC self-hosted servers only: Use master server to determine NAT type. Attempt to open router if needed.
						// ---------------------------------------------------------------------------------------------------------------------
						if (NAT_TYPE_DETECTION_SERVER)
						{
							game->EnterPhase(Game::DETERMINE_NAT_TYPE);
						}
						else
						{
							OpenUPNP();
							game->EnterPhase(Game::SEARCH_FOR_GAMES);
						}
					}
					else if (game->phase==Game::CONNECTING_TO_GAME_HOST)
					{
						printf("Asking host to join session...\n");

						// So time in single player does not count towards which system has been running multiplayer the longest
						fullyConnectedMesh2->ResetHostCalculation();

						// Custom message to ask to join the game
						// We first connect to the game host, and the game host is responsible for calling StartVerifiedJoin() for us to join the session
						BitStream bsOut;
						bsOut.Write((MessageID)ID_USER_PACKET_ENUM);
						rakPeer->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->guid,false);
					}
				}
				break;
			case ID_CONNECTION_LOST:
			case ID_DISCONNECTION_NOTIFICATION:
				if (game->phase==Game::DETERMINE_NAT_TYPE)
				{
					printf("Lost connection during NAT type detection. Reason %s. Retrying...\n", PacketLogger::BaseIDTOString(packet->data[0]));
					game->EnterPhase(Game::CONNECTING_TO_SERVER);
				}
				else if (game->phase==Game::NAT_PUNCH_TO_GAME_HOST)
				{
					printf("Lost connection during NAT punch to game host. Reason %s.\n", PacketLogger::BaseIDTOString(packet->data[0]));
					game->EnterPhase(Game::SEARCH_FOR_GAMES);
				}
				else
				{
					if (packet->guid==game->masterServerGuid)
					{
						printf("Server connection lost. Reason %s.\nGame session is no longer searchable.\n", PacketLogger::BaseIDTOString(packet->data[0]));
					}
					else
					{
						printf("Peer connection lost. Reason %s.\n", PacketLogger::BaseIDTOString(packet->data[0]));
					}
				}
				break;

			case ID_ALREADY_CONNECTED:
				printf("ID_ALREADY_CONNECTED with guid %"PRINTF_64_BIT_MODIFIER"u\n", packet->guid);
				break;

			case ID_INVALID_PASSWORD:
			case ID_NO_FREE_INCOMING_CONNECTIONS:
			case ID_CONNECTION_ATTEMPT_FAILED:
			case ID_CONNECTION_BANNED:
			case ID_IP_RECENTLY_CONNECTED:
			case ID_INCOMPATIBLE_PROTOCOL_VERSION:
				// Note: Failing to connect to another system does not automatically mean we cannot join a session, since that system may be disconnecting from the host simultaneously
				// FullyConnectedMesh2::StartVerifiedJoin() internally handles success or failure and notifies the client through ID_FCM2_VERIFIED_JOIN_FAILED if needed.
				printf("Failed to connect to %s. Reason %s\n", packet->systemAddress.ToString(true), PacketLogger::BaseIDTOString(packet->data[0]));

				if (game->phase==Game::CONNECTING_TO_SERVER)
					game->EnterPhase(Game::EXIT_SAMPLE);
				break;
				
			case ID_FCM2_NEW_HOST:
				{
					RakNet::BitStream bs(packet->data,packet->length,false);
					bs.IgnoreBytes(1);
					RakNetGUID oldHost;
					bs.Read(oldHost);

					if (packet->guid==rakPeer->GetMyGUID())
					{
						if (oldHost!=UNASSIGNED_RAKNET_GUID)
						{
							PostRoomToCloud();
							printf("ID_FCM2_NEW_HOST: Taking over as host from the old host.\nNew options:\n");
						}
						else
						{
							// Room not hosted if we become host the first time since this was done in CreateRoom() already
							printf("ID_FCM2_NEW_HOST: We have become host for the first time. New options:\n");
						}

						printf("(L)ock and unlock game\n");
					}
					else
					{
						if (oldHost!=UNASSIGNED_RAKNET_GUID)
							printf("ID_FCM2_NEW_HOST: A new system %s has become host, GUID=%s\n", packet->systemAddress.ToString(true), packet->guid.ToString());
						else
							printf("ID_FCM2_NEW_HOST: System %s is host, GUID=%s\n", packet->systemAddress.ToString(true), packet->guid.ToString());
					}

					if (oldHost==UNASSIGNED_RAKNET_GUID)
					{
						// First time calculated host. Add existing connections to ReplicaManager3
						DataStructures::List<RakNetGUID> participantList;
						fullyConnectedMesh2->GetParticipantList(participantList);
						for (unsigned int i=0; i < participantList.Size(); i++)
							RegisterGameParticipant(participantList[i]);

						// Reference previously created replicated objects, which cannot be serialized until host is known the first time
						if (packet->guid==rakPeer->GetMyGUID())
						{
							// As host, reference the teams we created
							for (unsigned int i=0; i < game->teams.Size(); i++)
								replicaManager3->Reference(game->teams[i]);
						}

						// Reference the user we created (host or not)
						for (unsigned int i=0; i < game->users.Size(); i++)
							replicaManager3->Reference(game->users[i]);
					}
				}
				break;
			case ID_TEAM_BALANCER_TEAM_ASSIGNED:
				{
					printf("ID_TEAM_BALANCER_TEAM_ASSIGNED for ");
					TM_World *world;
					TM_TeamMember *teamMember;
					teamManager->DecodeTeamAssigned(packet, &world, &teamMember);
					printf("worldId=%i teamMember=%s", world->GetWorldId(), ((User*)teamMember->GetOwner())->userName.C_String());
					if (teamMember->GetCurrentTeam()==0)
						printf(" not on team\n");
					else
						printf(" on team %s\n", ((Team*)(teamMember->GetCurrentTeam()->GetOwner()))->teamName.C_String());
				}
				break;
			case ID_TEAM_BALANCER_REQUESTED_TEAM_FULL:
				{
					printf("ID_TEAM_BALANCER_REQUESTED_TEAM_FULL\n");
				}
				break;
			case ID_TEAM_BALANCER_REQUESTED_TEAM_LOCKED:
				{
					printf("ID_TEAM_BALANCER_REQUESTED_TEAM_LOCKED\n");
				}
				break;
			case ID_TEAM_BALANCER_TEAM_REQUESTED_CANCELLED:
				{
					printf("ID_TEAM_BALANCER_TEAM_REQUESTED_CANCELLED\n");
				}
				break;
			case ID_NAT_TARGET_NOT_CONNECTED:
			case ID_NAT_TARGET_UNRESPONSIVE:
			case ID_NAT_CONNECTION_TO_TARGET_LOST:
			case ID_NAT_PUNCHTHROUGH_FAILED:
				{
					// As with connection failed, this does not automatically mean we cannot join the session
					// We only fail on ID_FCM2_VERIFIED_JOIN_FAILED
					printf("NAT punch to %s failed. Reason %s\n", packet->guid.ToString(), PacketLogger::BaseIDTOString(packet->data[0]));

					if (game->phase==Game::NAT_PUNCH_TO_GAME_HOST)
						game->EnterPhase(Game::SEARCH_FOR_GAMES);
				}

			case ID_NAT_ALREADY_IN_PROGRESS:
				// Can ignore this
				break;

			case ID_NAT_PUNCHTHROUGH_SUCCEEDED:
				{
					if (game->phase==Game::NAT_PUNCH_TO_GAME_HOST || game->phase==Game::VERIFIED_JOIN)
					{
						// Connect to the session host
						ConnectionAttemptResult car = rakPeer->Connect(packet->systemAddress.ToString(false), packet->systemAddress.GetPort(), 0, 0);
						if (car!=RakNet::CONNECTION_ATTEMPT_STARTED)
						{
							printf("Failed connect call to %s. Code=%i\n", packet->systemAddress.ToString(false), car);
							game->EnterPhase(Game::SEARCH_FOR_GAMES);
						}
						else
						{
							if (game->phase==Game::NAT_PUNCH_TO_GAME_HOST)
							{
								printf("NAT punch completed. Connecting to %s (game host)...\n", packet->systemAddress.ToString(true));
								game->EnterPhase(Game::CONNECTING_TO_GAME_HOST);
							}
							else
							{
								printf("NAT punch completed. Connecting to %s (game client)...\n", packet->systemAddress.ToString(true));
							}
						}
					}
				}
				break;


			case ID_CLOUD_GET_RESPONSE:
				{
					cloudClient->DeallocateWithDefaultAllocator(&cloudQueryResult);
					cloudClient->OnGetReponse(&cloudQueryResult, packet);
					unsigned int rowIndex;

					for (rowIndex=0; rowIndex < cloudQueryResult.rowsReturned.Size(); rowIndex++)
					{
						RakNet::CloudQueryRow *row = cloudQueryResult.rowsReturned[rowIndex];
						printf("%i. ", rowIndex);
						PrintRow(row);
					}

					printf("(J)oin room\n");
					printf("(C)reate room\n");
					printf("(S)earch rooms\n");
				}
				break;
			
			case ID_NAT_TYPE_DETECTION_RESULT:
				{
					game->myNatType = (RakNet::NATTypeDetectionResult) packet->data[1];
					printf("NAT Type is %s (%s)\n", NATTypeDetectionResultToString(game->myNatType), NATTypeDetectionResultToStringFriendly(game->myNatType));

					if (game->myNatType!=RakNet::NAT_TYPE_NONE)
					{
						OpenUPNP();
					}

					if (game->myNatType==RakNet::NAT_TYPE_PORT_RESTRICTED || game->myNatType==RakNet::NAT_TYPE_SYMMETRIC)
					{
						printf("Note: Your router must support UPNP or have the user manually forward ports.\n");
						printf("Otherwise NATPunchthrough may not always succeed.\n");
					}

					game->EnterPhase(Game::SEARCH_FOR_GAMES);
				}
				break;
				
			case ID_READY_EVENT_ALL_SET:
				printf("Got ID_READY_EVENT_ALL_SET from %s\n", packet->systemAddress.ToString(true));
				printf("All users ready.\n");
				if (fullyConnectedMesh2->IsConnectedHost())
					printf("New options:\n(B)egin gameplay\n");
				break;

			case ID_READY_EVENT_SET:
				printf("Got ID_READY_EVENT_SET from %s\n", packet->systemAddress.ToString(true));
				break;

			case ID_READY_EVENT_UNSET:
				printf("Got ID_READY_EVENT_UNSET from %s\n", packet->systemAddress.ToString(true));
				break;

			// ID_USER_PACKET_ENUM is used by this sample as a custom message to ask to join a game
			case ID_USER_PACKET_ENUM:
				if (game->phase > Game::SEARCH_FOR_GAMES)
				{
					printf("Got request from client to join session.\nExecuting StartVerifiedJoin()\n");
					fullyConnectedMesh2->StartVerifiedJoin(packet->guid);
				}
				else
				{
					BitStream bsOut;
					bsOut.Write((MessageID)(ID_USER_PACKET_ENUM+1));
					rakPeer->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->guid,false);
				}
				break;
			// ID_USER_PACKET_ENUM+1 is used by this sample as a custom message to reject a join game request
			// Requests may also be later rejected through FullyConnectedMesh2::RespondOnVerifiedJoinCapable() to send ID_FCM2_VERIFIED_JOIN_REJECTED
			case (ID_USER_PACKET_ENUM+1):
				printf("Join request denied\n");
				game->EnterPhase(Game::SEARCH_FOR_GAMES);
				break;
			case ID_FCM2_VERIFIED_JOIN_START:
				{
					game->EnterPhase(Game::VERIFIED_JOIN);

					// This message means the session host sent us a list of systems in the session
					// Once we connect to, or fail to connect to, each of these systems we will get ID_FCM2_VERIFIED_JOIN_FAILED, ID_FCM2_VERIFIED_JOIN_ACCEPTED, or ID_FCM2_VERIFIED_JOIN_REJECTED
					printf("Host sent us system list. Doing NAT punch to each system...\n");
					DataStructures::List<SystemAddress> addresses;
					DataStructures::List<RakNetGUID> guids;
					fullyConnectedMesh2->GetVerifiedJoinRequiredProcessingList(packet->guid, addresses, guids);
					for (unsigned int i=0; i < guids.Size(); i++)
						natPunchthroughClient->OpenNAT(guids[i], game->masterServerAddress);
				}
				break;

			case ID_FCM2_VERIFIED_JOIN_CAPABLE:
				printf("Client is capable of joining FullyConnectedMesh2.\n");
				if (game->lockGame)
				{
					RakNet::BitStream bsOut;
					bsOut.Write("Game is locked");
					fullyConnectedMesh2->RespondOnVerifiedJoinCapable(packet, false, &bsOut);
				}
				else
					fullyConnectedMesh2->RespondOnVerifiedJoinCapable(packet, true, 0);
				break;

			case ID_FCM2_VERIFIED_JOIN_ACCEPTED:
				{
					DataStructures::List<RakNetGUID> systemsAccepted;
					bool thisSystemAccepted;
					fullyConnectedMesh2->GetVerifiedJoinAcceptedAdditionalData(packet, &thisSystemAccepted, systemsAccepted, 0);
					if (thisSystemAccepted)
						printf("Game join request accepted\n");
					else
						printf("System %s joined the mesh\n", systemsAccepted[0].ToString());

					// Add the new participant to the game if we already know who the host is. Otherwise do this
					// once ID_FCM2_NEW_HOST arrives
					if (fullyConnectedMesh2->GetConnectedHost()!=UNASSIGNED_RAKNET_GUID)
					{
						// FullyConnectedMesh2 already called AddParticipant() for each accepted system
						// Still need to add those systems to the other plugins though
						for (unsigned int i=0; i < systemsAccepted.Size(); i++)
							RegisterGameParticipant(systemsAccepted[i]);

						if (thisSystemAccepted)
							game->EnterPhase(Game::IN_LOBBY_WITH_HOST);
					}
					else
					{
						if (thisSystemAccepted)
							game->EnterPhase(Game::IN_LOBBY_WAITING_FOR_HOST);
					}

					printf("(E)xit room\n");
				}
				break;

			case ID_FCM2_VERIFIED_JOIN_REJECTED:
				{
					BitStream additionalData;
					fullyConnectedMesh2->GetVerifiedJoinRejectedAdditionalData(packet, &additionalData);
					RakString reason;
					additionalData.Read(reason);
					printf("Join rejected. Reason=%s\n", reason.C_String());
					rakPeer->CloseConnection(packet->guid, true);
					game->EnterPhase(Game::SEARCH_FOR_GAMES);
					break;
				}

			case ID_REPLICA_MANAGER_DOWNLOAD_COMPLETE:
				{
					if (replicaManager3->GetAllConnectionDownloadsCompleted()==true)
					{
						printf("Completed all remote downloads\n");

						if (game->gameInLobby)
							game->EnterPhase(Game::IN_LOBBY_WITH_HOST);
						else
							game->EnterPhase(Game::IN_GAME);
					}

					break;
				}
			}
		}

		if (kbhit())
		{
			ch=getch();

			if (game->phase==Game::SEARCH_FOR_GAMES)
			{
				if (ch=='c' || ch=='C')
				{
					CreateRoom();
				}
				if (ch=='s' || ch=='S')
				{
					game->SearchForGames();
				}
				else if (ch=='j' || ch=='J')
				{
					// Join room
					if (cloudQueryResult.rowsReturned.Size()==0)
					{
						printf("No rooms to join.\n");
					}
					else
					{
						int index;
						if (cloudQueryResult.rowsReturned.Size()>1)
						{
							printf("Enter index of room to join.\n");
							char indexstr[64];
							Gets(indexstr,64);
							index = atoi(indexstr);
						}
						else
						{
							index = 0;
						}

						if (index < 0 || (unsigned int) index >= cloudQueryResult.rowsReturned.Size())
						{
							printf("Index out of range.\n");
						}
						else
						{
							CloudQueryRow *row = cloudQueryResult.rowsReturned[index];
							// Connect to the session host using NATPunchthrough
							natPunchthroughClient->OpenNAT(row->clientGUID, game->masterServerAddress);
							game->EnterPhase(Game::NAT_PUNCH_TO_GAME_HOST);
						}
					}
				}
			}
			else
			{
				if (game->phase==Game::IN_GAME)
				{
					if (ch=='c' || ch=='C')
					{
						DataStructures::List<RakNetGUID> participantList;
						fullyConnectedMesh2->GetParticipantList(participantList);

						if (participantList.Size()>0)
						{
							printf("Enter in-game chat message: ");
							char str[256];
							Gets(str, 256);
							RakString rs;
							// Don't use RakString constructor to assign str, or will process % escape characters
							rs=str;
							BitStream bsOut;
							bsOut.Write(rs);
							for (unsigned int i=0; i < participantList.Size(); i++)
								rpc4->Signal("InGameChat", &bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, participantList[i], false, false);
						}
					}
				}

				if (ch=='1')
				{
					user->tmTeamMember.RequestTeamSwitch(&game->teams[0]->tmTeam, 0);
				}
				else if (ch=='2')
				{
					user->tmTeamMember.RequestTeamSwitch(&game->teams[1]->tmTeam, 0);
				}
				else if (ch=='r' || ch=='R')
				{
					if (readyEvent->SetEvent(0, true))
						printf("We are ready to start.\n");
				}
				else if (ch=='u' || ch=='U')
				{
					if (readyEvent->SetEvent(0, false))
						printf("We are no longer ready to start.\n");
				}
				else if (ch=='l' || ch=='L')
				{
					if (fullyConnectedMesh2->IsConnectedHost())
					{
						if (game->lockGame)
						{
							printf("Game is no longer locked\n");
							game->lockGame=false;
						}
						else
						{
							printf("Game is now locked\n");
							game->lockGame=true;
						}
					}
				}
				else if (ch=='b' || ch=='B')
				{
					if (fullyConnectedMesh2->IsConnectedHost())
					{
						if (game->gameInLobby)
						{
							readyEvent->ForceCompletion(0);
							game->gameInLobby=false;
							game->EnterPhase(Game::IN_GAME);
						}
						else
						{
							readyEvent->DeleteEvent(0);
							printf("Game ended, and now in lobby\n");
							game->gameInLobby=true;
							game->EnterPhase(Game::IN_LOBBY_WITH_HOST);
						}
					}
				}
				else if (ch=='e' || ch=='E')
				{
					// Disconnect from FullyConnectedMesh2 participants
					DataStructures::List<RakNetGUID> participantList;
					fullyConnectedMesh2->GetParticipantList(participantList);
					for (unsigned int i=0; i < participantList.Size(); i++)
						rakPeer->CloseConnection(participantList[i], true);

					// User instances are deleted automatically from ReplicaManager3.
					// However, teams are not deleted since the Team class can migrate between systems. So delete Team instances manually
					while (game->teams.Size())
						delete game->teams[game->teams.Size()-1];

					// If we were the host, no longer list this session
					// The new host will call PostRoomToCloud to reupload under a new IP address on ID_FCM2_NEW_HOST
					ReleaseRoomFromCloud();

					// Clear out state data from plugins
					fullyConnectedMesh2->Clear();
					readyEvent->DeleteEvent(0);
					replicaManager3->Clear(false);
					replicaManager3->Reference(game);

					game->Reset();
					game->EnterPhase(Game::SEARCH_FOR_GAMES);
				}
				else if (ch=='q' || ch=='Q')
				{
					printf("Quitting.\n");
					// Disconnecting from the master server automatically releases from cloud
					game->EnterPhase(Game::EXIT_SAMPLE);
				}
			}
		}

		RakSleep(30);
	}

	rakPeer->Shutdown(100);

	while (game->teams.Size())
		delete game->teams[game->teams.Size()-1];
	while (game->users.Size())
		delete game->users[game->users.Size()-1];
	delete game;

	cloudClient->DeallocateWithDefaultAllocator(&cloudQueryResult);
	RakPeerInterface::DestroyInstance(rakPeer);
	TeamManager::DestroyInstance(teamManager);
	FullyConnectedMesh2::DestroyInstance(fullyConnectedMesh2);
	cloudClient->DeallocateWithDefaultAllocator(&cloudQueryResult);
	CloudClient::DestroyInstance(cloudClient);
	NatPunchthroughClient::DestroyInstance(natPunchthroughClient);
	NatTypeDetectionClient::DestroyInstance(natTypeDetectionClient);
	RPC4::DestroyInstance(rpc4);
	ReadyEvent::DestroyInstance(readyEvent);
	delete replicaManager3;
	NetworkIDManager::DestroyInstance(networkIDManager);

	return 1;
}