Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
netserver_login.cpp
Go to the documentation of this file.
1 #include "networking/netserver.h"
2 #include "networking/zonemgr.h"
3 #include "networking/clientptr.h"
6 #include "vsfilesystem.h"
7 #include "cmd/unit_factory.h"
8 #include "networking/fileutil.h"
10 #include "load_mission.h"
11 //#include "cmd/script/mission.h"
12 
14 
15 extern Unit& GetUnitMasterPartList();
16 
17 /*
18  *************************************************************
19  **** Authenticate a connected client ***
20  *************************************************************
21  */
22 
23 ClientPtr NetServer::getClientFromSerial( ObjSerial serial )
24 {
25  ClientPtr clt;
26  bool found = false;
27  for (LI li = allClients.begin(); li != allClients.end(); li++) {
28  clt = (*li);
29  Unit *un = clt->game_unit.GetUnit();
30  if ( un && serial == un->GetSerial() ) {
31  found = true;
32  break;
33  }
34  }
35  if (!found)
36  //cerr<<" WARNING client not found in getClientFromSerial !!!!"<<endl;
37  clt.reset();
38  return clt;
39 }
40 
41 //WARNING: ipadr is NULL since we are getting this packet from acctserver, not the client itself.
42 bool NetServer::loginAccept( const string &_inetbuf, ClientPtr clt, int newacct, char flags )
43 {
44  COUT<<"enter "<<__PRETTY_FUNCTION__<<endl;
45 
46  string inetbuf = _inetbuf;
47  string callsign;
48  string unused;
49  NetBuffer netbuf;
50  ObjSerial cltserial;
51  callsign = getSimpleString( inetbuf );
52  unused = getSimpleString( inetbuf );
53  string serverip = getSimpleString( inetbuf );
54  string serverport = getSimpleString( inetbuf );
55  string savestr = getSimpleString( inetbuf );
56  string xmlstr = getSimpleString( inetbuf );
57  if (!clt) {
58  /*
59  * // This must be UDP mode, because the client would exist otherwise.
60  * // In UDP mode, client is created here.
61  * clt = newConnection_udp( ); // WARNING: ipadr is null. This code is broken anyway.
62  * if( !clt )
63  * {*/
64  COUT<<"Error creating new client connection"<<endl;
65  return false;
66  /*}*/
67  }
68  clt->savegame.resize( 0 );
69  //Get the save parts in a string array
70  clt->savegame.push_back( savestr );
71  clt->savegame.push_back( xmlstr );
72  Cockpit *cp = loadCockpit( clt );
73  /*
74  * if (_Universe->star_system.size()) {
75  * std::string system = _Universe->star_system[0]->getFileName();
76  * std::string newsystem=savestr.substr(0,savestr.find("^"));
77  * if (newsystem!=system) {
78  * sendLoginError( clt );
79  * logout(clt);
80  * return false;
81  * }
82  *
83  * }
84  */
85 //memcpy( &clt->cltadr, &ipadr, sizeof( AddressIP)); // ipadr is uninitialized... see above.
86 
87  //clt->callsign = callsign;
88  //clt->passwd = passwd;
89  COUT<<"LOGIN REQUEST SUCCESS for <"<<callsign<<">"<<endl;
90  if (newacct) {
91  COUT<<"This account has no ship/char so create one"<<"(UNIMPLEMENTED)"<<endl;
92  sendLoginError( clt );
93  logout( clt );
94  return false;
95  //Send a command to make the client create a new character/ship
96  } else if (cp) {
97  if ( loadFromSavegame( clt, cp ) ) {
98  sendLoginAccept( clt, cp );
99  COUT<<"<<< SENT LOGIN ACCEPT -----------------------------------------------------------------------"<<endl;
100  }
101  }
102  return true;
103 }
104 void NetServer::sendLoginAccept( ClientPtr clt, Cockpit *cp )
105 {
106  COUT<<"enter "<<__PRETTY_FUNCTION__<<endl;
107  //Verify that client already has a character
108  NetBuffer netbuf;
109  Unit *un = cp->GetParent();
110  if (!un) {
111  sendLoginError( clt );
112  return;
113  }
114  //Put the save parts in buffers in order to load them properly
115  netbuf.Reset();
116 
117  string datestr = _Universe->current_stardate.GetFullTrekDate();
118  netbuf.addString( datestr );
119  netbuf.addString( clt->savegame[0] );
120  netbuf.addString( clt->savegame[1] );
121 
122  Packet packet2;
123 
124  //Create a cockpit for the player and parse its savegame
125  ObjSerial cltserial = un->GetSerial();
126 
127  COUT<<">>> SEND LOGIN ACCEPT =( serial #"<<cltserial<<" )= --------------------------------------"<<endl;
128  COUT<<"SAVE="<<clt->savegame[0].length()<<" bytes - XML="<<clt->savegame[1].length()<<" bytes"<<endl;
129  cerr<<"SENDING STARDATE : "<<datestr<<endl;
130  //Add the initial star system filename + hash if crypto++ support too
131  string sysname = cp->savegame->GetStarSystem();
132  string relsys = sysname+".system";
133  netbuf.addString( relsys );
134 
135  //Generate the starsystem before addclient so that it already contains serials
136  StarSystem *sts = zonemgr->addZone( sysname );
137 
138 #ifdef CRYPTO
139  unsigned char *digest = new unsigned char[FileUtil::Hash.DigestSize()];
140  string sysxml;
141  if ( !( sysxml = zonemgr->getSystem( relsys ) ).empty() )
142  FileUtil::HashStringCompute( sysxml, digest );
143  else if ( !sysname.empty() )
144  FileUtil::HashFileCompute( relsys, digest, SystemFile );
145  netbuf.addShort( FileUtil::Hash.DigestSize() );
146  netbuf.addBuffer( digest, FileUtil::Hash.DigestSize() );
147  delete[] digest;
148 #else
149  netbuf.addShort( 0 );
150 #endif
151 
152  int zoneid = _Universe->StarSystemIndex( sts );
153  netbuf.addShort( zoneid );
154 
155  //Add system string to packet...
156  //Long, I know, but is there any other way to keep all the proper graphics-related data that the server discards?
157  //netbuf.addString( zonemgr->getSystem(sysname) );
158 
159  packet2.send( LOGIN_ACCEPT, cltserial, netbuf.getData(),
160  netbuf.getDataLength(), SENDRELIABLE, &clt->cltadr, clt->tcp_sock, __FILE__, PSEUDO__LINE__( 241 ) );
161  //Now that we have a starsystem, we will want to make a mission.
163  if (active_missions.size() == 1)
164  active_missions[0]->DirectorInitgame();
165  //Make a mission specially for this cockpit.
166  unsigned int oldcp = _Universe->CurrentCockpit();
169  LoadMission( "", vs_config->getVariable( "server", "serverscript", "import server;my_obj=server.player()" ), false );
171  _Universe->SetActiveCockpit( oldcp );
172  }
173 }
174 
175 static void getShipList( vector< string > &ships )
176 {
177  Unit *mpl = &GetUnitMasterPartList();
178  for (vector< Cargo >::const_iterator iter = mpl->pImage->cargo.begin(); iter != mpl->pImage->cargo.end(); iter++)
179  if ( (*iter).GetCategory().substr( 0, 10 ) == "starships/" ) {
180  std::string content = (*iter).GetContent();
181  std::string::size_type dot = content.find( '.' );
182  //if (dot==std::string::npos) {
183  ships.push_back( content );
184  //}
185  }
186 }
187 
188 void NetServer::chooseShip( ClientPtr clt, Packet &p )
189 {
190  if (!clt) return;
191  if ( clt->callsign.empty() ) {
192  sendLoginError( clt );
193  return;
194  }
195  vector< string >ships;
196  getShipList( ships );
197 
198  NetBuffer netbuf( p.getData(), p.getDataLength() );
199  unsigned short selection = netbuf.getShort();
200  string shipname = netbuf.getString();
201  if ( selection >= ships.size() ) {
202  sendLoginError( clt );
203  return;
204  }
205  string fighter = ships[selection];
206  Cockpit *cp = loadCockpit( clt );
207  if (cp)
208  if ( loadFromNewGame( clt, cp, fighter ) )
209  sendLoginAccept( clt, cp );
210 }
211 
212 void NetServer::localLogin( ClientPtr clt, Packet &p )
213 {
214  if (!clt) return;
215  NetBuffer netbuf( p.getData(), p.getDataLength() );
216  clt->callsign = netbuf.getString();
217  string passwd = netbuf.getString();
218  if (!this->server_password.empty() && passwd != this->server_password) {
219  this->sendLoginError( clt );
220  return;
221  }
222  for (unsigned int i = 0; i < _Universe->numPlayers(); i++) {
223  Cockpit *cp = _Universe->AccessCockpit( i );
224  if (cp->savegame && cp->savegame->GetCallsign() == clt->callsign) {
225  COUT<<"Cannot login player "<<clt->callsign<<": already exists on this server!";
226  sendLoginAlready( clt );
227  return;
228  }
229  }
230  netbuf.Reset();
231  vector< string >ships;
232  getShipList( ships );
233  netbuf.addShort( ships.size() );
234  for (vector< string >::const_iterator iter = ships.begin(); iter != ships.end(); ++iter)
235  netbuf.addString( *iter );
236  Packet p1;
237  p1.send( CMD_CHOOSESHIP, 0, netbuf.getData(),
238  netbuf.getDataLength(), SENDRELIABLE, &clt->cltadr, clt->tcp_sock, __FILE__, PSEUDO__LINE__( 202 ) );
239 }
240 
241 Cockpit* NetServer::loadCockpit( ClientPtr clt )
242 {
243  Cockpit *cp = NULL;
244  for (unsigned int i = 1; i < _Universe->numPlayers(); i++) {
245  cp = _Universe->AccessCockpit( i );
246  if (cp->savegame->GetCallsign() == clt->callsign) {
247  if (clt->loginstate == Client::CONNECTED) {
248  sendLoginAlready( clt );
249  return NULL;
250  } else {
251  //already logged in... it *should* already exist.
252  return cp;
253  }
254  }
255  }
256  if (_Universe->numPlayers() == 0) {
257  fprintf( stderr, "======= Creating Cockpit 0 for universe save data! =======\n" );
258  _Universe->createCockpit( "" ); //create computer player (universe save data)
259  }
260  cp = NULL;
261  if ( !unused_players.empty() ) {
262  cp = _Universe->AccessCockpit( unused_players.back() );
263  unused_players.pop();
264  }
265  if (cp == NULL)
266  cp = _Universe->createCockpit( clt->callsign );
267  else
268  cp->recreate( clt->callsign );
269  clt->loginstate = Client::LOGGEDIN;
270  return cp;
271 }
272 
273 bool NetServer::loadFromNewGame( ClientPtr clt, Cockpit *cp, string fighter )
274 {
275  ObjSerial cltserial = getUniqueSerial();
276  string PLAYER_SHIPNAME = fighter;
277  Mission *mission = NULL;
278  if (active_missions.size() > 0)
279  mission = active_missions[0];
280  if (!mission) {
281  COUT<<"Cannot login player without acctserver: No missions available";
282  sendLoginError( clt );
283  return false;
284  }
285  int saved_faction = 0; //NETFIXME: Send faction over network too!
286  cp->savegame->SetSavedCredits( XMLSupport::parse_float( mission->getVariable( "credits", "0" ) ) );
287  cp->savegame->SetStarSystem( mission->getVariable( "system", "Sol/Sol" ) );
288  if ( !mission->flightgroups.empty() )
289  cp->savegame->SetPlayerFaction( mission->flightgroups[0]->faction );
290  COUT<<"\tcredits = "<<cp->savegame->GetSavedCredits()<<endl;
291  COUT<<"\tfaction = "<<cp->savegame->GetPlayerFaction()<<endl;
292  COUT<<"-> SAVE LOADED"<<endl;
293  cp->credits = cp->savegame->GetSavedCredits();
294 
295  //WARNING : WE DON'T SAVE FACTION NOR FLIGHTGROUP YET
296  COUT<<"-> UNIT FACTORY WITH XML"<<endl;
297  //We may have to determine which is the current ship of the player if we handle several ships for one player
298  string PLAYER_FACTION_STRING = cp->savegame->GetPlayerFaction();
299  saved_faction = FactionUtil::GetFactionIndex( PLAYER_FACTION_STRING );
300 
301  bool exist = true; //(VSFileSystem::LookForFile( savedships[0], VSFileSystem::UnitFile)<=VSFileSystem::Ok);
302  static std::string loadfailed( "LOAD_FAILED" );
303  Unit *un = NULL;
304  if ( !PLAYER_SHIPNAME.empty() ) {
305  un = UnitFactory::createUnit( PLAYER_SHIPNAME.c_str(),
306  false,
307  saved_faction,
308  string( "" ),
309  Flightgroup::newFlightgroup( clt->callsign, PLAYER_SHIPNAME, PLAYER_FACTION_STRING,
310  "default", 1, 1, "", "", mission ),
311  0 );
312  }
313  if (!un) {
314  exist = false;
315  } else if (un->name == loadfailed) {
316  exist = false;
317  un->Kill();
318  }
319  if (!exist) {
320  //We can't find the unit saved for player -> send a login error
321  this->sendLoginError( clt );
322  cerr<<"WARNING : Unit file ("<<PLAYER_SHIPNAME<<") not found for "<<clt->callsign<<endl;
323  return false;
324  }
325  COUT<<"\tAFTER UNIT FACTORY WITH XML"<<endl;
326  clt->game_unit.SetUnit( un );
327  //Assign its serial to client*
328  un->SetSerial( cltserial );
329  un->PrimeOrders(); //Accept Comm messages
330 
331  //Affect the created unit to the cockpit
332  COUT<<"-> UNIT LOADED"<<endl;
333 
334  QVector tmpvec( 0, 0, 0 );
335  cp->SetParent( un, PLAYER_SHIPNAME.c_str(), "", tmpvec );
336  COUT<<"-> COCKPIT AFFECTED TO UNIT"<<endl;
337  {
338  string savestr, xmlstr;
339  clt->savegame.resize( 0 );
340  //Get the save parts in a string array
341  cp->activeStarSystem = zonemgr->addZone( cp->savegame->GetStarSystem() ); //Needed for GetSaveStrings.
342  SaveNetUtil::GetSaveStrings( clt, savestr, xmlstr, true );
343  clt->savegame.push_back( savestr );
344  clt->savegame.push_back( xmlstr );
345  }
346  return true;
347 }
348 
349 bool NetServer::loadFromSavegame( ClientPtr clt, Cockpit *cp )
350 {
351  ObjSerial cltserial = getUniqueSerial();
352  QVector tmpvec( 0, 0, 0 );
353  bool update = true;
354  float credits;
355  vector< string >savedships;
356  string str( "" );
357 
358  COUT<<"-> LOADING SAVE FROM NETWORK"<<endl;
359  cp->savegame->SetStarSystem( string() );
360  cp->savegame->ParseSaveGame( "", str, "", tmpvec, update, credits, savedships, cltserial, clt->savegame[0], false );
361  //Generate the system we enter in if needed and add the client in it
362  if ( savedships.empty() ) {
363  COUT<<"There are no saved ships... corrupted save file for "<<clt->callsign<<endl;
364  std::string logoutnetbuf;
365  addSimpleChar( logoutnetbuf, ACCT_LOGOUT );
366  addSimpleString( logoutnetbuf, clt->callsign );
367  addSimpleString( logoutnetbuf, clt->passwd );
368  //We can't find the unit saved for player -> send a login error
369  this->logout( clt );
370  return false;
371  }
372  COUT<<"\tcredits = "<<credits<<endl;
373  COUT<<"\tfaction = "<<cp->savegame->GetPlayerFaction()<<endl;
374  COUT<<"-> SAVE LOADED"<<endl;
375 
376  //WARNING : WE DON'T SAVE FACTION NOR FLIGHTGROUP YET
377  COUT<<"-> UNIT FACTORY WITH XML"<<endl;
378  //We may have to determine which is the current ship of the player if we handle several ships for one player
379  string PLAYER_SHIPNAME = savedships[0];
380  string PLAYER_FACTION_STRING = cp->savegame->GetPlayerFaction();
381 
382  int saved_faction = FactionUtil::GetFactionIndex( PLAYER_FACTION_STRING );
383  //vector<vector <string> > path = lookforUnit( savedships[0].c_str(), saved_faction, false);
384  bool exist = true; //(VSFileSystem::LookForFile( savedships[0], VSFileSystem::UnitFile)<=VSFileSystem::Ok);
385  static std::string loadfailed( "LOAD_FAILED" );
386  Unit *un = NULL;
387  if ( !PLAYER_SHIPNAME.empty() ) {
388  un = UnitFactory::createUnit( PLAYER_SHIPNAME.c_str(),
389  false,
390  saved_faction,
391  string( "" ),
392  Flightgroup::newFlightgroup( clt->callsign, PLAYER_SHIPNAME, PLAYER_FACTION_STRING,
393  "default", 1, 1, "", "", mission ),
394  0, &clt->savegame[1] );
395  }
396  if (!un) {
397  exist = false;
398  } else if (un->name == loadfailed) {
399  exist = false;
400  un->Kill();
401  }
402  if (!exist) {
403  unsigned short serial = cltserial;
404  std::string logoutnetbuf;
405  addSimpleChar( logoutnetbuf, ACCT_LOGOUT );
406  addSimpleString( logoutnetbuf, clt->callsign );
407  addSimpleString( logoutnetbuf, clt->passwd );
408  //We can't find the unit saved for player -> send a login error
409  this->logout( clt );
410  Packet p2;
411  //Send the account server a logout info
412  if ( !acct_sock->sendstr( logoutnetbuf ) )
413  COUT<<"ERROR sending LOGOUT to account server"<<endl;
414  cerr<<"WARNING : Unit file ("<<savedships[0]<<") not found for "<<clt->callsign<<endl;
415  return cp;
416  }
417  COUT<<"\tAFTER UNIT FACTORY WITH XML"<<endl;
418  clt->game_unit.SetUnit( un );
419  //Assign its serial to client*
420  un->SetSerial( cltserial );
422 
423  //Affect the created unit to the cockpit
424  COUT<<"-> UNIT LOADED"<<endl;
425 
426  cp->SetParent( un, PLAYER_SHIPNAME.c_str(), "", tmpvec );
427  COUT<<"-> COCKPIT AFFECTED TO UNIT"<<endl;
428 
429  COUT<<"SHIP -- "<<savedships[0]<<" -- LOCATION: x="<<tmpvec.i<<",y="<<tmpvec.j<<",z="<<tmpvec.k<<endl;
430  return true;
431 }
432 
433 void NetServer::sendLoginError( ClientPtr clt )
434 {
435  Packet packet2;
436  //Send a login error
437  //COUT<<"Creating packet... ";
438  COUT<<">>> SEND LOGIN ERROR -----------------------------------------------------------------"<<endl;
439  packet2.send( LOGIN_ERROR, 0, (char*) NULL, 0, SENDRELIABLE, &clt->cltadr, clt->tcp_sock, __FILE__, PSEUDO__LINE__( 255 ) );
440  COUT<<"<<< SENT LOGIN ERROR -----------------------------------------------------------------------"<<endl;
441 }
442 
443 void NetServer::sendLoginUnavailable( ClientPtr clt )
444 {
445  Packet packet2;
446  //Send an unavailable login service
447  //COUT<<"Creating packet... ";
448  COUT<<">>> SEND LOGIN UNAVAILABLE -----------------------------------------------------------------"<<endl;
449  packet2.send( LOGIN_UNAVAIL, 0, (char*) NULL, 0, SENDRELIABLE, &clt->cltadr, clt->tcp_sock, __FILE__, PSEUDO__LINE__( 268 ) );
450  COUT<<"<<< SENT LOGIN UNAVAILABLE -----------------------------------------------------------------------"<<endl;
451 
452  discList.push_back( clt );
453 }
454 
455 void NetServer::sendLoginAlready( ClientPtr clt )
456 {
457  //SHOULD NOT WE FREE THE MEMORY OCCUPIED BY A POSSIBLE CLIENT * ???
458  Packet packet2;
459  //Send a login error
460  //int retsend;
461  //COUT<<"Creating packet... ";
462  COUT<<">>> SEND LOGIN ALREADY =( serial #"<<packet.getSerial()<<" )= --------------------------------------"<<endl;
463  packet2.send( LOGIN_ALREADY, 0, (char*) NULL, 0, SENDRELIABLE, &clt->cltadr, clt->tcp_sock, __FILE__, PSEUDO__LINE__( 283 ) );
464  COUT<<"<<< SENT LOGIN ALREADY -----------------------------------------------------------------------"<<endl;
465  discList.push_back( clt );
466 }
467