1 #include "MasterClient.h"
2 #include "RakPeerInterface.h"
3 #include "PacketEnumerations.h"
4 #include "RakNetworkFactory.h"
5 #include "StringCompressor.h"
6 #include "GetTime.h"
7 #include <cstring>
8 
9 // Uncomment this define for debugging printfs
10 #define _SHOW_MASTER_SERVER_PRINTF
11 #ifdef _SHOW_MASTER_SERVER_PRINTF
12 #include <cstdio>
13 #endif
14 
MasterClient()15 MasterClient::MasterClient()
16 {
17 }
18 
~MasterClient()19 MasterClient::~MasterClient()
20 {
21 	ClearServerList();
22 }
23 
Connect(char * host,int masterServerPort)24 bool MasterClient::Connect(char* host, int masterServerPort)
25 {
26 	localServer.Clear();
27 	listServer=serverListed=localServerModified=false;
28 	localServer.connectionIdentifier.port=rakPeer->GetInternalID().port;
29 	ruleIdentifierList.Reset();
30 
31 	return rakPeer->Connect(host, masterServerPort, 0, 0);
32 }
33 
Disconnect(void)34 void MasterClient::Disconnect(void)
35 {
36 	if (IsConnected())
37 		DelistServer();
38 
39 	rakPeer->Disconnect(100);
40 }
41 
IsConnected(void)42 bool MasterClient::IsConnected(void)
43 {
44 	unsigned short numberOfSystems;
45 	rakPeer->GetConnectionList(0, &numberOfSystems);
46 	return numberOfSystems==1;
47 }
48 
AddQueryRule(char * ruleIdentifier)49 void MasterClient::AddQueryRule(char *ruleIdentifier)
50 {
51 	if (ruleIdentifier && IsReservedRuleIdentifier(ruleIdentifier)==false)
52 		stringCompressor->EncodeString(ruleIdentifier, 256, &ruleIdentifierList);
53 }
ClearQueryRules(void)54 void MasterClient::ClearQueryRules(void)
55 {
56 	ruleIdentifierList.Reset();
57 }
QueryMasterServer(void)58 void MasterClient::QueryMasterServer(void)
59 {
60 	BitStream outgoingBitStream;
61 	// Request to the master server for the list of servers that contain at least one of the specified keys
62 	outgoingBitStream.Write((unsigned char)ID_QUERY_MASTER_SERVER);
63 	if (ruleIdentifierList.GetNumberOfBitsUsed()>0)
64 		outgoingBitStream.WriteBits(ruleIdentifierList.GetData(), ruleIdentifierList.GetNumberOfBitsUsed(), false);
65     rakPeer->Send(&outgoingBitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_PLAYER_ID, true);
66 }
67 
PingServers(void)68 void MasterClient::PingServers(void)
69 {
70 	unsigned serverIndex;
71 
72 	for (serverIndex=0; serverIndex < gameServerList.serverList.Size(); serverIndex++)
73 	{
74 		rakPeer->Ping((char*)rakPeer->PlayerIDToDottedIP(gameServerList.serverList[serverIndex]->connectionIdentifier),
75 			gameServerList.serverList[serverIndex]->connectionIdentifier.port, false);
76 	}
77 }
78 
Update(RakPeerInterface * peer)79 void MasterClient::Update(RakPeerInterface *peer)
80 {
81 	BitStream outgoingBitStream;
82 
83 	if (listServer && ((serverListed && localServerModified) || (serverListed==false)))
84 	{
85 		outgoingBitStream.Write((unsigned char)ID_MASTER_SERVER_SET_SERVER);
86 		SerializeServer(&localServer, &outgoingBitStream);
87 		rakPeer->Send(&outgoingBitStream, MEDIUM_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_PLAYER_ID, true);
88 		serverListed=true;
89 		localServerModified=false;
90 	}
91 }
92 
OnReceive(RakPeerInterface * peer,Packet * packet)93 bool MasterClient::OnReceive(RakPeerInterface *peer, Packet *packet)
94 {
95 	switch(packet->data[0])
96 	{
97 	case ID_NO_FREE_INCOMING_CONNECTIONS:
98 		OnMasterServerFull();
99 		return false; // Do not absorb packet
100 	case ID_DISCONNECTION_NOTIFICATION:
101 		OnLostConnection();
102 		return false; // Do not absorb packet
103 	case ID_CONNECTION_LOST:
104 		OnLostConnection();
105 		return false; // Do not absorb packet
106 	case ID_MODIFIED_PACKET:
107 		OnModifiedPacket();
108 		return false;
109 	case ID_CONNECTION_ATTEMPT_FAILED:
110 		OnConnectionAttemptFailed();
111 		return false; // Do not absorb packet
112 	case ID_MASTER_SERVER_UPDATE_SERVER:
113 		HandleServerListResponse(packet, false);
114 		return true; // Absorb packet
115 	case ID_MASTER_SERVER_SET_SERVER:
116 		HandleServerListResponse(packet, true);
117 		return true; // Absorb packet
118 	case ID_PONG:
119 		HandlePong(packet);
120 		return false; // Absorb packet
121 	case ID_RELAYED_CONNECTION_NOTIFICATION:
122 		HandleRelayedConnectionNotification(packet);
123 		return true; // Absorb packet
124 	}
125 
126 	return 0;
127 }
128 
ConnectionAttemptNotification(char * serverIP,unsigned short serverPort)129 void MasterClient::ConnectionAttemptNotification(char *serverIP, unsigned short serverPort)
130 {
131 	if (serverIP==0)
132 		return;
133 
134 	BitStream bitStream(23);
135 	bitStream.Write((unsigned char)ID_RELAYED_CONNECTION_NOTIFICATION);
136 	bitStream.Write(localServer.connectionIdentifier.port); // Your own game client port
137 	bitStream.Write(serverPort); // The game server you are connecting to port
138 	stringCompressor->EncodeString(serverIP, 22, &bitStream); // The game server IP you are connecting to
139 	rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE, 0, UNASSIGNED_PLAYER_ID, true);
140 }
ListServer(void)141 void MasterClient::ListServer(void)
142 {
143 	listServer=true;
144 }
DelistServer(void)145 void MasterClient::DelistServer(void)
146 {
147 	BitStream bitStream;
148 	listServer=false;
149 	if (serverListed)
150 	{
151 		bitStream.Write((unsigned char)ID_MASTER_SERVER_DELIST_SERVER);
152 		bitStream.Write(localServer.connectionIdentifier.port);
153         rakPeer->Send(&bitStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_PLAYER_ID, true);
154 		serverListed=false;
155 	}
156 }
HandleServerListResponse(Packet * packet,bool overwriteExisting)157 void MasterClient::HandleServerListResponse(Packet *packet, bool overwriteExisting)
158 {
159 	int serverIndex;
160 	bool newServerAdded;
161 	unsigned short numberOfServers;
162 	GameServer *gameServer;
163 	RakNetTime currentTime;
164 	BitStream inputBitStream(packet->data, packet->length, false);
165 	inputBitStream.IgnoreBits(8*sizeof(unsigned char));
166 
167 	if (inputBitStream.ReadCompressed(numberOfServers)==false)
168 		return;
169 
170 	currentTime=RakNet::GetTime();
171 
172 	for (serverIndex=0; serverIndex < numberOfServers; serverIndex++)
173 	{
174 		gameServer = DeserializeServer(&inputBitStream);
175 
176 		// Find the existing game server that matches this port/address.
177 		// If not found, then add it to the list.
178 		// else update it
179 		// If (overwriteExisting)
180 		// - Delete any fields that exist in the old and not in the new
181 		// Add any fields that exist in the new and do not exist in the old
182 		// Update any fields that exist in both
183 		// Unset the deletion mark
184 		gameServer=UpdateServerList(gameServer,overwriteExisting, &newServerAdded);
185 		if (newServerAdded)
186 		{
187 			// Ping the new server
188 			rakPeer->Ping((char*)rakPeer->PlayerIDToDottedIP(gameServer->connectionIdentifier),
189 				gameServer->connectionIdentifier.port, false);
190 
191 			// Returns true if new server updated
192 			OnGameServerListAddition(gameServer);
193 		}
194 		else
195 		{
196 			// returns false if an existing server is modified
197 			OnGameServerListRuleUpdate(gameServer);
198 		}
199 
200 
201 	}
202 
203 	// Any servers that were not updated on the last call to UpdateServerList
204 	// will have lastUpdateTime time as less than the current time
205 	// Delete those
206 	serverIndex=0;
207 	while (serverIndex < (int) gameServerList.serverList.Size())
208 	{
209 		if (gameServerList.serverList[serverIndex]->lastUpdateTime < currentTime)
210 		{
211 			delete gameServerList.serverList[serverIndex];
212 			gameServerList.serverList.RemoveAtIndex(serverIndex);
213 		}
214 		else
215 			serverIndex++;
216 	}
217 
218 	OnGameServerListQueryComplete();
219 }
HandleRelayedConnectionNotification(Packet * packet)220 void MasterClient::HandleRelayedConnectionNotification(Packet *packet)
221 {
222 	PlayerID clientSystem;
223 	BitStream incomingBitStream(packet->data, packet->length, false);
224 	incomingBitStream.IgnoreBits(8*sizeof(unsigned char));
225 	incomingBitStream.Read(clientSystem.binaryAddress);
226 	incomingBitStream.Read(clientSystem.port);
227 
228 	OnConnectionRequest(rakPeer->PlayerIDToDottedIP(clientSystem), clientSystem.port);
229 }
PostRule(char * ruleIdentifier,char * stringData,int intData)230 void MasterClient::PostRule(char *ruleIdentifier, char *stringData, int intData)
231 {
232 	if (ruleIdentifier)
233 	{
234 		if (IsReservedRuleIdentifier(ruleIdentifier))
235 			return;
236 
237 		localServerModified |= UpdateServerRule(&localServer, ruleIdentifier, stringData, intData);
238 	}
239 }
240 
RemoveRule(char * ruleIdentifier)241 void MasterClient::RemoveRule(char *ruleIdentifier)
242 {
243 	if (ruleIdentifier)
244 		localServerModified |= RemoveServerRule(&localServer, ruleIdentifier);
245 }
246 
OnLostConnection(void)247 void MasterClient::OnLostConnection(void)
248 {
249 #ifdef _SHOW_MASTER_SERVER_PRINTF
250 	printf("Connection lost.\n");
251 #endif
252 }
OnConnectionAttemptFailed(void)253 void MasterClient::OnConnectionAttemptFailed(void)
254 {
255 #ifdef _SHOW_MASTER_SERVER_PRINTF
256 	printf("Connection attempt failed.\n");
257 #endif
258 }
OnMasterServerFull(void)259 void MasterClient::OnMasterServerFull(void)
260 {
261 #ifdef _SHOW_MASTER_SERVER_PRINTF
262 	printf("Server full.\n");
263 #endif
264 }
OnModifiedPacket(void)265 void MasterClient::OnModifiedPacket(void)
266 {
267 #ifdef _SHOW_MASTER_SERVER_PRINTF
268 	printf("Modified packet.\n");
269 #endif
270 }
OnGameServerListAddition(GameServer * newServer)271 void MasterClient::OnGameServerListAddition(GameServer *newServer)
272 {
273 #ifdef _SHOW_MASTER_SERVER_PRINTF
274 	printf("Server added.\n");
275 #endif
276 }
OnGameServerListRuleUpdate(GameServer * updatedServer)277 void MasterClient::OnGameServerListRuleUpdate(GameServer *updatedServer)
278 {
279 #ifdef _SHOW_MASTER_SERVER_PRINTF
280 	printf("Rules updated for a server.\n");
281 #endif
282 }
OnGameServerListQueryComplete(void)283 void MasterClient::OnGameServerListQueryComplete(void)
284 {
285 #ifdef _SHOW_MASTER_SERVER_PRINTF
286 	printf("Query complete.\n");
287 #endif
288 }
289 // Event when a game client wants to connect to our server
290 // You should call AdvertiseSystem to the passed IP and port from your game instance
OnConnectionRequest(const char * clientIP,unsigned short clientPort)291 void MasterClient::OnConnectionRequest(const char *clientIP, unsigned short clientPort)
292 {
293 #ifdef _SHOW_MASTER_SERVER_PRINTF
294 	printf("Master client indicates a connection request from %s:%i.\n", clientIP, clientPort);
295 #endif
296 	rakPeer->AdvertiseSystem((char*)clientIP, clientPort,0,0);
297 }
298