1 #include "RakPeerInterface.h"
2 #include "RakNetworkFactory.h"
3 #include "BitStream.h"
4 #include <stdlib.h> // For atoi
5 #include <cstring> // For strlen
6 #include "Rand.h"
7 #include "RakNetStatistics.h"
8 #include "MessageIdentifiers.h"
9 #include <stdio.h>
10 #include "Kbhit.h"
11 #include "GetTime.h"
12 #include "RakAssert.h"
13 #include "RakSleep.h"
14 
15 
16 #ifdef _WIN32
17 #include "WindowsIncludes.h" // Sleep
18 #else
19 #include <unistd.h> // usleep
20 #include <cstdio>
21 #include "Getche.h"
22 #endif
23 
24 static const int NUM_CLIENTS=128;
25 #define SERVER_PORT 66666
26 #define RANDOM_DATA_SIZE 32
27 char randomData[RANDOM_DATA_SIZE];
28 char *remoteIPAddress=0;
29 
30 // Connects, sends data over time, disconnects, repeat
31 class Client
32 {
33 	public:
Client()34 		Client()
35 		{
36 			peer = RakNetworkFactory::GetRakPeerInterface();
37 		}
~Client()38 		~Client()
39 		{
40 			RakNetworkFactory::DestroyRakPeerInterface(peer);
41 		}
Startup(void)42 		void Startup(void)
43 		{
44 			SocketDescriptor socketDescriptor;
45 			socketDescriptor.port=0;
46 			nextSendTime=0;
47 			bool b = peer->Startup(1,30,&socketDescriptor,1);
48 			RakAssert(b);
49 			isConnected=false;
50 		}
Connect(void)51 		void Connect(void)
52 		{
53 			bool b;
54 			b=peer->Connect(remoteIPAddress, (unsigned short) SERVER_PORT, 0, 0, 0);
55 			if (b==false)
56 			{
57 				printf("Client connect call failed!\n");
58 			}
59 		}
Disconnect(void)60 		void Disconnect(void)
61 		{
62 			peer->CloseConnection(peer->GetSystemAddressFromIndex(0),true,0);
63 			isConnected=false;
64 		}
Update(RakNetTime curTime)65 		void Update(RakNetTime curTime)
66 		{
67 			Packet *p = peer->Receive();
68 			while (p)
69 			{
70 				switch (p->data[0])
71 				{
72 				case ID_CONNECTION_REQUEST_ACCEPTED:
73 					printf("ID_CONNECTION_REQUEST_ACCEPTED\n");
74 					isConnected=true;
75 					break;
76 					// print out errors
77 				case ID_CONNECTION_ATTEMPT_FAILED:
78 					printf("Client Error: ID_CONNECTION_ATTEMPT_FAILED\n");
79 					isConnected=false;
80 					break;
81 				case ID_ALREADY_CONNECTED:
82 					printf("Client Error: ID_ALREADY_CONNECTED\n");
83 					break;
84 				case ID_CONNECTION_BANNED:
85 					printf("Client Error: ID_CONNECTION_BANNED\n");
86 					break;
87 				case ID_INVALID_PASSWORD:
88 					printf("Client Error: ID_INVALID_PASSWORD\n");
89 					break;
90 				case ID_INCOMPATIBLE_PROTOCOL_VERSION:
91 					printf("Client Error: ID_INCOMPATIBLE_PROTOCOL_VERSION\n");
92 					break;
93 				case ID_NO_FREE_INCOMING_CONNECTIONS:
94 					printf("Client Error: ID_NO_FREE_INCOMING_CONNECTIONS\n");
95 					isConnected=false;
96 					break;
97 				case ID_DISCONNECTION_NOTIFICATION:
98 					//printf("ID_DISCONNECTION_NOTIFICATION\n");
99 					isConnected=false;
100 					break;
101 				case ID_CONNECTION_LOST:
102 					printf("Client Error: ID_CONNECTION_LOST\n");
103 					isConnected=false;
104 					break;
105 				case ID_MODIFIED_PACKET:
106 					printf("Client Error: ID_MODIFIED_PACKET\n");
107 					break;
108 				}
109 				peer->DeallocatePacket(p);
110 				p = peer->Receive();
111 
112 			}
113 
114 			if (curTime>nextSendTime && isConnected)
115 			{
116 				peer->Send((const char*)&randomData,RANDOM_DATA_SIZE,HIGH_PRIORITY,RELIABLE_ORDERED,0,UNASSIGNED_SYSTEM_ADDRESS,true);
117 				nextSendTime=curTime+30;
118 			}
119 		}
120 
121 		bool isConnected;
122 		RakPeerInterface *peer;
123 		RakNetTime nextSendTime;
124 };
125 
126 // Just listens for ID_USER_PACKET_ENUM and validates its integrity
127 class Server
128 {
129 	public:
Server()130 		Server()
131 		{
132 			peer = RakNetworkFactory::GetRakPeerInterface();
133 		}
~Server()134 		~Server()
135 		{
136 			RakNetworkFactory::DestroyRakPeerInterface(peer);
137 		}
Start(void)138 		void Start(void)
139 		{
140 			SocketDescriptor socketDescriptor;
141 			socketDescriptor.port=(unsigned short) SERVER_PORT;
142 			bool b = peer->Startup((unsigned short) NUM_CLIENTS,0,&socketDescriptor,1);
143 			RakAssert(b);
144 			peer->SetMaximumIncomingConnections(NUM_CLIENTS);
145 		}
ConnectionCount(void) const146 		unsigned ConnectionCount(void) const
147 		{
148 			unsigned i,count;
149 			for (i=0,count=0; i < NUM_CLIENTS;i++)
150 				if (peer->GetSystemAddressFromIndex(i)!=UNASSIGNED_SYSTEM_ADDRESS)
151 					count++;
152 			return count;
153 		}
Update(RakNetTime curTime)154 		void Update(RakNetTime curTime)
155 		{
156 			Packet *p = peer->Receive();
157 			while (p)
158 			{
159 				switch (p->data[0])
160 				{
161 				case ID_CONNECTION_LOST:
162 				case ID_DISCONNECTION_NOTIFICATION:
163 				case ID_NEW_INCOMING_CONNECTION:
164 					printf("Connections = %i\n", ConnectionCount());
165 					break;
166 				case ID_USER_PACKET_ENUM:
167 					{
168 						if (memcmp(p->data, randomData, RANDOM_DATA_SIZE)!=0)
169 						{
170 							printf("Bad data on server!\n");
171 						}
172 						break;
173 					}
174 				}
175 				peer->DeallocatePacket(p);
176 				p = peer->Receive();
177 			}
178 		}
179 
180 
181 		RakPeerInterface *peer;
182 };
183 
main(void)184 int main(void)
185 {
186 	Client clients[NUM_CLIENTS];
187 	Server server;
188 //	int clientIndex;
189 	int mode;
190 
191 	printf("Connects many clients to a single server.\n");
192 	printf("Difficulty: Intermediate\n\n");
193 	printf("Run as (S)erver or (C)lient or (B)oth? ");
194 	char ch = getche();
195 	static char *remoteIP="94.198.81.195";
196 	static char *localIP="127.0.0.1";
197 	if (ch=='s' || ch=='S')
198 		mode=0;
199 	else if (ch=='c' || ch=='c')
200 	{
201 		mode=1;
202 		remoteIPAddress=remoteIP;
203 	}
204 	else
205 	{
206 		mode=2;
207 		remoteIPAddress=localIP;
208 	}
209 	printf("\n");
210 
211 	unsigned i;
212 	randomData[0]=ID_USER_PACKET_ENUM;
213 	for (i=0; i < RANDOM_DATA_SIZE-1; i++)
214 		randomData[i+1]=i;
215 
216 	if (mode==0 || mode==2)
217 	{
218 		server.Start();
219 		printf("Started server\n");
220 	}
221 	if (mode==1 || mode==2)
222 	{
223 		printf("Starting clients...\n");
224 		for (i=0; i < NUM_CLIENTS; i++)
225 			clients[i].Startup();
226 		printf("Started clients\n");
227 		printf("Connecting clients...\n");
228 		for (i=0; i < NUM_CLIENTS; i++)
229 			clients[i].Connect();
230 		printf("Done.\n");
231 	}
232 
233 	RakNetTime endTime = RakNet::GetTime()+60000*5;
234 	RakNetTime time = RakNet::GetTime();
235 	while (time < endTime)
236 	{
237 		if (mode==0 || mode==2)
238 			server.Update(time);
239 		if (mode==1 || mode==2)
240 		{
241 			for (i=0; i < NUM_CLIENTS; i++)
242 				clients[i].Update(time);
243 		}
244 
245 		if (kbhit())
246 		{
247 			char ch = getch();
248 			if (ch==' ')
249 			{
250 				FILE *fp;
251 				char text[2048];
252 				if (mode==0 || mode==2)
253 				{
254 					printf("Logging server statistics to ServerStats.txt\n");
255 					fp=fopen("ServerStats.txt","wt");
256 					for (i=0; i < NUM_CLIENTS; i++)
257 					{
258 						RakNetStatistics *rssSender;
259 						rssSender=server.peer->GetStatistics(server.peer->GetSystemAddressFromIndex(i));
260 						StatisticsToString(rssSender, text, 3);
261 						fprintf(fp,"==== System %i ====\n", i+1);
262 						fprintf(fp,"%s\n\n", text);
263 					}
264 					fclose(fp);
265 				}
266 				if (mode==1 || mode==2)
267 				{
268 					printf("Logging client statistics to ClientStats.txt\n");
269 					fp=fopen("ClientStats.txt","wt");
270 					for (i=0; i < NUM_CLIENTS; i++)
271 					{
272 						RakNetStatistics *rssSender;
273 						rssSender=clients[i].peer->GetStatistics(clients[i].peer->GetSystemAddressFromIndex(0));
274 						StatisticsToString(rssSender, text, 3);
275 						fprintf(fp,"==== Client %i ====\n", i+1);
276 						fprintf(fp,"%s\n\n", text);
277 					}
278 					fclose(fp);
279 				}
280 			}
281 			if (ch=='q' || ch==0)
282 				break;
283 		}
284 
285 		time = RakNet::GetTime();
286 		RakSleep(30);
287 	}
288 
289 	if (mode==0 || mode==2)
290 		server.peer->Shutdown(0);
291 	if (mode==1 || mode==2)
292 		for (i=0; i < NUM_CLIENTS; i++)
293 			clients[i].peer->Shutdown(0);
294 
295 	printf("Test completed");
296 	return 0;
297 }
298