Linux multi-monitor fullscreen support
[ryzomcore.git] / nel / samples / net / udp / client.cpp
blob0cdb98c531cf5fea37a29dc5390031f6a59650ba
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 // Includes
22 #include "nel/misc/types_nl.h"
23 #include "nel/misc/debug.h"
24 #include "nel/misc/common.h"
25 #include "nel/misc/mem_stream.h"
26 #include "nel/misc/time_nl.h"
27 #include "nel/misc/config_file.h"
29 #include "nel/net/udp_sock.h"
30 #include "nel/net/callback_client.h"
31 #include "nel/net/inet_address.h"
32 #include "nel/net/udp_sim_sock.h"
34 #include "graph.h"
37 #ifdef USE_3D
39 #include "nel/3d/u_driver.h"
40 #include "nel/3d/u_scene.h"
41 #include "nel/3d/u_camera.h"
42 #include "nel/3d/u_instance.h"
43 #include "nel/3d/u_animation_set.h"
44 #include "nel/3d/u_play_list.h"
45 #include "nel/3d/u_play_list_manager.h"
46 #include "nel/3d/u_text_context.h"
47 #include "nel/3d/u_texture.h"
48 #include "nel/3d/event_mouse_listener.h"
50 using namespace NL3D;
51 #endif
53 #ifndef UDP_DIR
54 #define UDP_DIR "."
55 #endif // UDP_DIR
58 // Namespaces
61 using namespace std;
62 using namespace NLMISC;
63 using namespace NLNET;
66 // Variables
69 // must be increase at each version and must be the same value as the server
70 uint32 Version = 2;
72 string ServerAddr = "itsalive.nevrax.org"; // ldserver
73 uint16 UDPPort = 45455;
74 uint16 TCPPort = 45456;
76 uint32 MaxUDPPacketSize = 1000;
78 CUdpSimSock *UdpSock = NULL;
80 uint8 Mode = 0;
82 uint64 Session = 0;
84 string ConnectionName;
86 CConfigFile ConfigFile;
88 #ifdef USE_3D
90 CGraph FpsGraph ("frame rate (fps)", 10.0f, 110.0f, 100.0f, 100.0f, CRGBA(128,0,0,128), 1000, 150.0f);
91 CGraph DownloadGraph ("download (bps)", 10.0f, 260.0f, 100.0f, 100.0f, CRGBA(0,0,128,128), 1000, 20000.0f);
92 CGraph UploadGraph ("upload (bps)", 10.0f, 360.0f, 100.0f, 100.0f, CRGBA(0,128,128,128), 1000, 20000.0f);
93 CGraph LagGraph ("lag (ms)", 150.0f, 110.0f, 100.0f, 100.0f, CRGBA(128,64,64,128), 100000, 2000.0f);
95 #endif
98 // Functions
101 void exit (const string &reason)
103 if (!reason.empty())
104 InfoLog->displayRawNL ("%s", reason.c_str());
105 InfoLog->displayRawNL ("Press <enter> to exit");
106 getchar ();
107 exit(EXIT_FAILURE);
111 // Config file functions
114 void createConfigFile()
116 FILE *fp = nlfopen ("client.cfg", "wt");
117 if (fp == NULL)
119 InfoLog->displayRawNL ("Can't create client.cfg");
121 else
123 fprintf (fp, "ServerAddress = \"%s\";\n", ServerAddr.c_str());
124 fprintf (fp, "SimInLag = 0;\n");
125 fprintf (fp, "SimInPacketLost = 0;\n");
126 fprintf (fp, "SimOutLag = 0;\n");
127 fprintf (fp, "SimOutPacketLost = 0;\n");
128 fprintf (fp, "SimOutPacketDuplication = 0;\n");
129 fprintf (fp, "SimOutPacketDisordering = 0;\n");
130 fprintf (fp, "ConnectionName = \"\";\n");
131 fclose (fp);
135 void checkConnectionName ()
137 if (ConnectionName.size() > 30)
139 exit ("Bad connection name (must be <= 30 characters)");
142 if (ConnectionName.size() > 0 && ConnectionName[ConnectionName.size()-1] == '\n')
144 ConnectionName = ConnectionName.substr (0, ConnectionName.size()-1);
147 if (ConnectionName.size() <= 0)
149 exit ("Bad connection name (must be > 0 character)");
152 for (uint i = 0; i < ConnectionName.size(); i++)
154 if (!isalnum(ConnectionName[i]))
156 exit ("Bad connection name, only alpha numeric characters is allowed (char '%c' is not alphanum)");
161 void loadConfigFile ()
163 FILE *fp = nlfopen ("client.cfg", "rt");
164 if (fp == NULL)
166 createConfigFile();
168 else
170 fclose (fp);
173 ConfigFile.load ("client.cfg");
175 // set internet simulation values
176 CUdpSimSock::setSimValues (ConfigFile);
178 ServerAddr = ConfigFile.getVar("ServerAddress").asString();
180 ConnectionName = ConfigFile.getVar("ConnectionName").asString();
182 if (ConnectionName.empty())
184 InfoLog->displayRawNL ("Please, enter a connection name");
185 InfoLog->displayRawNL ("(only alphanumeric character limited to 30 character, no space)");
186 InfoLog->displayRawNL ("For example enter your name and/or your location (ie: \"AceHome\"),");
187 InfoLog->displayRawNL ("It'll be use to find your stat file easier:");
188 char cn[128];
189 if (fgets (cn, 127, stdin) == NULL)
191 exit ("Error during the keyboard scanning");
193 ConnectionName = cn;
194 checkConnectionName ();
195 ConfigFile.getVar ("ConnectionName").setAsString(ConnectionName);
196 ConfigFile.save ();
198 else
200 checkConnectionName ();
206 // Callbacks
209 void cbInfo (CMessage &msgin, TSockId from, CCallbackNetBase &netbase)
211 string line;
212 msgin.serial (line);
213 InfoLog->displayRawNL ("%s", line.c_str());
215 #ifdef USE_3D
216 string token = "MeanPongTime ";
217 string::size_type pos=line.find (token);
218 string::size_type pos2=line.find (" ", pos+token.size());
219 float val;
220 NLMISC::fromString(line.substr (pos+token.size(), pos2-pos-token.size()), val);
221 LagGraph.addOneValue (val);
222 #endif
225 void cbInit (CMessage &msgin, TSockId from, CCallbackNetBase &netbase)
227 msgin.serial (Session);
229 // create the UDP connection
230 nlassert (UdpSock == NULL);
231 UdpSock = new CUdpSimSock( false );
234 UdpSock->connect( CInetAddress (ServerAddr, UDPPort) );
236 catch (const Exception &e)
238 InfoLog->displayRawNL ("Cannot connect to remote UDP host '%s': %s", ServerAddr.c_str(), e.what() );
239 exit ("");
243 void cbStart (CMessage &msgin, TSockId from, CCallbackNetBase &netbase)
245 InfoLog->displayRawNL ("Bench is starting..");
247 Mode = 1;
250 void cbDisconnect (TSockId from, void *arg)
252 exit ("Lost the server connection. You should not have the last client version\nGet it here: http://www.nevrax.org/download/bench.zip");
255 TCallbackItem CallbackArray[] =
257 { "INIT", cbInit },
258 { "INFO", cbInfo },
259 { "START", cbStart },
265 // Main
267 int main( int argc, char **argv )
269 createDebug ();
270 DebugLog->addNegativeFilter(" ");
272 InfoLog->displayRawNL ("\nNevrax UDP benchmark client\n\nPress <CTRL-C> to exit");
274 CPath::addSearchPath(UDP_DIR);
276 loadConfigFile ();
278 CCallbackClient *cc = new CCallbackClient;
280 cc->addCallbackArray (CallbackArray, sizeof(CallbackArray)/sizeof(CallbackArray[0]));
281 cc->setDisconnectionCallback (cbDisconnect, NULL);
285 InfoLog->displayRawNL ("Try to connect to %s:%d", ServerAddr.c_str(), TCPPort);
286 cc->connect(CInetAddress (ServerAddr, TCPPort));
288 CMessage msgout ("INIT");
289 msgout.serial (ConnectionName);
290 msgout.serial (Version);
291 cc->send (msgout);
293 InfoLog->displayRawNL ("Waiting the server answer...");
295 catch(const Exception &e)
297 InfoLog->displayRawNL ("Can't connect to %s:%d (%s)\n", ServerAddr.c_str(), TCPPort, e.what());
298 exit ("");
301 uint8 *packet = new uint8[MaxUDPPacketSize];
302 uint32 psize;
304 #ifdef USE_3D
306 UDriver *Driver = UDriver::createDriver();
307 Driver->setDisplay(UDriver::CMode(800, 600, 32, true));
308 UScene *Scene= Driver->createScene(false);
309 UCamera Camera= Scene->getCam();
310 Camera.setTransformMode(UTransform::DirectMatrix);
311 UTextContext *TextContext= Driver->createTextContext(CPath::lookup("n019003l.pfb"));
312 TextContext->setFontSize(18);
314 Camera.setPerspective(80*(float)Pi/180, 1.33f, 0.15f, 1000);
316 CEvent3dMouseListener MouseListener;
317 MouseListener.addToServer(Driver->EventServer);
318 MouseListener.setFrustrum(Camera.getFrustum());
319 MouseListener.setHotSpot(CVector(0,0,0));
320 CMatrix initMat;
321 initMat.setPos(CVector(0,-5,0));
322 MouseListener.setMatrix(initMat);
324 #endif
328 while (cc->connected ())
330 #ifdef USE_3D
332 // Manip.
333 Camera.setMatrix(MouseListener.getViewMatrix());
335 Driver->EventServer.pump();
336 if(Driver->AsyncListener.isKeyPushed(KeyESCAPE))
337 return EXIT_SUCCESS;
339 Driver->clearBuffers(CRGBA(255,255,255,0));
341 Scene->render();
343 CGraph::render (*Driver, *TextContext);
345 Driver->swapBuffers();
347 FpsGraph.addValue (1);
349 #endif
352 CConfigFile::checkConfigFiles ();
354 // update TCP connection
355 cc->update ();
357 // update UDP connection
358 if (UdpSock != NULL)
360 if (Mode == 0)
362 // init the UDP connection
363 CMemStream msgout;
364 msgout.serial (Mode);
365 msgout.serial (Session);
366 uint32 size = msgout.length();
367 #ifdef USE_3D
368 UploadGraph.addValue ((float)size);
369 #endif
370 UdpSock->send (msgout.buffer(), size);
371 nldebug ("Sent init udp connection");
372 nlSleep (100);
375 while (UdpSock->dataAvailable())
377 psize = MaxUDPPacketSize;
378 UdpSock->receive (packet, psize);
379 #ifdef USE_3D
380 DownloadGraph.addValue ((float)psize);
381 #endif
382 CMemStream msgin( true );
383 memcpy (msgin.bufferToFill (psize), packet, psize);
385 sint64 t = 0;
386 msgin.serial (t);
388 uint32 p = 0;
389 msgin.serial (p);
391 uint32 b = 0;
392 msgin.serial (b);
394 // I received a ping, send a pong
396 CMemStream msgout;
397 msgout.serial (Mode);
398 msgout.serial (t);
399 msgout.serial (p);
400 msgout.serial (b);
401 uint8 dummy=0;
402 while (msgout.length() < 200)
403 msgout.serial (dummy);
405 uint32 size = msgout.length();
406 nlassert (size == 200);
408 #ifdef USE_3D
409 UploadGraph.addValue ((float)size);
410 #endif
411 UdpSock->send (msgout.buffer(), size);
415 nlSleep (1);
418 exit ("");
419 return EXIT_SUCCESS;