Exemple #1
0
void Network::ReqClientDataSend()
{
	RakNet::BitStream outBuffer;
	outBuffer.Write( (unsigned char)MessageType::C2S_CLIENT_DATA );
	outBuffer.Write( _myUserNo );

	//
	DataList & dataLIst = Network::GetInstance().GetDataList( _myUserNo );

	//
	int count = dataLIst.size();
	outBuffer.Write( count );

	for( int num = 0; num < count; num++ )
	{
		PacketData data = dataLIst[ num ];
		outBuffer.Write( data );
	}

	RakPeerInterface * client = Network::GetInstance().GetClient();
	if( client )
	{
		client->Send(&outBuffer, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true);
	}
}
int lraknet_SetUnreliableTimeout(lua_State* L)
{
    RakPeerInterface* peer = __self(L);
    lua_Integer timeout = luaL_checkinteger(L, 2);
    peer->SetUnreliableTimeout(timeout);
    return 0;
}
int lraknet_Receive(lua_State* L)
{
    RakPeerInterface* peer = __self(L);

    Packet* packet = peer->Receive();

    lua_pushlstring(L, (const char*)packet->data, packet->length);

    return 1;
}
Exemple #4
0
void Network::ReqGetUserInfoSend()
{
	RakNet::BitStream outBuffer;
	outBuffer.Write( (unsigned char)MessageType::H2S_GET_USERINFO_LIST );

	RakPeerInterface * client = Network::GetInstance().GetClient();
	if( client )
	{
		client->Send(&outBuffer, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true);
	}
}
int lraknet_SetTimeoutTime(lua_State* L)
{
    RakPeerInterface* peer = __self(L);
    RakNet::TimeMS timeMS = luaL_checknumber(L, 2);

    const char* systemAddress = luaL_checkstring(L, 3);
    if (!systemAddress) {
        peer->SetTimeoutTime(timeMS, UNASSIGNED_SYSTEM_ADDRESS);
    } else {
        peer->SetTimeoutTime(timeMS, SystemAddress(systemAddress));
    }
    return 0;
}
Exemple #6
0
void Network::ReqLoginSend( std::string id, std::string pass )
{
	RakNet::BitStream outBuffer;
	outBuffer.Write( (unsigned char)MessageType::CH2S_LOGIN );

	outBuffer.Write( id );
	outBuffer.Write( pass );

	RakPeerInterface * client = Network::GetInstance().GetClient();
	if( client )
	{
		client->Send(&outBuffer, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true);
	}
}
int lraknet_StartUp(lua_State* L)
{
    RakPeerInterface* peer = __self(L);
    lua_Integer maxConnections = luaL_checkinteger(L, 2);

    // for sake of simplicity, we listen only ONE port.
    const char* address = luaL_checkstring(L, 3);
    lua_Integer port = luaL_checkinteger(L, 4);

    SocketDescriptor socket(port, address);
    StartupResult result = peer->Startup(maxConnections, &socket, 1);

    lua_pushinteger(L, result);
    return 1;
}
Exemple #8
0
 bool operator()(string signal) {
     GuiConsoleOutput cout = GG.console->output();
     string input = GG.console->getInput();
     // cout << "Received command " << input << std::endl;
     // send message
     mClient->Send(input.c_str(), (int) input.length()+1, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true);
     return false;
 }
Exemple #9
0
void Network::ReqAddUserDataSend( UserData & userData )
{
	RakNet::BitStream outBuffer;
	outBuffer.Write( (unsigned char)MessageType::C2S_ADD_USERDATA );
	outBuffer.Write( _myUserNo );

	outBuffer.Write( userData._year );
	outBuffer.Write( userData._month );
	outBuffer.Write( userData._day );
	outBuffer.Write( userData._hour );
	outBuffer.Write( userData._min );
	outBuffer.Write( userData._value );
	outBuffer.Write( userData._temp );

	RakPeerInterface * client = Network::GetInstance().GetClient();
	if( client )
	{
		client->Send(&outBuffer, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true);
	}
}
Exemple #10
0
bool NetworkServer::listen(const std::string& host, int port, int maxConnections)
{
    assert(!isConnected());
    assert(maxConnections > 0);
    assert(port >= 0 && port <= 65535);

	RakPeerInterface* peer = RakNetworkFactory::GetRakPeerInterface();

	int threadSleepMillis = 30;
	SocketDescriptor descriptor(port, host.c_str());
	if (!peer->Startup(maxConnections, threadSleepMillis, &descriptor, 1)) {
		RakNetworkFactory::DestroyRakPeerInterface(peer);
		return false;
	}
    peer->SetMaximumIncomingConnections(maxConnections);
	peer->SetOccasionalPing(true);

	_peer = peer;
	return true;
}
int lraknet_Send(lua_State* L)
{
    RakPeerInterface* peer = __self(L);

    size_t len = 0;
    const char* data = luaL_checklstring(L, 2, &len);
    lua_Integer priority = luaL_checkinteger(L, 3);
    lua_Integer reliability = luaL_checkinteger(L, 4);
    lua_Integer orderingChannel = luaL_checkinteger(L, 5);

    uint64_t guid = luaL_checkinteger(L, 6);
    lua_Integer broadcast = luaL_checkinteger(L, 7);

    uint32_t n = peer->Send(data,
                            len,
                            (PacketPriority)priority,
                            (PacketReliability)reliability,
                            (char)orderingChannel,
                            AddressOrGUID(RakNetGUID(guid)),
                            (bool)broadcast);

    lua_pushinteger(L, n);
    return 1;
}
Exemple #12
0
void main(void)
{
	printf("Shows how to connect telnet to read PacketLogger output from RakPeer.\n");

	RakPeerInterface *rakPeer = RakNet::RakPeerInterface::GetInstance();
	TelnetTransport tt;
	ConsoleServer consoleServer;
	LogCommandParser lcp;
	PacketConsoleLogger pcl;
	pcl.SetLogCommandParser(&lcp);
	consoleServer.AddCommandParser(&lcp);
	consoleServer.SetTransportProvider(&tt, 23);
	rakPeer->AttachPlugin(&pcl);

	RakNet::SocketDescriptor sd(0,0);
	RakNet::StartupResult sr = rakPeer->Startup(32, &sd, 1);
	(void) sr;
	RakAssert(sr==RAKNET_STARTED);

	printf("Use telnet 127.0.0.1 23 to connect from the command window\n");
	printf("Use 'Turn Windows features on and off' with 'Telnet Client' if needed.\n");
	printf("Once telnet has connected, type 'Logger subscribe'\n");
	printf("Press any key in this window once you have done all this.\n");
	RakNet::Packet *packet;
	while (!kbhit())
	{
		consoleServer.Update();
		RakSleep(30);
	}

	RakNet::ConnectionAttemptResult car = rakPeer->Connect("natpunch.jenkinssoftware.com", 61111, 0, 0);
	(void) car;
	while (1)
	{
		for (packet=rakPeer->Receive(); packet; rakPeer->DeallocatePacket(packet), packet=rakPeer->Receive())
		{
		}

		consoleServer.Update();
		RakSleep(30);
	}	
}
Exemple #13
0
void AuthLoop(CONNECT_INFO* cfg, Ref< UsersPool > OnlineUsers, Ref< CrossThreadQueue< std::string > > OutputQueue) {
	// Initialize the RakPeerInterface used throughout the entire server
	RakPeerInterface* rakServer = RakNetworkFactory::GetRakPeerInterface();

	// Initialize the PacketFileLogger plugin (for the logs)
	PacketFileLogger* msgFileHandler = NULL;
	if (cfg->logFile) {
		msgFileHandler = new PacketFileLogger();
		rakServer->AttachPlugin(msgFileHandler);
	}

	// Initialize security IF user has enabled it in config.ini
	InitSecurity(rakServer, cfg->useEncryption);

	// Initialize the SocketDescriptor
	SocketDescriptor socketDescriptor(cfg->listenPort, 0);

	// If the startup of the server is successful, print it to the console
	// Otherwise, print an error
	if (rakServer->Startup(8, 30, &socketDescriptor, 1)) {
		std::stringstream s;
		s << "[AUTH] started! Listening on: " << cfg->listenPort << "\n";
		OutputQueue->Insert(s.str());
	} else QuitError("[AUTH] server init error!");

	// Set max incoming connections to 8
	rakServer->SetMaximumIncomingConnections(8);

	// If msgFileHandler is initalized, use it to log the server in ./logs/auth
	if (msgFileHandler != NULL) msgFileHandler->StartLog(".\\logs\\auth");

	// Initialize the Packet class
	Packet* packet;

	//LUNI_AUTH = true;

	// LUNIterminate is the bool used to terminate threads.
	// While it is false, the thread runs, but if it is true, the thread exits
	while (!getTerminate()) {
		RakSleep(30);	// This sleep keeps RakNet responsive
		packet = rakServer->Receive(); // Get the packets from the client
		if (packet == NULL) continue; // If the packet is null, just continue without processing anything
		PrintPacketInfo(packet, msgFileHandler); // Print the packet information (if packet is not NULL)

		// Figure out which packet it is...
		switch (packet->data[0]) {
			case ID_LEGO_PACKET:

				switch (packet->data[1]) {
					case GENERAL:
						if (packet->data[3] == 0) {
							// Send the Init packet to the client
							SendInitPacket(rakServer, packet->systemAddress, true);
						}
						break;

					case AUTH: //user logging into server
						{
							// Handle the user login using the above method
							auto usr = HandleUserLogin(rakServer, packet, cfg, OnlineUsers);

							// If username is not null, print the username that logged in.
							// Otherwise, print the error message
							if (usr != NULL) {
								Logger::log("AUTH", "", usr->GetUsername() + " Logged-in");
							}
							else Logger::log("AUTH", "", "Login failed");
						}
						break;

					// The default if the packet the server is recieving has an unidentified ID
					default:
						Logger::log("AUTH", "", "received unknown packet: " + RawDataToString(packet->data, packet->length));
				}

				break;

			// If the server is recieving a new connection, print it.
			case ID_NEW_INCOMING_CONNECTION:
#			ifdef DEBUG
				Logger::log("AUTH", "" , "is receiving a new connection...");
			#endif
				break;

			// If someone is disconnecting from the auth server, print it
			case ID_DISCONNECTION_NOTIFICATION:
				Logger::log("AUTH", "", "User disconnected from Auth server...");
				Session::disconnect(packet->systemAddress, SessionPhase::PHASE_CONNECTED);
				break;
				
			// If the packet has an unidentified RakNet ID (one not listed here), print the
			// packet info
			default:
				Logger::log("AUTH", "", "received unknown packet: " + RawDataToString(packet->data, packet->length));
		}

		// Deallocate the packet to conserve memory
		rakServer->DeallocatePacket(packet);
	}

	// If LUNIServer Auth has been terminated, print it
	Logger::log("AUTH", "", "quitting");

	// Shut down Auth server
	rakServer->Shutdown(0);
	RakNetworkFactory::DestroyRakPeerInterface(rakServer);

	//LUNI_AUTH = false;
}
void CharactersLoop(CONNECT_INFO* cfg, Ref< UsersPool > OnlineUsers, Ref< CrossThreadQueue< string > > OutputQueue) {
	RakPeerInterface* rakServer = RakNetworkFactory::GetRakPeerInterface();

	PacketFileLogger* msgFileHandler = NULL;
	if (cfg->logFile) {
		msgFileHandler = new PacketFileLogger();
		rakServer->AttachPlugin(msgFileHandler);
	}

	InitSecurity(rakServer, cfg->useEncryption);
	SocketDescriptor socketDescriptor(cfg->listenPort, 0);

	if (rakServer->Startup(8, 30, &socketDescriptor, 1)) {
		stringstream s;
		s << "characters started! Listening on: " << cfg->listenPort << "\n";
		OutputQueue->Insert(s.str());
	} else exit(2);
	rakServer->SetMaximumIncomingConnections(8);

	if (msgFileHandler != NULL) msgFileHandler->StartLog(".\\logs\\char");

	Packet* packet;

	while (!LUNIterminate) {
		RakSleep(30);	// This sleep keeps RakNet responsive
		packet = rakServer->Receive();
		if (packet == NULL) continue;
		PrintPacketInfo(packet, msgFileHandler);
		// create and send packets back here according to the one we got

		switch (packet->data[0]) {
			case ID_LEGO_PACKET:

				switch (packet->data[1]) {
					case LUNI_INITAW:
						if (packet->data[3] == 0) {	// thats just a formality so far since no other numbers occured for this case
							auto v = OpenPacket(".\\char\\init_aw.bin");
							ServerSendPacket(rakServer, v, packet->systemAddress);
						}
						break;

					case LUNI_CHARACTER:

						switch (packet->data[3]) {
							case LUNI_CHARACTER_CHARSDATA: // char response: 05, 06
								// char traffic only - byte 8 defines number of characters, if there are no characters the user automatically gets to the character creation screen
							{
								//giving client characters list
								auto v = OpenPacket(".\\char\\char_aw2.bin");
								ServerSendPacket(rakServer, v, packet->systemAddress);

							#ifdef DEBUG
								/*StringCompressor* sc = StringCompressor::Instance();
								Ref<char> output = new char[256];
								RakNet::BitStream* bs = new RakNet::BitStream(v.data(), v.size(), false);
								if (sc->DecodeString(output.Get(), 256, bs))
									cout << ("\n the TEST: " + RawDataToString((uchar*)output.Get(), 256) + "\n");
								else cout << ("\n the Test failure :(\n");*/
								RakNet::BitStream bs(v.data(), v.size(), false);
								vector< uchar > out(v.size() *2);
								bs.ReadCompressed(out.data(), out.size(), true);
								//cout << "\n the Test: " << RawDataToString( s.Get(), v.size() ) << endl;
								//SavePacket("theTest.bin", out);
							#endif
							}
								break;

							case LUNI_CHARACTER_CREATEDNEW:
							{
								CharacterCreation cc(CleanPacket(packet->data, packet->length));

								stringstream s;
								s << "\nSomebody wants to create a character with name: " << cc.GetName() << endl;
								s << "re-Serialization: " << RawDataToString(cc.Serialize(), cc.GetGeneratedPacketSize()) << endl;
								OutputQueue->Insert(s.str());
								// response: 05, 06
								// since we can't build our own packets yet we can't send a response here (because it is dependent on the user input)
								vector< uchar > reply(2);
								reply.push_back(5);
								reply.push_back(6);
								ServerSendPacket(rakServer, reply, packet->systemAddress);
							}
								break;

							case 4: // is this sent from the client once the user wants to enter world?
							{
								auto usr = OnlineUsers->Find(packet->systemAddress);
								if (usr != NULL) {
									usr->numredir++;
									//character id is received
									vector< uchar > t;
									for (int i = 8; i <= 11; i++) t.push_back(packet->data[i]);
									usr->nextcid = *(ulong*)t.data();

								#ifdef DEBUG
									stringstream s;
									s << "\nCharacter logging in world with id: " << usr->nextcid;
									if ( usr->nextcid == 2397732190 ) s << " CheekyMonkey!\n";
									else if ( usr->nextcid == 2444680020 ) s << " monkeybrown!\n";
									else if ( usr->nextcid == 1534792735 ) s << " GruntMonkey!\n";
									else if ( usr->nextcid == 1457240027 ) s << " Shafantastic!\n";
									else s << " Unknow cid: " << usr->nextcid << endl;
									OutputQueue->Insert(s.str());
								#endif
								}

								auto v = OpenPacket(".\\char\\char_aw_redirect.bin");
								if (v.size() > 0) {
									// ip starts at byte 8, port starts at byte 0x29
									if (cfg->redirectIp[0] != 0)
										memcpy(v.data() + 0x8, cfg->redirectIp, sizeof(cfg->redirectIp) - 3);	// NOTE: the IP can currently only be 13 characters long here since there are some non-zero bytes directly after the IP and I don't want to delete them (is it safe to overwrite them?)
									if (cfg->redirectPort > 0)
										memcpy(v.data() + 0x29, &cfg->redirectPort, sizeof(cfg->redirectPort));
									ServerSendPacket(rakServer, v, packet->systemAddress);
								}
								rakServer->CloseConnection(packet->systemAddress, true);
							}
								break;

							case LUNI_CHARACTER_DELETED:
								stringstream s;
								s << "\n Case LUNI_CHARACTER_DELETED: " << RawDataToString(packet->data, packet->length) << endl;
								OutputQueue->Insert(s.str());
								break;
						}

						break;

					default:
						stringstream s;
						s << "\ncharacters received unknow pakcet: " << RawDataToString(packet->data, packet->length) << endl;
						OutputQueue->Insert(s.str());
				}

				break;

			case ID_NEW_INCOMING_CONNECTION:
			#ifdef DEBUG
				OutputQueue->Insert("\n Characters is receiving a new connection...\n");
			#endif
				break;

			case ID_DISCONNECTION_NOTIFICATION:
			{
				auto usr = OnlineUsers->Find(packet->systemAddress);
				if (OnlineUsers->Remove(packet->systemAddress))
					OutputQueue->Insert("Disconnected " + usr->GetUsername() + "\n");
			}
				break;

			default:
				stringstream s;
				s << "\ncharacters received unknow pakcet: " << RawDataToString(packet->data, packet->length) << endl;
				OutputQueue->Insert(s.str());
		}
	}
}
void AuthLoop(CONNECT_INFO* cfg) {
	// Initialize the RakPeerInterface used throughout the entire server
	RakPeerInterface* rakServer = RakNetworkFactory::GetRakPeerInterface();

	// Initialize the PacketFileLogger plugin (for the logs)
	PacketFileLogger* msgFileHandler = NULL;
	if (cfg->logFile) {
		msgFileHandler = new PacketFileLogger();
		rakServer->AttachPlugin(msgFileHandler);
	}

	//for (int k = 0; k < 10; k++){
	//	Logger::log("AUTH", "IP", std::string(rakServer->GetLocalIP(k)), LOG_DEBUG);
	//}

	// Initialize security IF user has enabled it in config.ini
	InitSecurity(rakServer, cfg->useEncryption);

	// Initialize the SocketDescriptor
	SocketDescriptor socketDescriptor(cfg->listenPort, 0);

	// If the startup of the server is successful, print it to the console
	// Otherwise, print an error
	if (rakServer->Startup(8, 30, &socketDescriptor, 1)) {
		Logger::log("AUTH", "", "started! Listening on port " + std::to_string(cfg->listenPort));
	} else QuitError("[AUTH] server init error!");

	// Set max incoming connections to 8
	rakServer->SetMaximumIncomingConnections(8);

	// If msgFileHandler is initalized, use it to log the server in ./logs/auth
	if (msgFileHandler != NULL) msgFileHandler->StartLog(".\\logs\\auth");

	// Initialize the Packet class
	Packet* packet;

	bool LUNI_AUTH = true;

	// LUNIterminate is the bool used to terminate threads.
	// While it is false, the thread runs, but if it is true, the thread exits
	while (LUNI_AUTH) {
		RakSleep(30);	// This sleep keeps RakNet responsive
		packet = rakServer->Receive(); // Get the packets from the client
		if (packet == NULL) continue; // If the packet is null, just continue without processing anything
		PrintPacketInfo(packet, msgFileHandler); // Print the packet information (if packet is not NULL)

		RakNet::BitStream *data = new RakNet::BitStream(packet->data, packet->length, false);
		unsigned char packetID;
		data->Read(packetID);
		// Figure out which packet it is...
		switch (packetID) {
			case ID_LEGO_PACKET:

				unsigned short networkType;
				data->Read(networkType);
				unsigned long packetType;
				data->Read(packetType);
				unsigned char pad;
				data->Read(pad);

				switch (networkType) {
					case GENERAL:
						if (packetType == 0) {
							// Send the Init packet to the client
							//SendInitPacket(rakServer, packet->systemAddress, true);
							DoHandshake(rakServer, packet->systemAddress, data, "AUTH");
						}
						break;

					case AUTH: //user logging into server
						{
							// Handle the user login using the above method
							HandleUserLogin(rakServer, packet, cfg);
						}
						break;

					// The default if the packet the server is recieving has an unidentified ID
					default:
						Logger::log("AUTH", "", "received unknown packet: " + RawDataToString(packet->data, packet->length));
				}

				break;

			// If the server is recieving a new connection, print it.
			case ID_NEW_INCOMING_CONNECTION:
#			ifdef DEBUG
				Logger::log("AUTH", "" , "is receiving a new connection...");
			#endif
				break;

			// If someone is disconnecting from the auth server, print it
			case ID_DISCONNECTION_NOTIFICATION:
				Logger::log("AUTH", "", "User disconnected from Auth server...");
				Session::disconnect(packet->systemAddress, SessionPhase::PHASE_CONNECTED);
				break;
				
			// If the packet has an unidentified RakNet ID (one not listed here), print the
			// packet info
			default:
				Logger::log("AUTH", "", "received unknown packet: " + RawDataToString(packet->data, packet->length));
		}

		// Deallocate the packet to conserve memory
		rakServer->DeallocatePacket(packet);
	}

	// If LUNIServer Auth has been terminated, print it
	Logger::log("AUTH", "", "quitting");

	// Shut down Auth server
	rakServer->Shutdown(0);
	RakNetworkFactory::DestroyRakPeerInterface(rakServer);

	//LUNI_AUTH = false;
}
int main(void)
{
	// Pointers to the interfaces of our server and client.
	// Note we can easily have both in the same program
	RakPeerInterface *client;
	RakPeerInterface *server;
	bool b;
	char str[256];
	char serverPort[30], clientPort[30];
	RakNetTime quitTime;
	// Holds packets
	Packet* p;	

	printf("A client / server sample showing how clients can broadcast offline packets\n");
	printf("to find active servers.\n");
	printf("Difficulty: Beginner\n\n");

	printf("Instructions:\nRun one or more servers on the same port.\nRun a client and it will get pongs from those servers.\n");
	printf("Run as (s)erver or (c)lient?\n");
	gets(str);

	if (str[0]=='s' || str[0]=='S')
	{
		client=0;
		server=RakNetworkFactory::GetRakPeerInterface();
		// A server
		printf("Enter the server port\n");
		gets(serverPort);
		if (serverPort[0]==0)
			strcpy(serverPort, "60001");

		printf("Starting server.\n");
		// The server has to be started to respond to pings.
		SocketDescriptor socketDescriptor(atoi(serverPort),0);
		b = server->Startup(2, 30, &socketDescriptor, 1);
		server->SetMaximumIncomingConnections(2);
		if (b)
			printf("Server started, waiting for connections.\n");
		else
		{ 
			printf("Server failed to start.  Terminating.\n");
			exit(1);
		}
	}
	else
	{
		client=RakNetworkFactory::GetRakPeerInterface();
		server=0;

		// Get our input
		printf("Enter the client port to listen on, or 0\n");
		gets(clientPort);
		if (clientPort[0]==0)
			strcpy(clientPort, "60000");
		printf("Enter the port to ping\n");
		gets(serverPort);
		if (serverPort[0]==0)
			strcpy(serverPort, "60001");
		SocketDescriptor socketDescriptor(atoi(clientPort),0);
		client->Startup(1, 30, &socketDescriptor, 1);

		// Connecting the client is very simple.  0 means we don't care about
		// a connectionValidationInteger, and false for low priority threads
		// All 255's mean broadcast
		client->Ping("255.255.255.255", atoi(serverPort), true);

		printf("Pinging\n");
	}

	printf("How many seconds to run this sample for?\n");
	gets(str);
	if (str[0]==0)
	{
		printf("Defaulting to 5 seconds\n");
		quitTime = RakNet::GetTime() + 5000;
	}
	else
		quitTime = RakNet::GetTime() + atoi(str) * 1000;

	// Loop for input
	while (RakNet::GetTime() < quitTime)
	{
		if (server)
			p = server->Receive();
		else 
			p = client->Receive();

		if (p==0)
		{
			SLEEP(30);
			continue;
		}
		if (server)
			server->DeallocatePacket(p);
		else
		{
			if (p->data[0]==ID_PONG)
			{
				RakNetTime time;
				memcpy((char*)&time, p->data+1, sizeof(RakNetTime));
				printf("Got pong from %s with time %i\n", p->systemAddress.ToString(), RakNet::GetTime() - time);
			}
			client->DeallocatePacket(p);
		}

		SLEEP(30);
	}

	// We're done with the network
	if (server)
		RakNetworkFactory::DestroyRakPeerInterface(server);
	if (client)
		RakNetworkFactory::DestroyRakPeerInterface(client);

	return 0;
}
Exemple #17
0
int main()
{
	Packet *packet;
	RakPeerInterface *rakPeer;
	bool isConnected=false;
	rakPeer=RakNetworkFactory::GetRakPeerInterface();
	char command[512];
	printf("This sample demonstrates connecting to the command console.\n");
	printf("using the RakNet transport protocol\n");
	printf("It's the equivalent of a secure telnet client\n");
	printf("See the 'CommandConsoleServer' project.\n");
	printf("Difficulty: Intermediate\n\n");

	printf("RakNet secure command console.\n");
	printf("Commands:\n");
	printf("/Connect\n");
	printf("/Disconnect\n");
	printf("/Quit\n");
	printf("Any other command goes to the remote console\n");
	while (1)
	{
		if (kbhit())
		{
			gets(command);

			if (stricmp(command, "/quit")==0)
			{
				printf("Goodbye.\n");
				rakPeer->Shutdown(500, 0);
				return 0;
			}
			else if (stricmp(command, "/disconnect")==0)
			{
				if (isConnected)
				{
					rakPeer->Shutdown(500, 0);
					isConnected=false;
					printf("Disconnecting.\n");
				}
				else
				{
					printf("Not currently connected.\n");
				}
			}
			else if (stricmp(command, "/connect")==0)
			{
				if (isConnected)
				{
					printf("Disconnect first.\n");
				}
				else
				{
					char ip[128];
					char remotePort[64];
					char password[512];
					char localPort[64];
					printf("Enter remote IP: ");
					do {
						gets(ip);
					} while(ip[0]==0);
					printf("Enter remote port: ");
					do {
						gets(remotePort);
					} while(remotePort[0]==0);
					printf("Enter local port (enter for 0): ");
					gets(localPort);
					if (localPort[0]==0)
					{
						strcpy(localPort, "0");
					}
					printf("Enter console password (enter for none): ");
					gets(password);
					SocketDescriptor socketDescriptor((int) atoi(localPort),0);
					if (rakPeer->Startup(1, 100, &socketDescriptor, 1))
					{
						int passwordLen;
						if (password[0])
							passwordLen=(int) strlen(password)+1;
						else
							passwordLen=0;
						if (rakPeer->Connect(ip, (int) atoi(remotePort), password, passwordLen))
							printf("Connecting...\nNote: if the password is wrong the other system will ignore us.\n");
						else
						{
							printf("Connect call failed.\n");
							rakPeer->Shutdown(0, 0);
						}
					}
					else
						printf("Initialize call failed.\n");					
					
				}				
			}
			else
			{
				if (isConnected)
				{
					RakNet::BitStream str;
					str.Write((unsigned char) ID_TRANSPORT_STRING);
					str.Write(command, (int) strlen(command)+1);
					rakPeer->Send(&str, MEDIUM_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true);
				}
				else
				{
					printf("You must be connected to send commands.\n");
				}
			}
		}

		packet = rakPeer->Receive();
		if (packet)
		{
			switch (packet->data[0])
			{
			case ID_DISCONNECTION_NOTIFICATION:
				printf("The server disconnected us.\n");
				isConnected=false;
				break;
			case ID_CONNECTION_BANNED:
				printf("We are banned from this server.\n");
				isConnected=false;
				break;
			case ID_CONNECTION_ATTEMPT_FAILED:
				printf("Connection attempt failed.\nThe password was wrong or there is no responsive machine at that IP/port.\n");
				isConnected=false;
				break;
			case ID_NO_FREE_INCOMING_CONNECTIONS:
				printf("Server is full.\n");
				isConnected=false;
				break;
			case ID_CONNECTION_LOST:
				printf("We lost the connection.\n");
				isConnected=false;
				break;
			case ID_CONNECTION_REQUEST_ACCEPTED:
				printf("Connection accepted.\n");
				isConnected=true;
				break;
			case ID_TRANSPORT_STRING:
				printf("%s", packet->data+1);
				break;
			}

			rakPeer->DeallocatePacket(packet);
		}

		// This sleep keeps RakNet responsive
#ifdef _WIN32
		Sleep(30);
#else
		usleep(30 * 1000);
#endif

	return 0;
	}
}
int main(int argc, char *argv[])
{  
#ifndef WIN32
	setlinebuf(stdout);
#endif

	// Default values
	int listenPort = DEFAULTPORT;
	int connectionCount = 1000;

	time_t timerInterval = 10;	// 60 seconds
	time_t rotateCheckTimer = time(0) + timerInterval;
	int rotateSizeLimit = 50000000;	// 50 MB
	bool useLogFile = false;
	bool daemonMode = false;
	
	// Process command line arguments
	for (int i = 1; i < argc; i++)
	{
		if (strlen(argv[i]) == 2 && argc>=i+1)
		{
			switch (argv[i][1]) 
			{
				case 'd':
				{
					daemonMode = true;
					break;
				}
				case 'p':
				{
					listenPort = atoi(argv[i+1]);
					i++; // eat port number parameter
					if (listenPort < 1 || listenPort > 65535)
					{
						fprintf(stderr, "Master server port is invalid, should be between 0 and 65535.\nIt is also advisable to use a number above well known ports (>1024).\n");
						return 1;
					}
					break;
				}
				case 'c':
				{
					connectionCount = atoi(argv[i+1]);
					i++;
					if (connectionCount < 0)
					{
						fprintf(stderr, "Connection count must be higher than 0.\n");
						return 1;
					}
					break;
				}
				case 'l':
				{				
					useLogFile = Log::EnableFileLogging(logfile);
					break;
				}
				case 'e':
				{
					int debugLevel = atoi(argv[i+1]);
					Log::sDebugLevel = debugLevel;
					i++;
					if (debugLevel < 0 || debugLevel > 9)
					{
						fprintf(stderr, "Log level can be 0(errors), 1(warnings), 2(informational), 9(debug)\n");
						return 1;
					}
					break;
				}
				case 's':
				{
					int statDelay =  atoi(argv[i+1]);
					i++;
					if (statDelay < 0)
					{
						fprintf(stderr, "Statistics print delay must not be lower than 0. Use 0 to disable.\n");
						return 1;
					}
					databaseServer.SetStatDelay(statDelay);
					Log::printStats = true;
					break;
				}					
				case '?':
					usage();
					return 0;
				default:
					fprintf(stderr, "Parsing error, unknown parameter\n\n");
					usage();
					return 1;
			}
		}
		else
		{
			printf("Parsing error, incorrect parameters\n\n");
			usage();
			return 1;
		}
	}
	
#ifndef WIN32
	if (daemonMode)
	{
		printf("Running in daemon mode, file logging enabled...\n");
		if (!useLogFile)
			useLogFile = Log::EnableFileLogging(logfile);
		// Don't change cwd to /
		// Beware that log/pid files are placed wherever this was launched from
		daemon(1, 0);
	}
	
	if (!WriteProcessID(argv[0], &pidFile[0], fileBufSize))
		perror("Warning, failed to write own PID value to PID file\n");
#endif

	// Start the peers
	RakPeerInterface *masterPeer = RakNetworkFactory::GetRakPeerInterface();
	masterPeer->SetMaximumIncomingConnections(connectionCount);
	SocketDescriptor sd(listenPort,0);
	masterPeer->Startup(connectionCount, 30, &sd, 1);
	masterPeer->AttachPlugin(&databaseServer);
		
	Log::print_log("Unity master server version %s\n", VERSION);
	Log::print_log("Master server port set to %d\n",listenPort);
	Log::print_log("%d connection count limit\n", connectionCount);
	if (Log::printStats)
		Log::print_log("%d sec delay between statistics print to log\n", databaseServer.GetStatDelay());
	
	// Register signal handlers
#ifndef WIN32
	if (signal(SIGHUP, Log::RotateLogFile) == SIG_ERR)
		Log::error_log("Problem setting up hangup signal handler");
#endif
	if (signal(SIGINT, shutdown) == SIG_ERR || signal(SIGTERM, shutdown) == SIG_ERR)
		Log::error_log("Problem setting up terminate signal handler");
	else
		Log::print_log("To quit press Ctrl-C\n----------------------------------------------------\n");

	Packet *p;
	while (!quit)
	{
		p=masterPeer->Receive();
		while (p)
		{
			ProcessPacket(p);
			masterPeer->DeallocatePacket(p);
			p=masterPeer->Receive();
		}
		// Is it time to rotate the logs?
		if (useLogFile)
		{
			if (rotateCheckTimer < time(0))
			{
				// We should always be writing to the end of the stream, so the current position should give the total size
				int position = Log::GetLogSize();
				if (position > rotateSizeLimit) {
					Log::info_log("Rotating logs, size limit reached\n");
					Log::RotateLogFile(0);
				}
				rotateCheckTimer = time(0) + timerInterval;
			}
		}
		RakSleep(30);
	}

	if (pidFile)
	{
		if (remove(pidFile) != 0)
			fprintf(stderr, "Failed to remove PID file at %s\n", pidFile);
	}	
	masterPeer->Shutdown(100,0);
	RakNetworkFactory::DestroyRakPeerInterface(masterPeer);
				
	return 0;
}
void AuthLoop(CONNECT_INFO* cfg, Ref< UsersPool > OnlineUsers, Ref< CrossThreadQueue< string > > OutputQueue) {
	RakPeerInterface* rakServer = RakNetworkFactory::GetRakPeerInterface();

	PacketFileLogger* msgFileHandler = NULL;
	if (cfg->logFile) {
		msgFileHandler = new PacketFileLogger();
		rakServer->AttachPlugin(msgFileHandler);
	}

	InitSecurity(rakServer, cfg->useEncryption);
	SocketDescriptor socketDescriptor(cfg->listenPort, 0);

	if (rakServer->Startup(8, 30, &socketDescriptor, 1)) {
		stringstream s;
		s << "auth started! Listening on: " << cfg->listenPort << "\n";
		OutputQueue->Insert(s.str());
	} else QuitError("auth server init error!");
	rakServer->SetMaximumIncomingConnections(8);

	if (msgFileHandler != NULL) msgFileHandler->StartLog(".\\logs\\auth");

	Packet* packet;

	while (!LUNIterminate) {
		RakSleep(30);	// This sleep keeps RakNet responsive
		packet = rakServer->Receive();
		if (packet == NULL) continue;
		PrintPacketInfo(packet, msgFileHandler);

		switch (packet->data[0]) {
			case ID_LEGO_PACKET:

				switch (packet->data[1]) {
					case LUNI_INITAW:
						if (packet->data[3] == 0) {	// thats just a formality so far since no other numbers occured for this case
							// response: 00, 00
							auto v = OpenPacket(".\\auth\\init_aw.bin");
							// bytes 8-10 is the game version (same numbers are mentioned in the game log)
							// the client expects it to be the same that he sent (otherwise he displays "server is being updated" and disconnects)
							ServerSendPacket(rakServer, v, packet->systemAddress);
						}
						break;

					case LUNI_LOGIN: //user logging into server
						{
							auto usr = HandleUserLogin(rakServer, packet, cfg, OnlineUsers);
							if( usr != NULL ) OutputQueue->Insert("\n" + usr->GetUsername() + " Logged-in\n");
						#ifdef DEBUG
							else OutputQueue->Insert("\n Login failed!\n");
						#endif
						}
						break;

					default:
						stringstream s;
						s << "\nauth received unknow pakcet: " << RawDataToString(packet->data, packet->length) << endl;
						OutputQueue->Insert(s.str());
				}

				break;

			case ID_NEW_INCOMING_CONNECTION:
#			ifdef DEBUG
				OutputQueue->Insert("\n Auth is receiving a new connection...\n");
			#endif
				break;

			case ID_DISCONNECTION_NOTIFICATION: // do nothing
				break;

			default:
				stringstream s;
				s << "\nauth received unknow pakcet: " << RawDataToString(packet->data, packet->length) << endl;
				OutputQueue->Insert(s.str());
		}

		rakServer->DeallocatePacket(packet);
	}

	stringstream s;
	s << "Quitting auth\n";
	OutputQueue->Insert(s.str());

	rakServer->Shutdown(0);
	RakNetworkFactory::DestroyRakPeerInterface(rakServer);
}
int main(void)
{
	MasterServer masterServer;
	int serverListSize;
	const char *outputString;
	int outputInt;
	bool identiferFound;
	int index;
	char ch;
	Packet *p;

	RakPeerInterface *testGameMasterServer;

	testGameMasterServer = RakNetworkFactory::GetRakPeerInterface();
	testGameMasterServer->Initialize(10, 60000, 0);
	testGameMasterServer->SetMaximumIncomingConnections(8);
	testGameMasterServer->AttachPlugin(&masterServer);

	printf("This project shows how to use the master server.\n");
	printf("The master server is a plugin that maintains a list of games uplodated.\n");
	printf("by the master client.\n");
	printf("Difficulty: Beginner\n\n");

	printf("(p)rint\n(q)uit\n");
	char buff[256];

	while (1)
	{
		if (kbhit())
		{
			READCHAR(buff);
			if (ch=='q')
				break;
			else if (ch=='p')
			{
				serverListSize=masterServer.GetServerListSize();
				if (serverListSize==0)
				{
					printf("No servers in list\n");
				}
				else
				{
					for (index=0; index < serverListSize; index++)
					{
						printf("%i. ", index);
						outputString=masterServer.GetServerListRuleAsString(index, "IP", &identiferFound);
						if (identiferFound)
							printf("%s:", outputString);
						else
							printf("NO_IP:");
						outputInt=masterServer.GetServerListRuleAsInt(index, "Port", &identiferFound);
						if (identiferFound)
							printf("%i ", outputInt);
						else
							printf("NO_PORT ");
						outputString=masterServer.GetServerListRuleAsString(index, "Game type", &identiferFound);
						if (identiferFound)
							printf("%s ", outputString);
						else
							printf("NIL_GT ");
						outputString=masterServer.GetServerListRuleAsString(index, "Game name", &identiferFound);
						if (identiferFound)
							printf("%s ", outputString);
						else
							printf("NIL_GN ");
						outputInt=masterServer.GetServerListRuleAsInt(index, "Score", &identiferFound);
						if (identiferFound)
							printf("%i\n", outputInt);
						else
							printf("NO_SCORE\n");
					}
				}
			}
			ch=0;
		}

		p = testGameMasterServer->Receive();
		while (p)
		{
			// Ignore any game packets.  The master server plugin handles everything.
			testGameMasterServer->DeallocatePacket(p);
			// Call Receive every update to keep the plugin going
			p = testGameMasterServer->Receive();
		}
		

#ifdef _WIN32
		Sleep(30);
#else
		usleep(30 * 1000);
#endif
	}

	return 0;
}
void WorldLoop(CONNECT_INFO* cfg, Ref< UsersPool > OnlineUsers, Ref< CrossThreadQueue< string > > OutputQueue) {
	// Initialize the RakPeerInterface used throughout the entire server
	RakPeerInterface* rakServer = RakNetworkFactory::GetRakPeerInterface();

	// Initialize the PacketFileLogger plugin (for the logs)
	PacketFileLogger* msgFileHandler = NULL;
	if (cfg->logFile) {
		msgFileHandler = new PacketFileLogger();
		rakServer->AttachPlugin(msgFileHandler);
	}

	// Initialize security IF user has enabled it in config.ini
	InitSecurity(rakServer, cfg->useEncryption);

	// Initialize the SocketDescriptor
	SocketDescriptor socketDescriptor(cfg->listenPort, 0);

	// If the startup of the server is successful, print it to the console
	// Otherwise, quit the server (as the char server is REQUIRED for the
	// server to function properly)
	if (rakServer->Startup(8, 30, &socketDescriptor, 1)) {
		stringstream s;
		s << "world started! Listening on: " << cfg->listenPort << "\n";
		OutputQueue->Insert(s.str());
	} else exit(2);

	// Set max incoming connections to 8
	rakServer->SetMaximumIncomingConnections(8);

	// If msgFileHandler is not NULL, save logs of char server
	if (msgFileHandler != NULL) msgFileHandler->StartLog(".\\logs\\world");

	// Initialize the Packet class for the packets
	Packet* packet;

	// This will be used in the saving of packets below
	int i = 0;

	// This will be used in the saving of packets below...
	while (!LUNIterminate) {
		RakSleep(30);	// This sleep keeps RakNet responsive
		packet = rakServer->Receive(); // Recieve the packets from the server
		if (packet == NULL) continue; // If packet is NULL, just continue without processing anything

		// This will save all packets recieved from the client if running from DEBUG
		#ifdef DEBUG
			stringstream packetName;
			packetName << ".//Saves//World_Packet" << i << ".bin";

			SavePacket(packetName.str(), (char*)packet->data, packet->length);
			i++;
		#endif

		// Create and send packets back here according to the one we got
		switch (packet->data[0]) {
			case ID_USER_PACKET_ENUM:
				switch (packet->data[1]) {
					case GENERAL:
						if (packet->data[3] == 0) {	// thats just a formality so far since no other numbers occured for this case
							auto v = OpenPacket(".\\world\\init_aw.bin");
							ServerSendPacket(rakServer, v, packet->systemAddress);
						}
						break;

					case SERVER:

						switch (packet->data[3]) {
							case CLIENT_VALIDATION:
							{ 
								auto usr = OnlineUsers->Find(packet->systemAddress);
								//this packets contains ZoneId and something else... but what?
								// it starts whit: 53 05 00 02 00 00 00 00 -- -- (<-ZoneId) ?? ?? ??
								vector< uchar > v;
								if (usr != NULL && usr->nextcid == 2444680020) { //monkeybrown
									v = OpenPacket(".\\world\\monkeybrown\\char_aw2.bin");
								}
								else if (usr != NULL && usr->nextcid == 1534792735) { //gruntmonkey
									v = OpenPacket(".\\world\\gruntmonkey\\char_aw2.bin");
								}
								else if (usr != NULL && usr->nextcid == 1457240027) { //shafantastic
									v = OpenPacket(".\\world\\shastafantastic\\char_aw22.bin");
								}
								else { //cheekymonkey
									v = OpenPacket(".\\world\\char_aw2.bin");
								}

								#ifdef DEBUG
								if (v.size() > 0) {
									RakNet::BitStream bs( CleanPacket(v.data(), v.size()), v.size()-8, false );
									ZoneId zid;
									bs.Read(zid);
									stringstream s;
									s << "\nLoading world: " << zid << endl;
									OutputQueue->Insert(s.str());
								} else OutputQueue->Insert("\nWorld Error: can't load char_aw2.bin\n");
								#endif

								ServerSendPacket(rakServer, v, packet->systemAddress);
							}
								break;

							case CLIENT_LEVEL_LOAD_COMPLETE:
							{
								// Response: 05, 04
								// The answer to this is compressed data detailing character data
								// also since the answer seems to consist of a split packet, does RakNet automatically split the packets if the data is too big? or do we have to do something, if yes what?
								// byte 08 (2 or 4 bytes long? I guess 4...) seems to define the size of the data we send, no idea what the data itself is though...
								auto usr = OnlineUsers->Find(packet->systemAddress);

								// If the user is not equal to null and next character id = below number,
								// Open the packets of monkeybrown and load him into a world
								if (usr != NULL && usr->nextcid == 2444680020) {
									cout << "\n Replying to monkeybrown\n";
									auto v = OpenPacket(".\\world\\monkeybrown\\rocket_1a.bin");
									ServerSendPacket(rakServer, v, packet->systemAddress);

									v = OpenPacket(".\\world\\monkeybrown\\rocket_1b.bin");
									ServerSendPacket(rakServer, v, packet->systemAddress);

									v = OpenPacket(".\\world\\monkeybrown\\rocket_1c.bin");
									ServerSendPacket(rakServer, v, packet->systemAddress);

									v = OpenPacket(".\\world\\monkeybrown\\world_2a.bin");
									ServerSendPacket(rakServer, v, packet->systemAddress);
									// test, is this the right thing to do? there's no difference in the process when they are (not) sent so far
									v = OpenPacket(".\\world\\monkeybrown\\world_2b.bin");   // I assume these two are sent together?
									ServerSendPacket(rakServer, v, packet->systemAddress);

									for (int i = 0; i < 42; i++) {  // herpaderp
										stringstream fl;
										fl << ".\\world\\monkeybrown\\test\\world_2_" << (i + 1) << ".bin";
										auto v = OpenPacket(fl.str());
										ServerSendPacket(rakServer, v, packet->systemAddress);
									}

									v = OpenPacket(".\\world\\monkeybrown\\test\\world_2_1.bin");
									ServerSendPacket(rakServer, v, packet->systemAddress);

									for (int i = 42; i < 210; i++) {  // herpaderp
										stringstream fl;
										fl << ".\\world\\monkeybrown\\test\\world_2_" << (i + 1) << ".bin";
										auto v = OpenPacket(fl.str());
										ServerSendPacket(rakServer, v, packet->systemAddress);
									}
								} else { // Otherwise, reply to Cheekymonkey and open his packets
									cout << "\n Replying to cheekymonkey\n";
									auto v = OpenPacket(".\\world\\world_2a.bin");
									ServerSendPacket(rakServer, v, packet->systemAddress);
									// test, is this the right thing to do? there's no difference in the process when they are (not) sent so far
									v = OpenPacket(".\\world\\world_2b.bin");	// I assume these two are sent together?
									ServerSendPacket(rakServer, v, packet->systemAddress);
									for (int i = 0; i < 5; i++) {	// herpaderp
										stringstream fl;
										fl << ".\\world\\test\\world_2_" << (i + 1) << ".bin";
										auto v = OpenPacket(fl.str());
										ServerSendPacket(rakServer, v, packet->systemAddress);
									}
								}
							}
								break;

							case 22: //user moving / update request?
							{
								auto usr = OnlineUsers->Find(packet->systemAddress);
							#ifdef DEBUG
								OutputQueue->Insert("Received packet 22: " + RawDataToString(packet->data, packet->length) + "\n");
							#endif
							}
								break;

							case LUNI_WORLD_CHAT: //user wrote a chat message
							{
								if (packet->length >= 10 && RawDataToString(packet->data + packet->length - 10, 10, true) == "730064006f0077006e00") {//virus used to be here
								}

								// dummy try
								vector< uchar > v(packet->length);
								for (uint i = 0; i < packet->length; i++) v.push_back(packet->data[i]);
								ServerSendPacket(rakServer, v, packet->systemAddress);
							}
								break;

							case 5:
							{
							#ifdef DEBUG
								vector< uchar > t;
								for (int i = 8; i <= 11; i++) t.push_back(packet->data[i]);
								ulong cid = *(ulong*)t.data();
								//cout << "\nCharacter id is doing something?: " << cid;
							#endif
							}
								break;

							default:
								stringstream s;
								s << "\nworld received unknow pakcet: " << RawDataToString(packet->data, packet->length) << endl;
								OutputQueue->Insert(s.str());
						}

						break;

					default:
						stringstream s;
						s << "\nworld received unknow pakcet: " << RawDataToString(packet->data, packet->length) << endl;
						OutputQueue->Insert(s.str());
				}
				break;

			case ID_NEW_INCOMING_CONNECTION:
			#ifdef DEBUG
				OutputQueue->Insert("\n World is receiving a new connection...\n");
			#endif
				break;

			case ID_DISCONNECTION_NOTIFICATION:
			{
				auto usr = OnlineUsers->Find(packet->systemAddress);
				if (OnlineUsers->Remove(packet->systemAddress))
					OutputQueue->Insert("Disconnected " + usr->GetUsername() + "\n");
			}
				break;

			default:
				stringstream s;
				s << "\nworld received unknow pakcet: " << RawDataToString(packet->data, packet->length) << endl;
				OutputQueue->Insert(s.str());
		}

		rakServer->DeallocatePacket(packet);
	}

	stringstream s;
	s << "Quitting world\n";
	OutputQueue->Insert(s.str());

	rakServer->Shutdown(0);
	RakNetworkFactory::DestroyRakPeerInterface(rakServer);
}
int main(int argc, char **argv)
{
	printf("A simple client interface for the advanced autopatcher.\n");
	printf("Use DirectoryDeltaTransfer for a simpler version of an autopatcher.\n");
	printf("Difficulty: Intermediate\n\n");

	printf("Client starting...");
	SystemAddress serverAddress=UNASSIGNED_SYSTEM_ADDRESS;
	AutopatcherClient autopatcherClient;
	FileListTransfer fileListTransfer;
	autopatcherClient.SetFileListTransferPlugin(&fileListTransfer);
	unsigned short localPort=0;
	if (argc>=6)
	{
		localPort=atoi(argv[5]);
	}
#ifdef USE_TCP
	PacketizedTCP packetizedTCP;
	if (packetizedTCP.Start(localPort,1)==false)
	{
		printf("Failed to start TCP. Is the port already in use?");
		return 1;
	}
	packetizedTCP.AttachPlugin(&autopatcherClient);
	packetizedTCP.AttachPlugin(&fileListTransfer);
#else
	RakPeerInterface *rakPeer;
	rakPeer = RakNetworkFactory::GetRakPeerInterface();
	SocketDescriptor socketDescriptor(localPort,0);
	rakPeer->Startup(1,0,&socketDescriptor, 1);
	// Plugin will send us downloading progress notifications if a file is split to fit under the MTU 10 or more times
	rakPeer->SetSplitMessageProgressInterval(10);
	rakPeer->AttachPlugin(&autopatcherClient);
	rakPeer->AttachPlugin(&fileListTransfer);
#endif
	printf("started\n");
	char buff[512];
	if (argc<2)
	{
		printf("Enter server IP: ");
		gets(buff);
		if (buff[0]==0)
			//	strcpy(buff, "94.198.81.195");
			strcpy(buff, "127.0.0.1");
	}
	else
		strcpy(buff, argv[1]);

#ifdef USE_TCP
	packetizedTCP.Connect(buff,60000,false);
#else
	rakPeer->Connect(buff, 60000, 0, 0);
#endif

	printf("Connecting...\n");
	char appDir[512];
	if (argc<3)
	{
		printf("Enter application directory: ");
		gets(appDir);
		if (appDir[0]==0)
		{
			strcpy(appDir, "C:/temp2");
		}
	}
	else
		strcpy(appDir, argv[2]);
	char appName[512];
	if (argc<4)
	{
		printf("Enter application name: ");
		gets(appName);
		if (appName[0]==0)
			strcpy(appName, "TestApp");
	}
	else
		strcpy(appName, argv[3]);

	bool patchImmediately=argc>=5 && argv[4][0]=='1';

	if (patchImmediately==false)
		printf("Hit 'q' to quit, 'p' to patch, 'c' to cancel the patch. 'r' to reconnect. 'd' to disconnect.\n");
	else
		printf("Hit 'q' to quit, 'c' to cancel the patch.\n");

	char ch;
	Packet *p;
	while (1)
	{
#ifdef USE_TCP
		SystemAddress notificationAddress;
		notificationAddress=packetizedTCP.HasCompletedConnectionAttempt();
		if (notificationAddress!=UNASSIGNED_SYSTEM_ADDRESS)
		{
			printf("ID_CONNECTION_REQUEST_ACCEPTED\n");
			serverAddress=notificationAddress;
		}
		notificationAddress=packetizedTCP.HasNewIncomingConnection();
		if (notificationAddress!=UNASSIGNED_SYSTEM_ADDRESS)
			printf("ID_NEW_INCOMING_CONNECTION\n");
		notificationAddress=packetizedTCP.HasLostConnection();
		if (notificationAddress!=UNASSIGNED_SYSTEM_ADDRESS)
			printf("ID_CONNECTION_LOST\n");


		p=packetizedTCP.Receive();
		while (p)
		{
			if (p->data[0]==ID_AUTOPATCHER_REPOSITORY_FATAL_ERROR)
			{
				char buff[256];
				RakNet::BitStream temp(p->data, p->length, false);
				temp.IgnoreBits(8);
				stringCompressor->DecodeString(buff, 256, &temp);
				printf("ID_AUTOPATCHER_REPOSITORY_FATAL_ERROR\n");
				printf("%s\n", buff);
			}
			else if (p->data[0]==ID_AUTOPATCHER_FINISHED)
				printf("ID_AUTOPATCHER_FINISHED\n");
			else if (p->data[0]==ID_AUTOPATCHER_RESTART_APPLICATION)
				printf("Launch \"AutopatcherClientRestarter.exe autopatcherRestart.txt\"\nQuit this application immediately after to unlock files.\n");

			packetizedTCP.DeallocatePacket(p);
			p=packetizedTCP.Receive();
		}
#else
		p=rakPeer->Receive();
		while (p)
		{
			if (p->data[0]==ID_DISCONNECTION_NOTIFICATION)
				printf("ID_DISCONNECTION_NOTIFICATION\n");
			else if (p->data[0]==ID_CONNECTION_LOST)
				printf("ID_CONNECTION_LOST\n");
			else if (p->data[0]==ID_CONNECTION_REQUEST_ACCEPTED)
			{
				printf("ID_CONNECTION_REQUEST_ACCEPTED\n");
				serverAddress=p->systemAddress;
			}
			else if (p->data[0]==ID_CONNECTION_ATTEMPT_FAILED)
				printf("ID_CONNECTION_ATTEMPT_FAILED\n");
			else if (p->data[0]==ID_AUTOPATCHER_REPOSITORY_FATAL_ERROR)
			{
				char buff[256];
				RakNet::BitStream temp(p->data, p->length, false);
				temp.IgnoreBits(8);
				stringCompressor->DecodeString(buff, 256, &temp);
				printf("ID_AUTOPATCHER_REPOSITORY_FATAL_ERROR\n");
				printf("%s\n", buff);
			}
			else if (p->data[0]==ID_AUTOPATCHER_FINISHED)
				printf("ID_AUTOPATCHER_FINISHED\n");
			else if (p->data[0]==ID_AUTOPATCHER_RESTART_APPLICATION)
				printf("Launch \"AutopatcherClientRestarter.exe autopatcherRestart.txt\"\nQuit this application immediately after to unlock files.\n");

			rakPeer->DeallocatePacket(p);
			p=rakPeer->Receive();
		}
#endif

		if (kbhit())
			ch=getch();
		else
			ch=0;

		if (ch=='q')
			break;
		else if (ch=='r')
		{
#ifdef USE_TCP
			packetizedTCP.Connect(buff,60000,false);
#else
			rakPeer->Connect(buff, 60000, 0, 0);
#endif
		}
		else if (ch=='d')
		{
#ifdef USE_TCP
			packetizedTCP.CloseConnection(serverAddress);
#else
			rakPeer->CloseConnection(serverAddress, true);
#endif
		}
		else if (ch=='p' || (serverAddress!=UNASSIGNED_SYSTEM_ADDRESS && patchImmediately==true))
		{
			patchImmediately=false;
			char lastUpdateDate[128];
			char restartFile[512];
			strcpy(restartFile, appDir);
			strcat(restartFile, "/autopatcherRestart.txt");
		//	printf("Enter last update date (only newer updates retrieved) or nothing to get all updates\n");
		//	gets(lastUpdateDate);
			lastUpdateDate[0]=0;

			if (autopatcherClient.PatchApplication(appName, appDir, lastUpdateDate, serverAddress, &transferCallback, restartFile, argv[0]))
			{
				printf("Patching process starting.\n");
			}
			else
			{
				printf("Failed to start patching.\n");
			}
		}
		else if (ch=='c')
		{
			autopatcherClient.Clear();
			printf("Autopatcher cleared.\n");
		}

		RakSleep(30);
	}

	// Dereference so the destructor doesn't crash
	autopatcherClient.SetFileListTransferPlugin(0);

#ifdef USE_TCP
	packetizedTCP.Stop();
#else
	rakPeer->Shutdown(500,0);
	RakNetworkFactory::DestroyRakPeerInterface(rakPeer);
#endif
	return 1;
}
int main(int argc, char **argv)
{
	// Avoids the Error: Got a packet bigger than 'max_allowed_packet' bytes
	printf("Important: Requires that you first set the DB schema and the max packet size on the server.\n");
	printf("See DependentExtensions/AutopatcherMySQLRepository/readme.txt\n");
	
	RakPeerInterface *rakPeer;
	rakPeer = RakNetworkFactory::GetRakPeerInterface();
	printf("Server starting... ");
	SocketDescriptor socketDescriptor(60000,0);
	rakPeer->Startup(8,0,&socketDescriptor, 1);
	rakPeer->SetMaximumIncomingConnections(8);
	printf("started.\n");

	AutopatcherServer autopatcherServer;
	rakPeer->AttachPlugin(&autopatcherServer);
	AutopatcherMySQLRepository repository;
	autopatcherServer.SetAutopatcherRepositoryInterface(&repository);
	FLP_Printf progressIndicator;
	FileListTransfer fileListTransfer;
	fileListTransfer.SetCallback(&progressIndicator);
	autopatcherServer.SetFileListTransferPlugin(&fileListTransfer);
	rakPeer->AttachPlugin(&fileListTransfer);
	printf("Enter database password:\n");
	char password[128];
	char username[256];
	strcpy(username, "root");
	gets(password);
	if (password[0]==0)
		strcpy(password,"aaaa");
	char db[256];
	printf("Enter DB schema: ");
	gets(db);
	if (db[0]==0)
		strcpy(db,"autopatcher");
	if (!repository.Connect("localhost", username, password, db, 0, NULL, 0))
	{
		printf("Database connection failed.\n");
		return 1;
	}
	printf("Database connection suceeded.\n");
	printf("(D)rop database\n(C)reate database.\n(A)dd application\n(U)pdate revision.\n(R)emove application\n(Q)uit\n");

	char ch;
	Packet *p;
	while (1)
	{
		p=rakPeer->Receive();
		while (p)
		{
			if (p->data[0]==ID_NEW_INCOMING_CONNECTION)
				printf("ID_NEW_INCOMING_CONNECTION\n");
			else if (p->data[0]==ID_DISCONNECTION_NOTIFICATION)
				printf("ID_DISCONNECTION_NOTIFICATION\n");
			else if (p->data[0]==ID_CONNECTION_LOST)
				printf("ID_CONNECTION_LOST\n");

			rakPeer->DeallocatePacket(p);
			p=rakPeer->Receive();
		}

		if (kbhit())
		{
			ch=getch();
			if (ch=='q')
				break;
			else if (ch=='c')
			{
				if (repository.CreateAutopatcherTables()==false)
					printf("Error: %s\n", repository.GetLastError());
				else
					printf("Created\n");
			}
			else if (ch=='d')
			{
				if (repository.DestroyAutopatcherTables()==false)
					printf("Error: %s\n", repository.GetLastError());
				else
					printf("Destroyed\n");
			}
			else if (ch=='a')
			{
				printf("Enter application name to add: ");
				char appName[512];
				gets(appName);
				if (appName[0]==0)
					strcpy(appName, "TestApp");

				if (repository.AddApplication(appName, username)==false)
					printf("Error: %s\n", repository.GetLastError());
				else
					printf("Done\n");
			}
			else if (ch=='r')
			{
				printf("Enter application name to remove: ");
				char appName[512];
				gets(appName);
				if (appName[0]==0)
					strcpy(appName, "TestApp");

				if (repository.RemoveApplication(appName)==false)
					printf("Error: %s\n", repository.GetLastError());
				else
					printf("Done\n");
			}
			else if (ch=='u')
			{
				printf("Enter application name: ");
				char appName[512];
				gets(appName);
				if (appName[0]==0)
					strcpy(appName, "TestApp");

				printf("Enter application directory: ");
				char appDir[512];
				gets(appDir);
				if (appDir[0]==0)
					strcpy(appDir, "C:/temp");

				if (repository.UpdateApplicationFiles(appName, appDir, username, &progressIndicator)==false)
				{
					printf("Error: %s\n", repository.GetLastError());
				}
				else
				{
					printf("Update success.\n");
				}
			}
		}

		RakSleep(30);


	}

	RakNetworkFactory::DestroyRakPeerInterface(rakPeer);
}
Exemple #24
0
int main(int argc, char **argv)
{
	RakPeerInterface *rakPeer;
	char str[256];
	char ip[32];
	unsigned short remotePort, localPort;
	RakNet::Packet *packet;

	printf("This project tests sending a burst of messages to a remote system.\n");
	printf("Difficulty: Beginner\n\n");
	
	rakPeer = RakNet::RakPeerInterface::GetInstance();
	
	printf("Enter remote IP (enter to not connect): ");
	Gets(ip, sizeof(ip));
	if (ip[0])
	{
		printf("Enter remote port: ");
		Gets(str, sizeof(str));
		if (str[0]==0)
			strcpy(str, "60000");
		remotePort=atoi(str);
		
		printf("Enter local port: ");
		Gets(str, sizeof(str));
		if (str[0]==0)
			strcpy(str, "0");
		localPort=atoi(str);
		
		RakNet::SocketDescriptor socketDescriptor(localPort,0);
		rakPeer->Startup(32, &socketDescriptor, 1);
		
		printf("Connecting...\n");
		rakPeer->Connect(ip, remotePort, 0, 0);
	}
	else
	{
		printf("Enter local port: ");
		Gets(str, sizeof(str));
		if (str[0]==0)
			strcpy(str, "60000");
		localPort=atoi(str);
		
		RakNet::SocketDescriptor socketDescriptor(localPort,0);
		rakPeer->Startup(32, &socketDescriptor, 1);
	}
	rakPeer->SetMaximumIncomingConnections(32);
	
	printf("'s' to send. ' ' for statistics. 'q' to quit.\n");

	while (1)
	{
		if (kbhit())
		{
			char ch=getch();
			if (ch=='q')
				return 1;
			else if (ch==' ')
			{
				RakNetStatistics *rss;
				char message[2048];
					rss=rakPeer->GetStatistics(rakPeer->GetSystemAddressFromIndex(0));
				StatisticsToString(rss, message, 2);
				printf("%s", message);
			}
			else if (ch=='s')
			{
				char msgSizeStr[128], msgCountStr[128];
				uint32_t msgSize, msgCount,index;
				printf("Enter message size in bytes: ");
				Gets(msgSizeStr, sizeof(msgSizeStr));
				if (msgSizeStr[0]==0)
					msgSize=4096;
				else
					msgSize=atoi(msgSizeStr);
				printf("Enter times to repeatedly send message: ");
				Gets(msgCountStr, sizeof(msgCountStr));
				if (msgCountStr[0]==0)
					msgCount=128;
				else
					msgCount=atoi(msgCountStr);
				RakNet::BitStream bitStream;
				for (index=0; index < msgCount; index++)
				{
					bitStream.Reset();
					bitStream.Write((MessageID)ID_USER_PACKET_ENUM);
					bitStream.Write(msgSize);
					bitStream.Write(index);
					bitStream.Write(msgCount);
					bitStream.PadWithZeroToByteLength(msgSize);
					rakPeer->Send(&bitStream, MEDIUM_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true);
				}
				printf("Sent\n");
					
			}
		}
		
		for (packet=rakPeer->Receive(); packet; rakPeer->DeallocatePacket(packet), packet=rakPeer->Receive())
		{
			switch(packet->data[0])
			{
			case ID_CONNECTION_REQUEST_ACCEPTED:
				printf("ID_CONNECTION_REQUEST_ACCEPTED\n");
				break;
			case ID_NEW_INCOMING_CONNECTION:
				printf("ID_NEW_INCOMING_CONNECTION\n");
				break;
			case ID_NO_FREE_INCOMING_CONNECTIONS:
				printf("ID_NO_FREE_INCOMING_CONNECTIONS\n");
				break;
			case ID_DISCONNECTION_NOTIFICATION:
				printf("ID_DISCONNECTION_NOTIFICATION\n");
				break;
			case ID_CONNECTION_LOST:
				printf("ID_CONNECTION_LOST\n");
				break;
			case ID_CONNECTION_ATTEMPT_FAILED:
				printf("Connection attempt failed\n");
				break;
			case ID_USER_PACKET_ENUM:
				{
					uint32_t msgSize, msgCount, index;
					RakNet::BitStream bitStream(packet->data, packet->length, false);
					bitStream.IgnoreBytes(sizeof(MessageID));
					bitStream.Read(msgSize);
					bitStream.Read(index);
					bitStream.Read(msgCount);
					printf("%i/%i len=%i", index+1, msgCount, packet->length);
					if (msgSize > BITS_TO_BYTES(bitStream.GetReadOffset()) && packet->length!=msgSize)
						printf("UNDERLENGTH!\n");
					else
						printf("\n");
					break;
				}
			default:
				printf("Unknown message type %i\n", packet->data[0]);
			}
		}
	
		RakSleep(30);
	}

	rakPeer->Shutdown(100);
	RakNet::RakPeerInterface::DestroyInstance(rakPeer);

	return 1;
}
int DroppedConnectionConvertTest::RunTest(DataStructures::List<RakString> params,bool isVerbose,bool noPauses)
{

	RakPeerInterface *server;
	RakPeerInterface *clients[NUMBER_OF_CLIENTS];
	unsigned index, connectionCount;
	SystemAddress serverID;
	Packet *p;
	unsigned short numberOfSystems;
	unsigned short numberOfSystems2;
	int sender;

	// Buffer for input (an ugly hack to keep *nix happy)
	//	char buff[256];

	// Used to refer to systems.  We already know the IP
	unsigned short serverPort = 20000;
	serverID.binaryAddress=inet_addr("127.0.0.1");
	serverID.port=serverPort;

	server=RakPeerInterface::GetInstance();
	destroyList.Clear(false,_FILE_AND_LINE_);
	destroyList.Push(server,_FILE_AND_LINE_);
	//	server->InitializeSecurity(0,0,0,0);
	SocketDescriptor socketDescriptor(serverPort,0);
	server->Startup(NUMBER_OF_CLIENTS, &socketDescriptor, 1);
	server->SetMaximumIncomingConnections(NUMBER_OF_CLIENTS);
	server->SetTimeoutTime(2000,UNASSIGNED_SYSTEM_ADDRESS);

	for (index=0; index < NUMBER_OF_CLIENTS; index++)
	{
		clients[index]=RakPeerInterface::GetInstance();
		destroyList.Push(clients[index],_FILE_AND_LINE_);
		SocketDescriptor socketDescriptor2(serverPort+1+index,0);
		clients[index]->Startup(1, &socketDescriptor2, 1);
		if (clients[index]->Connect("127.0.0.1", serverPort, 0, 0)!=CONNECTION_ATTEMPT_STARTED)
		{
			DebugTools::ShowError("Connect function failed.",!noPauses && isVerbose,__LINE__,__FILE__);
			return 2;

		}
		clients[index]->SetTimeoutTime(5000,UNASSIGNED_SYSTEM_ADDRESS);

		RakSleep(1000);
		if (isVerbose)
			printf("%i. ", index);
	}

	TimeMS entryTime=GetTimeMS();//Loop entry time

	int seed = 12345;
	if (isVerbose)
		printf("Using seed %i\n", seed);
	seedMT(seed);//specify seed to keep execution path the same.

	int randomTest;

	bool dropTest=false;
	RakTimer timeoutWaitTimer(1000);

	while (GetTimeMS()-entryTime<30000)//run for 30 seconds.
	{
		// User input

		randomTest=randomMT() %4;

		if(dropTest)
		{

			server->GetConnectionList(0, &numberOfSystems);
			numberOfSystems2=numberOfSystems;

			connectionCount=0;
			for (index=0; index < NUMBER_OF_CLIENTS; index++)
			{
				clients[index]->GetConnectionList(0, &numberOfSystems);
				if (numberOfSystems>1)
				{
					if (isVerbose)
					{
						printf("Client %i has %i connections\n", index, numberOfSystems);
						DebugTools::ShowError("Client has more than one connection",!noPauses && isVerbose,__LINE__,__FILE__);
						return 1;
					}

				}
				if (numberOfSystems==1)
				{
					connectionCount++;
				}
			}

			if (connectionCount!=numberOfSystems2)
			{
				if (isVerbose)
					DebugTools::ShowError("Timeout on dropped clients not detected",!noPauses && isVerbose,__LINE__,__FILE__);
				return 3;
			}

		}
		dropTest=false;

		switch(randomTest)
		{

		case 0:
			{
				index = randomMT() % NUMBER_OF_CLIENTS;

				clients[index]->GetConnectionList(0, &numberOfSystems);
				clients[index]->CloseConnection(serverID, false,0);
				if (numberOfSystems==0)
				{
					if (isVerbose)
						printf("Client %i silently closing inactive connection.\n",index);
				}
				else
				{
					if (isVerbose)
						printf("Client %i silently closing active connection.\n",index);
				}
			}

			break;
		case 1:
			{
				index = randomMT() % NUMBER_OF_CLIENTS;

				clients[index]->GetConnectionList(0, &numberOfSystems);

				if(!CommonFunctions::ConnectionStateMatchesOptions (clients[index],serverID,true,true,true,true) )//Are we connected or is there a pending operation ?
				{
					if (clients[index]->Connect("127.0.0.1", serverPort, 0, 0)!=CONNECTION_ATTEMPT_STARTED)
					{

						DebugTools::ShowError("Connect function failed.",!noPauses && isVerbose,__LINE__,__FILE__);
						return 2;

					}
				}
				if (numberOfSystems==0)
				{
					if (isVerbose)
						printf("Client %i connecting to same existing connection.\n",index);

				}
				else
				{
					if (isVerbose)
						printf("Client %i connecting to closed connection.\n",index);
				}
			}

			break;
		case 2:
			{

				if (isVerbose)
					printf("Randomly connecting and disconnecting each client\n");
				for (index=0; index < NUMBER_OF_CLIENTS; index++)
				{
					if (NUMBER_OF_CLIENTS==1 || (randomMT()%2)==0)
					{
						if (clients[index]->IsActive())
						{

							int randomTest2=randomMT() %2;
							if (randomTest2)
								clients[index]->CloseConnection(serverID, false, 0);
							else
								clients[index]->CloseConnection(serverID, true, 0);
						}
					}
					else
					{
						if(!CommonFunctions::ConnectionStateMatchesOptions (clients[index],serverID,true,true,true,true) )//Are we connected or is there a pending operation ?
						{
							if (clients[index]->Connect("127.0.0.1", serverPort, 0, 0)!=CONNECTION_ATTEMPT_STARTED)
							{
								DebugTools::ShowError("Connect function failed.",!noPauses && isVerbose,__LINE__,__FILE__);
								return 2;

							}
						}
					}
				}
			}
			break;

		case 3:
			{

				if (isVerbose)
					printf("Testing if clients dropped after timeout.\n");
				timeoutWaitTimer.Start();
						//Wait half the timeout time, the other half after receive so we don't drop all connections only missing ones, Active ait so the threads run on linux
				while (!timeoutWaitTimer.IsExpired())
				{
				RakSleep(50);
				}
				dropTest=true;

			}
			break;
		default:
			// Ignore anything else
			break;
		}

		server->GetConnectionList(0, &numberOfSystems);
		numberOfSystems2=numberOfSystems;
		if (isVerbose)
			printf("The server thinks %i clients are connected.\n", numberOfSystems);
		connectionCount=0;
		for (index=0; index < NUMBER_OF_CLIENTS; index++)
		{
			clients[index]->GetConnectionList(0, &numberOfSystems);
			if (numberOfSystems>1)
			{
				if (isVerbose)
				{
					printf("Client %i has %i connections\n", index, numberOfSystems);
					DebugTools::ShowError("Client has more than one connection",!noPauses && isVerbose,__LINE__,__FILE__);
					return 1;
				}

			}
			if (numberOfSystems==1)
			{
				connectionCount++;
			}
		}

		if (isVerbose)
			printf("%i clients are actually connected.\n", connectionCount);
		if (isVerbose)
			printf("server->NumberOfConnections==%i.\n", server->NumberOfConnections());

		//}

		// Parse messages

		while (1)
		{
			p = server->Receive();
			sender=NUMBER_OF_CLIENTS;
			if (p==0)
			{
				for (index=0; index < NUMBER_OF_CLIENTS; index++)
				{
					p = clients[index]->Receive();
					if (p!=0)
					{
						sender=index;
						break;						
					}
				}
			}

			if (p)
			{
				switch (p->data[0])
				{
				case ID_CONNECTION_REQUEST_ACCEPTED:
					if (isVerbose)
						printf("%i: %ID_CONNECTION_REQUEST_ACCEPTED from %i.\n",sender, p->systemAddress.port);
					break;
				case ID_DISCONNECTION_NOTIFICATION:
					// Connection lost normally
					if (isVerbose)
						printf("%i: ID_DISCONNECTION_NOTIFICATION from %i.\n",sender, p->systemAddress.port);
					break;

				case ID_NEW_INCOMING_CONNECTION:
					// Somebody connected.  We have their IP now
					if (isVerbose)
						printf("%i: ID_NEW_INCOMING_CONNECTION from %i.\n",sender, p->systemAddress.port);
					break;


				case ID_CONNECTION_LOST:
					// Couldn't deliver a reliable packet - i.e. the other system was abnormally
					// terminated
					if (isVerbose)
						printf("%i: ID_CONNECTION_LOST from %i.\n",sender, p->systemAddress.port);
					break;

				case ID_NO_FREE_INCOMING_CONNECTIONS:
					if (isVerbose)
						printf("%i: ID_NO_FREE_INCOMING_CONNECTIONS from %i.\n",sender, p->systemAddress.port);
					break;

				default:
					// Ignore anything else
					break;
				}
			}
			else
				break;

			if (sender==NUMBER_OF_CLIENTS)
				server->DeallocatePacket(p);
			else
				clients[sender]->DeallocatePacket(p);
		}
		if (dropTest)
		{
			//Trigger the timeout if no recieve
			timeoutWaitTimer.Start();
			while (!timeoutWaitTimer.IsExpired())
			{
			RakSleep(50);
			}
		}
		// 11/29/05 - No longer necessary since I added the keepalive
		/*
		// Have everyone send a reliable packet so dropped connections are noticed.
		ch=255;
		server->Send((char*)&ch, 1, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true);

		for (index=0; index < NUMBER_OF_CLIENTS; index++)
		clients[index]->Send((char*)&ch, 1, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_SYSTEM_ADDRESS, true);
		*/

		// Sleep so this loop doesn't take up all the CPU time

		RakSleep(10);

	}

	return 0;
}
int main(void)
{
	printf("DEPRECIATED - Use LightweightDatabase instead\n");

	BitStream bitStream;
	char str[256];
	char ch;
	MasterClient masterClient;
	RakPeerInterface *testGameServerOrClient;
	unsigned int serverListSize, index;
	bool identiferFound;
	const char *outputString;
	int outputInt;
	Packet *p;

	// Create a fake game
	testGameServerOrClient = RakNetworkFactory::GetRakPeerInterface();
	testGameServerOrClient->Initialize(8, 60003, 0);
	testGameServerOrClient->SetMaximumIncomingConnections(8);
	testGameServerOrClient->AttachPlugin(&masterClient);

	printf("This project shows how to use the master client.\n");
	printf("The master client is used by game servers to advertise themselves.\n");
	printf("On the master server and by game clients to download a list of game servers\n");
	printf("Difficulty: Intermediate\n\n");

	if (masterClient.Connect("127.0.0.1", 60000))
		printf("Master client connecting...\n");
	else
		printf("Master client failed to start or connect.\n");

	printf("(Q)uit\n(q)uery master server\n(l)ist server\n(d)elist server\n(D)isconnect from the master server.\n(a)dd rule\n(r)emove rule\n(p)ing server list\n(C)onnect to the master server.\n(c)onnect to another game, using NAT punch-through with master server, bypassing most NATs\n(SPACE) print server list\n");
	char buff[256];
	while (1)
	{
		if (kbhit())
		{
			READCHAR(buff);
			if (ch=='Q')
				break;
			if (ch=='q')
			{
				masterClient.ClearQueryRules();
				printf("Enter query key 1/2 or enter for none: ");
				gets(str);
				masterClient.AddQueryRule(str);
				printf("Enter query key 2/2 or enter for none: ");
				gets(str);
				masterClient.AddQueryRule(str);
				masterClient.QueryMasterServer();
				printf("Server queried.  Press space to see server list.\n");
			}
			else if (ch=='l')
			{
				printf("Uploading game server.  Query to see it.\n");
				masterClient.ListServer();
			}
			else if (ch=='d')
			{
				printf("Server delisted.  Query to update our own list.\n");
				masterClient.DelistServer();
			}
			else if (ch=='D')
			{
				printf("Disconnected.\n");
				PlayerID playerId;
				testGameServerOrClient->IPToPlayerID("127.0.0.1", 60000, &playerId);
				testGameServerOrClient->CloseConnection(playerId, true, 0);
			}
			else if (ch=='C')
			{
				if (masterClient.Connect("127.0.0.1", 60000))
					printf("Master client connecting...\n");
				else
					printf("Master client failed to start or connect.\n");
			}
			else if (ch=='a')
			{
				printf("Adding sample rules.  Query to update our own list.\n");
				masterClient.PostRule("Game name", "My big game o' death.", 0);
				masterClient.PostRule("Game type", "Death match", 0);
				masterClient.PostRule("Score",0, 100);
			}
			else if (ch=='r')
			{
				printf("Removing rules. Query to update our own list.\n");
				masterClient.RemoveRule("Game type");
				masterClient.RemoveRule("Game name");
				masterClient.RemoveRule("Score");
			}
			else if (ch=='p')
			{
				printf("Pinging any servers in our list\n");
				masterClient.PingServers();
			}
			else if (ch=='c')
			{
				char ip[22];
				printf("Sending connection attempt notification to master server\n");
				printf("Enter IP of server from game list: ");
				gets(ip);
				printf("Enter port: ");
				gets(str);
				if (ip[0]!=0 && str[0]!=0)
				{
					masterClient.ConnectionAttemptNotification(ip, atoi(str));
					printf("Sent connection attempt notification to the server the master server\n");
				}
				else
				{
					printf("Aborting...");
				}				
			}
			else if (ch==' ')
			{
				serverListSize=masterClient.GetServerListSize();
				if (serverListSize==0)
				{
					printf("No servers in list\n");
				}
				else
				{
					for (index=0; index < serverListSize; index++)
					{
						printf("%i. ", index);
						outputString=masterClient.GetServerListRuleAsString(index, "IP", &identiferFound);
						if (identiferFound)
							printf("%s:", outputString);
						else
							printf("NO_IP:");
						outputInt=masterClient.GetServerListRuleAsInt(index, "Port", &identiferFound);
						if (identiferFound)
							printf("%i ", outputInt);
						else
							printf("NO_PORT ");
						outputInt=masterClient.GetServerListRuleAsInt(index, "Ping", &identiferFound);
						if (identiferFound)
							printf("%i ", outputInt);
						else
							printf("NO_PING ");
						outputString=masterClient.GetServerListRuleAsString(index, "Game type", &identiferFound);
						if (identiferFound)
							printf("%s ", outputString);
						else
							printf("NO_GT ");
						outputString=masterClient.GetServerListRuleAsString(index, "Game name", &identiferFound);
						if (identiferFound)
							printf("%s ", outputString);
						else
							printf("NO_GN ");
						outputInt=masterClient.GetServerListRuleAsInt(index, "Score", &identiferFound);
						if (identiferFound)
							printf("%i\n", outputInt);
						else
							printf("NO_SCORE\n");
					}
				}
			}
			ch=0;
		}

		p = testGameServerOrClient->Receive();
		while (p)
		{
			// Ignore any game packets.  The master server plugin handles everything.
			testGameServerOrClient->DeallocatePacket(p);
			// Call Receive every update to keep the plugin going
			p = testGameServerOrClient->Receive();
		}

#ifdef _WIN32
		Sleep(30);
#else
		usleep(30 * 1000);
#endif
	}

	masterClient.Disconnect();
	RakNetworkFactory::DestroyRakPeerInterface(testGameServerOrClient);

	return 0;
}
/*
What is being done here is having 256 clients connect to one server, disconnect, connect again.

Do this for about 10 seconds. Then allow them all to connect for one last time.

This one has a nonblocking recieve so doesn't wait for connects or anything.
Just rapid connecting disconnecting.

Good ideas for changes:
After the last check run a eightpeers like test an add the conditions
of that test as well.

Make sure that if we initiate the connection we get a proper message
and if not we get a proper message. Add proper conditions.

Randomize sending the disconnect notes

Success conditions:
All connected normally.

Failure conditions:
Doesn't reconnect normally.

During the very first connect loop any connect returns false.

Connect function returns false and peer is not connected to anything.

*/
int ManyClientsOneServerNonBlockingTest::RunTest(DataStructures::List<RakString> params,bool isVerbose,bool noPauses)
{

	const int clientNum= 256;

	RakPeerInterface *clientList[clientNum];//A list of clients
	RakPeerInterface *server;//The server
	SystemAddress currentSystem;

	//SystemAddress currentSystem;

	Packet *packet;
	destroyList.Clear(false,_FILE_AND_LINE_);

	//Initializations of the arrays
	for (int i=0;i<clientNum;i++)
	{
		clientList[i]=RakPeerInterface::GetInstance();
		destroyList.Push(clientList[i],_FILE_AND_LINE_);

		clientList[i]->Startup(1,&SocketDescriptor(), 1);

	}

	server=RakPeerInterface::GetInstance();
	destroyList.Push(server,_FILE_AND_LINE_);
	server->Startup(clientNum, &SocketDescriptor(60000,0), 1);
	server->SetMaximumIncomingConnections(clientNum);

	//Connect all the clients to the server

	for (int i=0;i<clientNum;i++)
	{

		if (clientList[i]->Connect("127.0.0.1", 60000, 0,0)!=CONNECTION_ATTEMPT_STARTED)
		{

			if (isVerbose)
				DebugTools::ShowError("Problem while calling connect.\n",!noPauses && isVerbose,__LINE__,__FILE__);

			return 1;//This fails the test, don't bother going on.

		}

	}

	TimeMS entryTime=GetTimeMS();//Loop entry time

	DataStructures::List< SystemAddress  > systemList;
	DataStructures::List< RakNetGUID > guidList;

	if (isVerbose)
		printf("Entering disconnect loop \n");

	while(GetTimeMS()-entryTime<10000)//Run for 10 Secoonds
	{

		//Disconnect all clients IF connected to any from client side
		for (int i=0;i<clientNum;i++)
		{

			clientList[i]->GetSystemList(systemList,guidList);//Get connectionlist
			int len=systemList.Size();

			for (int j=0;j<len;j++)//Disconnect them all
			{

				clientList[i]->CloseConnection (systemList[j],true,0,LOW_PRIORITY); 	
			}

		}

		//RakSleep(100);

		//Connect

		for (int i=0;i<clientNum;i++)
		{

			currentSystem.SetBinaryAddress("127.0.0.1");
			currentSystem.port=60000;
			if(!CommonFunctions::ConnectionStateMatchesOptions (clientList[i],currentSystem,true,true,true,true) )//Are we connected or is there a pending operation ?
			{

				if (clientList[i]->Connect("127.0.0.1", 60000, 0,0)!=CONNECTION_ATTEMPT_STARTED)
				{

					if (isVerbose)
						DebugTools::ShowError("Problem while calling connect. \n",!noPauses && isVerbose,__LINE__,__FILE__);

					return 1;//This fails the test, don't bother going on.

				}
			}

		}

		//Server receive

		packet=server->Receive();

		if (isVerbose&&packet)
			printf("For server\n");

		while(packet)
		{

			switch (packet->data[0])
			{
			case ID_REMOTE_DISCONNECTION_NOTIFICATION:
				if (isVerbose)
					printf("Another client has disconnected.\n");

				break;
			case ID_REMOTE_CONNECTION_LOST:
				if (isVerbose)
					printf("Another client has lost the connection.\n");

				break;
			case ID_REMOTE_NEW_INCOMING_CONNECTION:
				if (isVerbose)              
					printf("Another client has connected.\n");
				break;
			case ID_CONNECTION_REQUEST_ACCEPTED:
				if (isVerbose)              
					printf("Our connection request has been accepted.\n");

				break;
			case ID_CONNECTION_ATTEMPT_FAILED:
				if (isVerbose)
					printf("A connection has failed.\n");

				break;

			case ID_NEW_INCOMING_CONNECTION:
				if (isVerbose)              
					printf("A connection is incoming.\n");

				break;
			case ID_NO_FREE_INCOMING_CONNECTIONS:
				if (isVerbose)              
					printf("The server is full.\n");

				break;

			case ID_ALREADY_CONNECTED:
				if (isVerbose)              
					printf("Already connected\n");

				break;

			case ID_DISCONNECTION_NOTIFICATION:
				if (isVerbose)
					printf("We have been disconnected.\n");
				break;
			case ID_CONNECTION_LOST:
				if (isVerbose)
					printf("Connection lost.\n");

				break;
			default:

				break;
			}

			server->DeallocatePacket(packet);

			// Stay in the loop as long as there are more packets.
			packet = server->Receive();
		}

		for (int i=0;i<clientNum;i++)//Receive for all peers
		{

			packet=clientList[i]->Receive();

			if (isVerbose&&packet)
				printf("For peer %i\n",i);

			while(packet)
			{

				switch (packet->data[0])
				{
				case ID_REMOTE_DISCONNECTION_NOTIFICATION:
					if (isVerbose)
						printf("Another client has disconnected.\n");

					break;
				case ID_REMOTE_CONNECTION_LOST:
					if (isVerbose)
						printf("Another client has lost the connection.\n");

					break;
				case ID_REMOTE_NEW_INCOMING_CONNECTION:
					if (isVerbose)              
						printf("Another client has connected.\n");
					break;
				case ID_CONNECTION_REQUEST_ACCEPTED:
					if (isVerbose)              
						printf("Our connection request has been accepted.\n");

					break;
				case ID_CONNECTION_ATTEMPT_FAILED:
					if (isVerbose)
						printf("A connection has failed.\n");

					break;

				case ID_NEW_INCOMING_CONNECTION:
					if (isVerbose)              
						printf("A connection is incoming.\n");

					break;
				case ID_NO_FREE_INCOMING_CONNECTIONS:
					if (isVerbose)              
						printf("The server is full.\n");

					break;

				case ID_ALREADY_CONNECTED:
					if (isVerbose)              
						printf("Already connected\n");

					break;

				case ID_DISCONNECTION_NOTIFICATION:
					if (isVerbose)
						printf("We have been disconnected.\n");
					break;
				case ID_CONNECTION_LOST:
					if (isVerbose)
						printf("Connection lost.\n");

					break;
				default:

					break;
				}

				clientList[i]->DeallocatePacket(packet);

				// Stay in the loop as long as there are more packets.
				packet = clientList[i]->Receive();
			}
		}
		RakSleep(0);//If needed for testing
	}

	entryTime=GetTimeMS();

	while(GetTimeMS()-entryTime<2000)//Run for 2 Secoonds to process incoming disconnects
	{

		//Server receive

		packet=server->Receive();

		if (isVerbose&&packet)
			printf("For server\n");

		while(packet)
		{

			switch (packet->data[0])
			{
			case ID_REMOTE_DISCONNECTION_NOTIFICATION:
				if (isVerbose)
					printf("Another client has disconnected.\n");

				break;
			case ID_REMOTE_CONNECTION_LOST:
				if (isVerbose)
					printf("Another client has lost the connection.\n");

				break;
			case ID_REMOTE_NEW_INCOMING_CONNECTION:
				if (isVerbose)              
					printf("Another client has connected.\n");
				break;
			case ID_CONNECTION_REQUEST_ACCEPTED:
				if (isVerbose)              
					printf("Our connection request has been accepted.\n");

				break;
			case ID_CONNECTION_ATTEMPT_FAILED:
				if (isVerbose)
					printf("A connection has failed.\n");

				break;

			case ID_NEW_INCOMING_CONNECTION:
				if (isVerbose)              
					printf("A connection is incoming.\n");

				break;
			case ID_NO_FREE_INCOMING_CONNECTIONS:
				if (isVerbose)              
					printf("The server is full.\n");

				break;

			case ID_ALREADY_CONNECTED:
				if (isVerbose)              
					printf("Already connected\n");

				break;

			case ID_DISCONNECTION_NOTIFICATION:
				if (isVerbose)
					printf("We have been disconnected.\n");
				break;
			case ID_CONNECTION_LOST:
				if (isVerbose)
					printf("Connection lost.\n");

				break;
			default:

				break;
			}

			server->DeallocatePacket(packet);

			// Stay in the loop as long as there are more packets.
			packet = server->Receive();
		}

		for (int i=0;i<clientNum;i++)//Receive for all peers
		{

			packet=clientList[i]->Receive();
			if (isVerbose&&packet)
				printf("For peer %i\n",i);

			while(packet)
			{

				switch (packet->data[0])
				{
				case ID_REMOTE_DISCONNECTION_NOTIFICATION:
					if (isVerbose)
						printf("Another client has disconnected.\n");

					break;
				case ID_REMOTE_CONNECTION_LOST:
					if (isVerbose)
						printf("Another client has lost the connection.\n");

					break;
				case ID_REMOTE_NEW_INCOMING_CONNECTION:
					if (isVerbose)              
						printf("Another client has connected.\n");
					break;
				case ID_CONNECTION_REQUEST_ACCEPTED:
					if (isVerbose)              
						printf("Our connection request has been accepted.\n");

					break;
				case ID_CONNECTION_ATTEMPT_FAILED:
					if (isVerbose)
						printf("A connection has failed.\n");

					break;

				case ID_NEW_INCOMING_CONNECTION:
					if (isVerbose)              
						printf("A connection is incoming.\n");

					break;
				case ID_NO_FREE_INCOMING_CONNECTIONS:
					if (isVerbose)              
						printf("The server is full.\n");

					break;

				case ID_ALREADY_CONNECTED:
					if (isVerbose)              
						printf("Already connected\n");

					break;

				case ID_DISCONNECTION_NOTIFICATION:
					if (isVerbose)
						printf("We have been disconnected.\n");
					break;
				case ID_CONNECTION_LOST:
					if (isVerbose)
						printf("Connection lost.\n");

					break;
				default:

					break;
				}

				clientList[i]->DeallocatePacket(packet);

				// Stay in the loop as long as there are more packets.
				packet = clientList[i]->Receive();
			}
		}
		RakSleep(0);//If needed for testing
	}

	//Connect

	for (int i=0;i<clientNum;i++)
	{

		currentSystem.SetBinaryAddress("127.0.0.1");
		currentSystem.port=60000;

		if(!CommonFunctions::ConnectionStateMatchesOptions (clientList[i],currentSystem,true,true,true,true) )//Are we connected or is there a pending operation ?
		{

			if (clientList[i]->Connect("127.0.0.1", 60000, 0,0)!=CONNECTION_ATTEMPT_STARTED)
			{

				clientList[i]->GetSystemList(systemList,guidList);//Get connectionlist
				int len=systemList.Size();

				if (isVerbose)
					DebugTools::ShowError("Problem while calling connect. \n",!noPauses && isVerbose,__LINE__,__FILE__);

				return 1;//This fails the test, don't bother going on.

			}
		}

	}

	entryTime=GetTimeMS();

	while(GetTimeMS()-entryTime<5000)//Run for 5 Secoonds
	{

		//Server receive

		packet=server->Receive();
		if (isVerbose&&packet)
			printf("For server\n");

		while(packet)
		{

			switch (packet->data[0])
			{
			case ID_REMOTE_DISCONNECTION_NOTIFICATION:
				if (isVerbose)
					printf("Another client has disconnected.\n");

				break;
			case ID_REMOTE_CONNECTION_LOST:
				if (isVerbose)
					printf("Another client has lost the connection.\n");

				break;
			case ID_REMOTE_NEW_INCOMING_CONNECTION:
				if (isVerbose)              
					printf("Another client has connected.\n");
				break;
			case ID_CONNECTION_REQUEST_ACCEPTED:
				if (isVerbose)              
					printf("Our connection request has been accepted.\n");

				break;
			case ID_CONNECTION_ATTEMPT_FAILED:
				if (isVerbose)
					printf("A connection has failed.\n");

				break;

			case ID_NEW_INCOMING_CONNECTION:
				if (isVerbose)              
					printf("A connection is incoming.\n");

				break;
			case ID_NO_FREE_INCOMING_CONNECTIONS:
				if (isVerbose)              
					printf("The server is full.\n");

				break;

			case ID_ALREADY_CONNECTED:
				if (isVerbose)              
					printf("Already connected\n");

				break;

			case ID_DISCONNECTION_NOTIFICATION:
				if (isVerbose)
					printf("We have been disconnected.\n");
				break;
			case ID_CONNECTION_LOST:
				if (isVerbose)
					printf("Connection lost.\n");

				break;
			default:

				break;
			}

			server->DeallocatePacket(packet);

			// Stay in the loop as long as there are more packets.
			packet = server->Receive();
		}

		for (int i=0;i<clientNum;i++)//Receive for all clients
		{

			packet=clientList[i]->Receive();
			if (isVerbose&&packet)
				printf("For peer %i\n",i);

			while(packet)
			{

				switch (packet->data[0])
				{
				case ID_REMOTE_DISCONNECTION_NOTIFICATION:
					if (isVerbose)
						printf("Another client has disconnected.\n");

					break;
				case ID_REMOTE_CONNECTION_LOST:
					if (isVerbose)
						printf("Another client has lost the connection.\n");

					break;
				case ID_REMOTE_NEW_INCOMING_CONNECTION:
					if (isVerbose)              
						printf("Another client has connected.\n");
					break;
				case ID_CONNECTION_REQUEST_ACCEPTED:
					if (isVerbose)              
						printf("Our connection request has been accepted.\n");

					break;
				case ID_CONNECTION_ATTEMPT_FAILED:
					if (isVerbose)
						printf("A connection has failed.\n");

					break;

				case ID_NEW_INCOMING_CONNECTION:
					if (isVerbose)              
						printf("A connection is incoming.\n");

					break;
				case ID_NO_FREE_INCOMING_CONNECTIONS:
					if (isVerbose)              
						printf("The server is full.\n");

					break;

				case ID_ALREADY_CONNECTED:
					if (isVerbose)              
						printf("Already connected\n");

					break;

				case ID_DISCONNECTION_NOTIFICATION:
					if (isVerbose)
						printf("We have been disconnected.\n");
					break;
				case ID_CONNECTION_LOST:
					if (isVerbose)
						printf("Connection lost.\n");

					break;
				default:

					break;
				}

				clientList[i]->DeallocatePacket(packet);

				// Stay in the loop as long as there are more packets.
				packet = clientList[i]->Receive();
			}
		}
		RakSleep(0);//If needed for testing
	}

	for (int i=0;i<clientNum;i++)
	{

		clientList[i]->GetSystemList(systemList,guidList);
		int connNum=guidList.Size();//Get the number of connections for the current peer
		if (connNum!=1)//Did we connect to all?
		{

			if (isVerbose)
				printf("Not all clients reconnected normally.\nFailed on clients number %i\n",i);

			if (isVerbose)
				DebugTools::ShowError("",!noPauses && isVerbose,__LINE__,__FILE__);

		
			

			return 2;

		}

	}

	

	if (isVerbose)
		printf("Pass\n");
	return 0;

}
void CharactersLoop(CONNECT_INFO* cfg, Ref< UsersPool > OnlineUsers, Ref< CrossThreadQueue< string > > OutputQueue) {
    // Initialize the RakPeerInterface used throughout the entire server
    RakPeerInterface* rakServer = RakNetworkFactory::GetRakPeerInterface();

    // Initialize the PacketFileLogger plugin (for the logs)
    PacketFileLogger* msgFileHandler = NULL;
    if (cfg->logFile) {
        msgFileHandler = new PacketFileLogger();
        rakServer->AttachPlugin(msgFileHandler);
    }

    // Initialize security IF user has enabled it in config.ini
    InitSecurity(rakServer, cfg->useEncryption);

    // Initialize the SocketDescriptor
    SocketDescriptor socketDescriptor(cfg->listenPort, 0);

    // If the startup of the server is successful, print it to the console
    // Otherwise, quit the server (as the char server is REQUIRED for the
    // server to function properly)
    if (rakServer->Startup(8, 30, &socketDescriptor, 1)) {
        stringstream s;
        s << "Characters started! Listening on: " << cfg->listenPort << "\n";
        OutputQueue->Insert(s.str());
    } else exit(2);

    // Set max incoming connections to 8
    rakServer->SetMaximumIncomingConnections(8);

    // If msgFileHandler is not NULL, save logs of char server
    if (msgFileHandler != NULL) msgFileHandler->StartLog(".\\logs\\char");

    // Initialize the Packet class for the packets
    Packet* packet;

    // This will be used in the saving of packets below...
    int i = 0;

    while (!LUNIterminate) {
        RakSleep(30);	// This sleep keeps RakNet responsive
        packet = rakServer->Receive(); // Recieve the packets from the server
        if (packet == NULL) continue; // If packet is NULL, just continue without processing anything
        PrintPacketInfo(packet, msgFileHandler); // Save packet info

        // This will save all packets recieved from the client if running from DEBUG
#ifdef DEBUG
        stringstream packetName;
        packetName << ".//Saves//Packet" << i << ".bin";

        SavePacket(packetName.str(), (char *)packet->data, packet->length);
        i++;
#endif

        switch (packet->data[0]) {
        case ID_LEGO_PACKET:

            switch (packet->data[1]) {
            case GENERAL:
                if (packet->data[3] == VERSION_CONFIRM) {	// thats just a formality so far since no other numbers occured for this case
                    SendInitPacket(rakServer, packet->systemAddress, false);
                }
                break;

            case SERVER:

                switch (packet->data[3]) {
                case CLIENT_VALIDATION:
                {
                    cout << "Recieved client validation..." << endl;
                    break;
                }

                case CLIENT_CHARACTER_LIST_REQUEST:
                {
                    auto usr = OnlineUsers->Find(packet->systemAddress);
                    if (usr->nameInUse == 0) {
                        cout << "Sending char packet...";
                        SendCharPacket(rakServer, packet->systemAddress, usr);
                    }
                    break;
                }

                case CLIENT_CHARACTER_CREATE_REQUEST:
                {
                    // Find online user by systemAddress
                    auto usr = OnlineUsers->Find(packet->systemAddress);

                    // Make SURE user is not null!!!!!!
                    if (usr != NULL) {
                        AddCharToDatabase(rakServer, packet->systemAddress, packet->data, packet->length, usr);
                    }
                    else {
                        cout << "ERROR SAVING USER: User is null." << endl;
                    }

                    // If the username is in use, do NOT send the char packet. Otherwise, send it
                    if (usr->nameInUse == 0) {
                        SendCharPacket(rakServer, packet->systemAddress, usr);
                    }
                }
                break;

                case CLIENT_CHARACTER_DELETE_REQUEST:
                {
                    // Find online user
                    auto usr = OnlineUsers->Find(packet->systemAddress);

                    // Send the delete packet
                    SendDeletePacket(rakServer, packet->systemAddress, usr, packet->data, packet->length);
                    break;
                }

                case CLIENT_LOGIN_REQUEST:
                {
                    // Find online user using systemAddress
                    auto usr = OnlineUsers->Find(packet->systemAddress);

                    // If user exists, continue
                    if (usr != NULL) {
                        usr->numredir++; // Add to the number of redirects that the character has
                        // Get Character ID
                        vector< uchar > t;
                        for (int i = 8; i <= 11; i++) t.push_back(packet->data[i]);
                        usr->nextcid = *(ulong*)t.data();

                        // If DEBUG is on, and user had ID of one of these (It probably won't)
                        // Print who the char is logging in with
#ifdef DEBUG
                        stringstream s;
                        s << "\nCharacter logging in world with id: " << usr->nextcid;
                        if ( usr->nextcid == 2397732190 ) s << " CheekyMonkey!\n";
                        else if ( usr->nextcid == 2444680020 ) s << " monkeybrown!\n";
                        else if ( usr->nextcid == 1534792735 ) s << " GruntMonkey!\n";
                        else if ( usr->nextcid == 1457240027 ) s << " Shafantastic!\n";
                        else s << "Unknown Character ID: " << usr->nextcid << endl;
                        OutputQueue->Insert(s.str());
#endif
                    }

                    // Open the packet to redirect the character to the world server
                    auto v = OpenPacket(".\\char\\char_aw_redirect.bin");
                    if (v.size() > 0) {
                        // IP Address starts at byte 0x08, Port number starts at byte 0x29
                        // Copy the redirectId to the packet
                        if (cfg->redirectIp[0] != 0)
                            memcpy(v.data() + 0x8, cfg->redirectIp, sizeof(cfg->redirectIp) - 3);	// NOTE: the IP can currently only be 13 characters long here since there are some non-zero bytes directly after the IP and I don't want to delete them (is it safe to overwrite them?)
                        // Copy the redirectPort to the packet
                        if (cfg->redirectPort > 0)
                            memcpy(v.data() + 0x29, &cfg->redirectPort, sizeof(cfg->redirectPort));
                        ServerSendPacket(rakServer, v, packet->systemAddress);
                    }

                    // Close connections to the char server for now
                    rakServer->CloseConnection(packet->systemAddress, true);
                }
                break;
                }

                break;

            // If packet ID (3rd byte) is unidentified, print the packet data
            default:
                stringstream s;

                // If packet is unidentified, print data to console
                s << "\nCharacters received unknown packet: " << RawDataToString(packet->data, packet->length) << endl;
                OutputQueue->Insert(s.str());
            }

            break;

        // Recieving a new connection to the char server
        case ID_NEW_INCOMING_CONNECTION:
#ifdef DEBUG
            OutputQueue->Insert("\n Characters is receiving a new connection...\n");
#endif
            break;

        // User disconnected from the char server
        case ID_DISCONNECTION_NOTIFICATION:
        {
            auto usr = OnlineUsers->Find(packet->systemAddress);
            if (OnlineUsers->Remove(packet->systemAddress))
                OutputQueue->Insert("Disconnected " + usr->GetUsername() + "\n");
        }
        break;

        // Default msg (if packet is unidentified)
        default:
            stringstream s;
            s << "\nCharacters received unknown packet: " << RawDataToString(packet->data, packet->length) << endl;
            OutputQueue->Insert(s.str());
        }
    }
}
int main(void)
{
	char ch;
	RakPeerInterface *rakPeer;

	// directoryDeltaTransfer is the main plugin that does the work for this sample.
	DirectoryDeltaTransfer directoryDeltaTransfer;
	// The fileListTransfer plugin is used by the DirectoryDeltaTransfer plugin and must also be registered (you could use this yourself too if you wanted, of course).
	FileListTransfer fileListTransfer;

	rakPeer = RakNetworkFactory::GetRakPeerInterface();
	rakPeer->AttachPlugin(&directoryDeltaTransfer);
	rakPeer->AttachPlugin(&fileListTransfer);
	// Get download progress notifications.  Handled by the plugin.
	rakPeer->SetSplitMessageProgressInterval(1);
	directoryDeltaTransfer.SetFileListTransferPlugin(&fileListTransfer);

	printf("This sample demonstrates the plugin to incrementally transfer compressed\n");
	printf("deltas of directories.  In essence, it's a simple autopatcher.\n");
	printf("Unlike the full autopatcher, it has no dependencies.  It is suitable for\n");
	printf("patching from non-dedicated servers at runtime.\n");
	printf("Difficulty: Intermediate\n\n");

	printf("Enter listen port. Enter for default. If running two instances on the\nsame computer, use 0 for the client.\n");
	unsigned short localPort;
	char str[256];
	gets(str);
	if (str[0]==0)
		localPort=60000;
	else
		localPort=atoi(str);
	SocketDescriptor socketDescriptor(localPort,0);
	if (rakPeer->Startup(8,30,&socketDescriptor, 1)==false)
	{
		RakNetworkFactory::DestroyRakPeerInterface(rakPeer);
		printf("RakNet initialize failed.  Possibly duplicate port.\n");
		return 1;
	}
	rakPeer->SetMaximumIncomingConnections(8);

	printf("Commands:\n");
	printf("(S)et application directory.\n");
	printf("(A)dd allowed uploads from subdirectory.\n");
	printf("(D)ownload from subdirectory.\n");
	printf("(C)lear allowed uploads.\n");
	printf("C(o)nnect to another system.\n");
	printf("(Q)uit.\n");

	RakNetTime nextStatTime = RakNet::GetTime() + 1000;

	Packet *p;
	while (1)
	{
		/*
		if (//directoryDeltaTransfer.GetNumberOfFilesForUpload()>0 &&
			RakNet::GetTime() > nextStatTime)
		{
			// If sending, periodically show connection stats
			char statData[2048];
			RakNetStatistics *statistics = rakPeer->GetStatistics(rakPeer->GetSystemAddressFromIndex(0));
		//	if (statistics->messagesOnResendQueue>0 || statistics->internalOutputQueueSize>0)
			if (rakPeer->GetSystemAddressFromIndex(0)!=UNASSIGNED_SYSTEM_ADDRESS)
			{
				StatisticsToString(statistics, statData, 2);
				printf("%s\n", statData);
			}
			
			nextStatTime=RakNet::GetTime()+5000;
		}
		*/

		// Process packets
		p=rakPeer->Receive();
		while (p)
		{
			if (p->data[0]==ID_NEW_INCOMING_CONNECTION)
				printf("ID_NEW_INCOMING_CONNECTION\n");
			else if (p->data[0]==ID_CONNECTION_REQUEST_ACCEPTED)
				printf("ID_CONNECTION_REQUEST_ACCEPTED\n");
			else if (p->data[0]==ID_DISCONNECTION_NOTIFICATION)
				printf("ID_DISCONNECTION_NOTIFICATION\n");
			else if (p->data[0]==ID_CONNECTION_LOST)
				printf("ID_CONNECTION_LOST\n");

			rakPeer->DeallocatePacket(p);
			p=rakPeer->Receive();
		}

		if (kbhit())
		{
			ch=getch();
			if (ch=='s')
			{
				printf("Enter application directory\n");
				gets(str);
				if (str[0]==0)
					strcpy(str, "C:/Temp");
				directoryDeltaTransfer.SetApplicationDirectory(str);
				printf("This directory will be prefixed to upload and download subdirectories.\n");
			}
			else if (ch=='a')
			{
				printf("Enter uploads subdirectory\n");
				gets(str);
				directoryDeltaTransfer.AddUploadsFromSubdirectory(str);
				printf("%i files for upload.\n", directoryDeltaTransfer.GetNumberOfFilesForUpload());
			}
			else if (ch=='d')
			{
				char subdir[256];
				char outputSubdir[256];
				printf("Enter remote subdirectory to download from.\n");
				printf("This directory may be any uploaded directory, or a subdir therein.\n");
				gets(subdir);
				printf("Enter subdirectory to output to.\n");
				gets(outputSubdir);
                
				unsigned short setId;
				setId=directoryDeltaTransfer.DownloadFromSubdirectory(subdir, outputSubdir, true, rakPeer->GetSystemAddressFromIndex(0), &transferCallback, HIGH_PRIORITY, 0, 0);
				if (setId==(unsigned short)-1)
					printf("Download failed.  Host unreachable.\n");
				else
					printf("Downloading set %i\n", setId);
			}
			else if (ch=='c')
			{
				directoryDeltaTransfer.ClearUploads();
				printf("Uploads cleared.\n");
			}
			else if (ch=='o')
			{
				char host[256];
				printf("Enter host IP: ");
				gets(host);
				if (host[0]==0)
					strcpy(host, "127.0.0.1");
				unsigned short remotePort;
				printf("Enter host port: ");
				gets(str);
				if (str[0]==0)
					remotePort=60000;
				else
					remotePort=atoi(str);
				rakPeer->Connect(host, remotePort, 0, 0);
				printf("Connecting.\n");
			}
			else if (ch=='q')
			{
				printf("Bye!\n");
				rakPeer->Shutdown(1000,0);
				break;
			}
		}

		// Keeps the threads responsive
		RakSleep(0);
	}

	RakNetworkFactory::DestroyRakPeerInterface(rakPeer);

	return 0;
}
//This static method is called when the user wants to host a server
void Session::StartHost(void* pVoid){
	//A parameter list is given with needed variables
	ArgumentList* pArgumentList = (ArgumentList*)pVoid;
	RakPeerInterface *pServer;
	//Filling my fields from argument list.
	pServer=pArgumentList->inter;
	std::string password = pArgumentList->password;
	int port = pArgumentList->port;
	RakNet::RPC3* rpc3Inst = pArgumentList->rpc3;
	//map that keeps track of who is who
	std::map<RakNet::SystemAddress, std::string> clientCharacterMap;

	//Register the functions we want to call RPC3 upon
	RPC3_REGISTER_FUNCTION(rpc3Inst, ReceiveInformation);
	RPC3_REGISTER_FUNCTION(rpc3Inst, UpdateCharacter);
	RPC3_REGISTER_FUNCTION(rpc3Inst, UpdateCharacterVelocity);
	RPC3_REGISTER_FUNCTION(rpc3Inst, SyncClients);
	RPC3_REGISTER_FUNCTION(rpc3Inst, ReceiveID);
	RPC3_REGISTER_FUNCTION(rpc3Inst, RemoveCharacter);
	RPC3_REGISTER_FUNCTION(rpc3Inst, AddScore);
	
	//Set up the host using RakNet
	pServer->SetIncomingPassword(password.c_str(), (int)strlen(password.c_str()));
	pServer->SetTimeoutTime(5000,UNASSIGNED_SYSTEM_ADDRESS);
	SystemAddress clientID=UNASSIGNED_SYSTEM_ADDRESS;
	RakNet::SocketDescriptor socketDescriptor(port,0);
	socketDescriptor.socketFamily=AF_INET;
	bool b = pServer->Startup(10,&socketDescriptor, 1 );
	pServer->SetMaximumIncomingConnections(10);

	pServer->SetOccasionalPing(true);
	pServer->SetUnreliableTimeout(1000);

	DataStructures::List<RakNetSmartPtr<RakNetSocket> > sockets;
	pServer->GetSockets(sockets);	
	
	// Holds packets
	Packet* p;
	// Record the first client that connects to us so we can pass it to the ping function
	clientID=UNASSIGNED_SYSTEM_ADDRESS;

	pServer->AttachPlugin(rpc3Inst);

	char message[2048];

	// Loop for input
	while (threading)
	{
		for (p=pServer->Receive(); p; pServer->DeallocatePacket(p), p=pServer->Receive())
		{
			switch (p->data[0])
			{
			case ID_DISCONNECTION_NOTIFICATION:
				{
				printf("ID_DISCONNECTION_NOTIFICATION\n");
				RakString name(clientCharacterMap[p->systemAddress].c_str());
				RemoveCharacter(name);
				rpc3Inst->CallC("RemoveCharacter", name);
				break;
				}
			case ID_ALREADY_CONNECTED:
				printf("ID_ALREADY_CONNECTED\n");
				break;
			case ID_CONNECTION_ATTEMPT_FAILED:
				printf("Connection attempt failed\n");
				break;
			case ID_NO_FREE_INCOMING_CONNECTIONS:
				printf("ID_NO_FREE_INCOMING_CONNECTIONS\n");
				break;
			case ID_UNCONNECTED_PONG:
				// Found the server
				pServer->Connect(p->systemAddress.ToString(false),p->systemAddress.GetPort(),0,0,0);
				break;
			case ID_CONNECTION_REQUEST_ACCEPTED:
				// This tells the client they have connected
				printf("ID_CONNECTION_REQUEST_ACCEPTED\n");
				//Session::SendInformation(RakNet::RakString("The italians are invading utrecht!"), rpc3Inst, 0);
				//Game::getSingletonPtr()->
				break;
			case ID_NEW_INCOMING_CONNECTION:
			{
				//When there is a new incoming connection we are change the local player to the host
				printf("New incoming connection\n");
				Game::getSingletonPtr()->getLocalPlayer()->SetNetworkName("PlayerHost");
				std::stringstream ss, ss2;
				ss << "Client" << (Game::getSingletonPtr()->GetCharacters().size()+1);
				//create a new character for the client
				Game::getSingletonPtr()->CreateCharacter(ss.str());
				clientCharacterMap[p->systemAddress] = ss.str();

				RPC3::CallExplicitParameters params;
				params.systemAddress = p->systemAddress;
				params.broadcast = false;
				//Make sure the client knows who he is
				rpc3Inst->CallExplicit("ReceiveID", &params, RakString::RakString(ss.str().c_str()));
				ss2 << Game::getSingletonPtr()->GetCharacters().size();
				//Synchronize the players with all clients; make sure they have all the characters on the screen
				RPC3::CallExplicitParameters params2;
				//params2.systemAddress = p->systemAddress;
				params2.broadcast = true;
				rpc3Inst->CallExplicit("SyncClients", &params2, RakNet::RakString(ss2.str().c_str()));
				//rpc3Inst->CallC("SyncClients", RakNet::RakString(ss2.str().c_str()));
				break;
			}				
			case ID_RPC_REMOTE_ERROR:
				{
					// Recipient system returned an error
					switch (p->data[1])
					{
					case RakNet::RPC_ERROR_NETWORK_ID_MANAGER_UNAVAILABLE:
						printf("RPC_ERROR_NETWORK_ID_MANAGER_UNAVAILABLE\n");
						break;
					case RakNet::RPC_ERROR_OBJECT_DOES_NOT_EXIST:
						printf("RPC_ERROR_OBJECT_DOES_NOT_EXIST\n");
						break;
					case RakNet::RPC_ERROR_FUNCTION_INDEX_OUT_OF_RANGE:
						printf("RPC_ERROR_FUNCTION_INDEX_OUT_OF_RANGE\n");
						break;
					case RakNet::RPC_ERROR_FUNCTION_NOT_REGISTERED:
						printf("RPC_ERROR_FUNCTION_NOT_REGISTERED\n");
						break;
					case RakNet::RPC_ERROR_FUNCTION_NO_LONGER_REGISTERED:
						printf("RPC_ERROR_FUNCTION_NO_LONGER_REGISTERED\n");
						break;
					case RakNet::RPC_ERROR_CALLING_CPP_AS_C:
						printf("RPC_ERROR_CALLING_CPP_AS_C\n");
						break;
					case RakNet::RPC_ERROR_CALLING_C_AS_CPP:
						printf("RPC_ERROR_CALLING_C_AS_CPP\n");
						break;
					}
					printf("Function: %s", p->data+2);
				}
			}
		}
	}
	pServer->Shutdown(30,0);
	RakNet::RakPeerInterface::DestroyInstance(pServer);
	delete rpc3Inst;
}