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