Leviathan  0.8.0.0
Leviathan game engine
NetworkHandler.cpp
Go to the documentation of this file.
1 // ------------------------------------ //
2 #include "NetworkHandler.h"
3 
5 #include "Connection.h"
6 #include "FileSystem.h"
9 #include "NetworkRequest.h"
10 #include "NetworkResponse.h"
11 #include "SentNetworkThing.h"
12 #include "ObjectFiles/ObjectFile.h"
14 #include "RemoteConsole.h"
15 #include "SFML/Network/Http.hpp"
16 #include "SyncedVariables.h"
18 #include "Utility/ComplainOnce.h"
19 #include "NetworkCache.h"
20 #include "Engine.h"
21 using namespace Leviathan;
22 using namespace std;
23 // ------------------------------------ //
25  NetworkInterface* packethandler)
26  : AppType(ntype), CloseMasterServerConnection(false)
27 {
28  // This will assert if we were passed the wrong type
29  packethandler->VerifyType(AppType);
30  packethandler->SetOwner(this);
31 
33 
34  ClientInterface = dynamic_cast<NetworkClientInterface*>(packethandler);
35 
36  } else if(AppType == NETWORKED_TYPE::Server){
37 
38  ServerInterface = dynamic_cast<NetworkServerInterface*>(packethandler);
39  }
40 
41  // Create the variable sync object //
42  VariableSyncer = std::make_unique<SyncedVariables>(this, AppType, packethandler);
43 
44  _NetworkCache = std::make_unique<NetworkCache>(AppType);
45 
46  if(!_NetworkCache || !_NetworkCache->Init(this)){
47 
48  LOG_ERROR("NetworkHandler: failed to create NetworkCache");
49  LEVIATHAN_ASSERT(0, "NetworkHandler: failed to create NetworkCache");
50  }
51 
52  // Create the custom packet handler //
53  _GameSpecificPacketHandler = std::make_unique<GameSpecificPacketHandler>(
54  packethandler);
55 }
56 
58 
59  _NetworkCache.reset();
60 }
61 // ------------------------------------ //
63 
64  MasterServerMustPassIdentification = info.MasterServerIdentificationString;
65 
66  if(AppType != NETWORKED_TYPE::Master){
67  // Query master server //
68  QueryMasterServer(info);
69 
70  } else {
71  // We are our own master! //
72 
73  // Get out port number here //
75 
76  int tmpport = 0;
77 
78  if(!vars->GetValueAndConvertTo<int>("MasterServerPort", tmpport)){
79  // This is quite bad //
80  Logger::Get()->Error("NetworkHandler: Init: no port configured, config missing "
81  "'MasterServerPort' of type int");
82  }
83 
84  PortNumber = (unsigned short)tmpport;
85  }
86 
87  if(AppType == NETWORKED_TYPE::Client){
88  // We can use any port we get //
89  PortNumber = sf::Socket::AnyPort;
90 
91  } else if(AppType == NETWORKED_TYPE::Server){
92  // We need to use a specific port //
94 
95  int tmpport = 0;
96 
97  if(!vars->GetValueAndConvertTo<int>("DefaultServerPort", tmpport)){
98  // This is quite bad //
99  Logger::Get()->Error("NetworkHandler: Init: no port configured, config missing "
100  "'ServerPort' of type int");
101  }
102 
103  PortNumber = (unsigned short)tmpport;
104  }
105 
106  // We want to receive responses //
107  if(_Socket.bind(PortNumber) != sf::Socket::Done){
108 
109  Logger::Get()->Error("NetworkHandler: Init: failed to bind to port "+
110  Convert::ToString(PortNumber));
111  return false;
112  }
113 
114  PortNumber = _Socket.getLocalPort();
115 
116  // Set the socket as blocking //
117  if(BlockingMode) {
118 
119  _Socket.setBlocking(true);
120 
121  // Run the listening thread //
122  ListenerThread = std::thread(std::bind(&NetworkHandler::_RunListenerThread, this));
123  } else {
124 
125  _Socket.setBlocking(false);
126  }
127 
128  // Report success //
129  Logger::Get()->Info("NetworkHandler: running listening socket on port "+Convert::ToString(
130  _Socket.getLocalPort()));
131 
132  return true;
133 }
134 // ------------------------------------ //
136 
137  if(_Socket.bind(port) != sf::Socket::Done) {
138 
139  LOG_ERROR("NetworkHandler: Init: failed to bind to port " +
140  Convert::ToString(PortNumber));
141  return false;
142  }
143 
144  PortNumber = _Socket.getLocalPort();
145 
146  _Socket.setBlocking(false);
147 
148  return true;
149 }
150 // ------------------------------------ //
152 
153  {
154  GUARD_LOCK();
155 
156  CloseMasterServerConnection = true;
157 
158  // Kill master server connection //
159 
160  // Notify master server connection kill //
161  if(MasterServerConnection){
162 
163  MasterServerConnection->Release();
164  }
165 
166  // Close all connections //
167  for(auto& connection : OpenConnections){
168 
169  connection->Release();
170  }
171 
172  OpenConnections.clear();
173 
174 
175  }
176 
177  if(MasterServerConnectionThread.joinable()){
178  MasterServerConnectionThread.join();
179  MasterServerConnection.reset();
180  }
181 
182  _ReleaseSocket();
183 
184  if(BlockingMode){
185  // This thread is blocked in infinite read //
186  //ListenerThread.join();
187  if(ListenerThread.joinable())
188  ListenerThread.detach();
189  }
190 }
191 
193 
194  ServerInterface = nullptr;
195  ClientInterface = nullptr;
196 }
197 
199  // This might cause the game to hang... //
200 
201  bool blockunbind = false;
202 
203  {
205  variables->GetValueAndConvertTo<bool>("DisableSocketUnbind", blockunbind);
206  }
207 
208  auto lock = LockSocketForUse();
209 
210  // This should do the trick //
211  if(!blockunbind || !BlockingMode){
212 
213  _Socket.unbind();
214 
215  } else {
216  Logger::Get()->Info("NetworkHandler: _ReleaseSocket: blocked unbind");
217  }
218 }
219 
221 {
222  sf::Packet receivedpacket;
223 
224  sf::IpAddress sender;
225  unsigned short sentport;
226 
228 
229  sf::Socket::Status status;
230 
231  while (true) {
232 
233  guard.unlock();
234 
235  {
236  auto lock = LockSocketForUse();
237  status = _Socket.receive(receivedpacket, sender, sentport);
238  }
239 
240  guard.lock();
241 
242  if(status != sf::Socket::Done)
243  break;
244 
245  // Process packet //
246 
247  // Pass to a connection //
248  bool Passed = false;
249 
250 
251  for (size_t i = 0; i < OpenConnections.size(); i++) {
252  // Keep passing until somebody handles it //
253  if(OpenConnections[i]->IsThisYours(sender, sentport)) {
254 
255  auto curconnection = OpenConnections[i];
256 
257  // Prevent deaclocks, TODO: make NetworkHandler only usable by the main thread
258  guard.unlock();
259  curconnection->HandlePacket(receivedpacket);
260  guard.lock();
261 
262  Passed = true;
263  break;
264  }
265  }
266 
267  if(Passed)
268  continue;
269 
270  shared_ptr<Connection> tmpconnect;
271 
272  // TODO: Check is it a close or a keep alive packet //
273 
274  // We might want to open a new connection to this client //
275  Logger::Get()->Info("Received a new connection from " + sender.toString() + ":" +
276  Convert::ToString(sentport));
277 
278  // \todo Make sure that the console won't be deleted between this and the actual check
279 
280  if(AppType != NETWORKED_TYPE::Client) {
281  // Accept the connection //
282  LOG_WRITE("\t> Connection accepted");
283 
284  tmpconnect = OpenConnectionTo(guard, sender, sentport);
285 
286  } else if(rcon && rcon->IsAwaitingConnections()) {
287 
288  // We might allow a remote start remote console session //
289  LOG_WRITE("\t> Connection accepted for remote console receive");
290 
291  tmpconnect = OpenConnectionTo(guard, sender, sentport);
292 
293  // We need a special restriction for this connection //
294  if(tmpconnect)
296 
297  } else {
298  // Deny the connection //
299  LOG_WRITE("\t> Dropping connection due to not being a server "
300  "(and not expecting anything)");
301  continue;
302  }
303 
304  if(!tmpconnect) {
305 
306  LOG_WRITE("\t> Failed to create connection object");
307  continue;
308  }
309 
310  // Try to handle the packet //
311  if(!tmpconnect->IsThisYours(sender, sentport)) {
312  // That's an error //
313  Logger::Get()->Error("NetworkHandler: UpdateAllConnections: new connection "
314  "refused to process its packet from " + sender.toString() + ":" +
315  Convert::ToString(sentport));
316  CloseConnection(*tmpconnect);
317  } else {
318 
319  tmpconnect->HandlePacket(receivedpacket);
320  }
321  }
322 
323  return (status != sf::Socket::Error) && (status != sf::Socket::Disconnected);
324 }
325 // ------------------------------------ //
326 DLLEXPORT std::shared_ptr<std::promise<string>> Leviathan::NetworkHandler::QueryMasterServer(
327  const MasterServerInformation &info) {
328  // Copy the data //
329  StoredMasterServerInfo = info;
330 
331  shared_ptr<std::promise<string>> resultvalue(new std::promise<string>());
332 
333  // Make sure it doesn't die instantly //
334  CloseMasterServerConnection = false;
335 
336  // Run the task async //
337  MasterServerConnectionThread = std::thread(RunGetResponseFromMaster, this, resultvalue);
338 
339  return resultvalue;
340 }
341 
343 
344  GUARD_LOCK();
345 
346  bool found = false;
347 
348  for (auto& connectioniter : OpenConnections) {
349 
350  if(connectioniter.get() == &connection) {
351 
352  found = true;
353  break;
354  }
355  }
356 
357  if(!found)
358  return false;
359 
360  return connection.IsValidForSend();
361 }
362 // ------------------------------------ //
364 
365  // Set up the values //
366  vector<VariableBlock*> vals;
367  {
368  vals.reserve(MasterServers.size());
369 
370  // Only this scope requires locking //
371  GUARD_LOCK();
372 
373  for(size_t i = 0; i < MasterServers.size(); i++){
374  vals.push_back(new VariableBlock(*MasterServers[i].get()));
375  }
376  }
377 
378  NamedVars headervars;
379  headervars.Add(std::make_shared<NamedVariableList>("MasterServers", vals));
380 
381  ObjectFile file(headervars);
382 
383  ObjectFileProcessor::WriteObjectFile(file, StoredMasterServerInfo.StoredListFile,
384  Logger::Get());
385 }
386 
388 
389  // Skip if there is no file defined //
390  if(!StoredMasterServerInfo.StoredListFile.size())
391  return false;
392 
394  StoredMasterServerInfo.StoredListFile, Logger::Get());
395 
396  if(!fileobj)
397  return false;
398 
399  // Try to get the right variable with the name //
400  auto foundvar = fileobj->GetVariables()->GetValueDirectRaw("MasterServers");
401 
402  if(!foundvar)
403  return false;
404 
405  // Found value, load //
406  size_t maxval = foundvar->GetVariableCount();
407 
408  // We need locking for this add //
409  GUARD_LOCK();
410 
411  MasterServers.reserve(maxval);
412 
413  for(size_t i = 0; i < maxval; i++){
414  MasterServers.push_back(unique_ptr<string>(new std::string(
415  foundvar->GetValueDirect(i)->ConvertAndReturnVariable<std::string>())));
416  }
417 
418  return true;
419 }
420 
422 
423  if(_NetworkCache)
424  _NetworkCache->Release();
425 }
426 
428 
429 }
430 // ------------------------------------ //
432  const string &fulladdress, const string &regextouse /*= "http://.*?/"*/)
433 {
434  // Create a regex //
435  regex findaddressregex(regextouse, regex_constants::ECMAScript | regex_constants::icase);
436 
437  match_results<const char*> addressmatch;
438 
439  // Return the match //
440  regex_search(fulladdress.c_str(), addressmatch, findaddressregex);
441 
442 
443  return string(addressmatch[1]);
444 }
445 
447  std::shared_ptr<Connection> connection)
448 {
449  // Skip duplicates //
450  if(GetConnection(connection.get()))
451  return;
452 
453  GUARD_LOCK();
454 
455  OpenConnections.push_back(connection);
456 }
457 
458 // ------------------------------------ //
460 
461  // Update remote console sessions if they exist //
462  auto rconsole = Engine::Get()->GetRemoteConsole();
463  if(rconsole)
464  rconsole->UpdateStatus();
465  {
466  GUARD_LOCK();
467 
468  // Remove closed connections //
469  RemoveClosedConnections(guard);
470 
471  // Do listening //
472  if(!BlockingMode) {
473 
474  _RunUpdateOnce(guard);
475  }
476 
477  // Time-out requests //
478  for (auto& connection : OpenConnections) {
479 
480  connection->UpdateListening();
481  }
482  }
483 
484  // Interface might want to do something //
485  GetInterface()->TickIt();
486 }
487 // ------------------------------------ //
489 
490  return Lock((SocketMutex));
491 }
492 // ------------------------------------ //
494 
496 
497  // Return if it is already queued //
498  for(auto& connection : ConnectionsToTerminate){
499  if(connection == &to)
500  return;
501  }
502 
503  ConnectionsToTerminate.push_back(&to);
504 }
505 
507 {
508  Lock terminatelock(ConnectionsToTerminateMutex);
509 
510  // Go through the removed connection list and remove closed connections //
511  for (size_t a = 0; a < OpenConnections.size(); ) {
512 
513  bool close = false;
514 
515  if(!OpenConnections[a]->IsValidForSend()) {
516 
517  close = true;
518 
519  } else {
520 
521  for (size_t i = 0; i < ConnectionsToTerminate.size(); i++) {
522 
523  if(OpenConnections[a].get() == ConnectionsToTerminate[i]) {
524 
525  close = true;
526  break;
527  }
528  }
529  }
530 
531  if(close) {
532 
533  auto& connection = OpenConnections[a];
534 
535  // Send a close packet //
536  connection->SendCloseConnectionPacket();
537 
538  // Close it //
539  connection->Release();
540 
541  connection.reset();
542 
543  OpenConnections.erase(OpenConnections.begin() + a);
544 
545  } else {
546 
547  a++;
548  }
549  }
550 
551  ConnectionsToTerminate.clear();
552 }
553 // ------------------------------------ //
554 DLLEXPORT std::shared_ptr<Connection> NetworkHandler::GetConnection(Connection* directptr)
555  const
556 {
557  GUARD_LOCK();
558 
559  for(auto& connection : OpenConnections){
560 
561  if(connection.get() == directptr)
562  return connection;
563  }
564 
565  return nullptr;
566 }
567 // ------------------------------------ //
569  const string &targetaddress)
570 {
571  if(targetaddress.empty())
572  return nullptr;
573 
574  GUARD_LOCK();
575 
576  // Find existing one //
577  for (auto& connection : OpenConnections) {
578 
579  if(connection->GetRawAddress() == targetaddress)
580  return connection;
581  }
582 
583  // Create new //
584  auto newconnection = std::make_shared<Connection>(targetaddress);
585 
586  // Initialize the connection //
587  if(!newconnection->Init(this)){
588 
589  return nullptr;
590  }
591 
592  OpenConnections.push_back(newconnection);
593 
594  return newconnection;
595 }
596 
597 DLLEXPORT std::shared_ptr<Leviathan::Connection> Leviathan::NetworkHandler::OpenConnectionTo(
598  Lock &guard, const sf::IpAddress &targetaddress, unsigned short port)
599 {
600  // Find existing one //
601  for (auto& connection : OpenConnections) {
602 
603  if(connection->IsThisYours(targetaddress, port))
604  return connection;
605  }
606 
607  // Create new //
608  auto newconnection = std::make_shared<Connection>(targetaddress, port);
609 
610  // Initialize the connection //
611  if(!newconnection->Init(this)) {
612 
613  return nullptr;
614  }
615 
616  OpenConnections.push_back(newconnection);
617 
618  return newconnection;
619 }
620 
621 // ------------------------------------ //
623 
624  // Let's listen for things //
625  Logger::Get()->Info("NetworkHandler: running listening thread");
626  {
627 
628  GUARD_LOCK();
629  while (_RunUpdateOnce(guard)) {
630 
631  }
632  }
633 
634  Logger::Get()->Info("NetworkHandler: listening socket thread quitting");
635 }
636 // ------------------------------------ //
638  std::shared_ptr<std::promise<string>> resultvar)
639 {
640  // Try to load master server list //
641 
642  // To reduce duplicated code and namespace pollution use a lambda thread for this //
643  std::thread DataUpdaterThread(std::bind<void>([](NetworkHandler* instance)
644  -> void
645  {
646 
647  Logger::Get()->Info("NetworkHandler: Fetching new master server list...");
648  sf::Http::Request request(instance->StoredMasterServerInfo.MasterListFetchPage,
649  sf::Http::Request::Get);
650 
651  sf::Http httpserver(instance->StoredMasterServerInfo.MasterListFetchServer);
652 
653  sf::Http::Response response = httpserver.sendRequest(request, sf::seconds(2.f));
654 
655  if(instance->CloseMasterServerConnection)
656  return;
657 
658  if(response.getStatus() == sf::Http::Response::Ok) {
659 
660  // It should just be a list of master servers one on each line //
661  StringIterator itr(response.getBody());
662 
663  unique_ptr<string> data;
664 
665  std::vector<unique_ptr<string>> tmplist;
666 
667 
668  while ((data = itr.GetUntilNextCharacterOrAll<string>(L'\n')) && (data->size())) {
669 
670  tmplist.push_back(move(data));
671  }
672 
673  // Check //
674  if(tmplist.size() == 0) {
675 
676  Logger::Get()->Warning("NetworkHandler: retrieved an empty list of master "
677  "servers, not updated");
678  return;
679  }
680 
681  if(instance->CloseMasterServerConnection)
682  return;
683 
684  // Update real list //
685  GUARD_LOCK_OTHER(instance);
686 
687  instance->MasterServers.clear();
688  instance->MasterServers.reserve(tmplist.size());
689  for (auto iter = tmplist.begin(); iter != tmplist.end(); ++iter) {
690 
691  instance->MasterServers.push_back(shared_ptr<string>(new string((*(*iter)))));
692  }
693 
694 
695  // Notify successful fetch //
696  auto tmpget = Logger::Get();
697  if(tmpget)
698  tmpget->Info("NetworkHandler: Successfully fetched a master server list:");
699 
700  for (auto iter = instance->MasterServers.begin();
701  iter != instance->MasterServers.end();
702  ++iter)
703  {
704  if(tmpget)
705  Logger::Get()->Write("\t> " + *(*iter).get());
706  }
707 
708  } else {
709  // Fail //
710  Logger::Get()->Error("NetworkHandler: failed to update the master server list, "
711  "using the old list");
712  }
713 
714 
715  }, instance));
716 
717  if(!instance->_LoadMasterServerList()){
718 
719  // We need to request a new list before we can do anything //
720  Logger::Get()->Info("NetworkHandler: no stored list of master servers, "
721  "waiting for the update to finish");
722 
723  if(!DataUpdaterThread.joinable())
724  throw Exception("This should be joinable");
725  DataUpdaterThread.join();
726  }
727 
728  if(instance->CloseMasterServerConnection)
729  return;
730 
731  bool uselocalhost = false;
732 
733  // We might want to try to connect to localhost //
734  {
736 
737  if(variables)
738  variables->GetValueAndConvertTo<bool>("MasterServerForceLocalhost", uselocalhost);
739  }
740 
741  // Try to find a master server to connect to //
742  for (size_t i = 0; i < instance->MasterServers.size(); i++) {
743 
744  shared_ptr<string> tmpaddress;
745 
746  {
747  GUARD_LOCK_OTHER(instance);
748 
749  tmpaddress = instance->MasterServers[i];
750  }
751 
752  if(uselocalhost) {
753 
754  // We might want to warn about this //
755  ComplainOnce::PrintWarningOnce("MasterServerForceLocalhostOn",
756  "Master server list forced to use localhost as address, "
757  "might not be what you want");
758 
759  StringIterator itr(tmpaddress.get());
760 
761  itr.GetUntilNextCharacterOrAll<string>(':');
762 
763  // Right now the part we don't want is retrieved //
764  auto tmpres = itr.GetUntilEnd<string>();
765 
766  if(!tmpres){
767 
768  // Got nothing //
769  LOG_WARNING("GetMasterServerList: got an empty response");
770  continue;
771  }
772 
773  // The result now should have the ':' character and the possible port //
774 
775  tmpaddress = std::shared_ptr<string>(new string("localhost" + *tmpres.get()));
776  }
777 
778  if(instance->CloseMasterServerConnection)
779  return;
780 
781  // Try connection //
782  auto tmpinfo = instance->OpenConnectionTo(*tmpaddress);
783 
784  if(!tmpinfo) {
785 
786  Logger::Get()->Error("NetworkHandler: failed to open a connection to target");
787  continue;
788  }
789 
790  // Create an identification request //
791  auto serverinforesponse = tmpinfo->SendPacketToConnection(
792  std::make_shared<RequestIdentification>(),
794 
795  // a task that'll wait for the response //
796  serverinforesponse->SetCallbackFunc(
797  [=](bool succeeded, SentNetworkThing &sentthing) -> void {
798 
799  // Report this for easier debugging //
800  Logger::Get()->Info("Master server check with \"" + *tmpaddress +
801  "\" completed");
802 
803  // Quit if the instance is gone //
804  if(instance->CloseMasterServerConnection)
805  return;
806 
807  auto actualresponse = serverinforesponse->GotResponse;
808 
809 
810  if(!actualresponse) {
811  // Failed to receive something from the server //
812  Logger::Get()->Warning("NetworkHandler: failed to receive a "
813  "response from master server(" + *tmpaddress + ")");
814 
815  // Release connection //
816  tmpinfo->Release();
817  return;
818  }
819 
820  Logger::Get()->Warning("NetworkHandler: received a response from "
821  "master server(" + *tmpaddress + "):");
822 
823  // Get data //
824  ResponseIdentification* tmpresponse = static_cast<ResponseIdentification*>(
825  actualresponse.get());
826 
827  if(actualresponse->GetType() != NETWORK_RESPONSE_TYPE::Identification) {
828  // Failed to receive valid response //
829  Logger::Get()->Warning("NetworkHandler: received an invalid response "
830  "from master server(" + *tmpaddress + ")");
831  // Release connection //
832  tmpinfo->Release();
833  return;
834  }
835 
836  // Ensure data validness //
837 
838  // \todo verify that the data is sane //
839 
840  {
841  // Set a working server //
842  GUARD_LOCK_OTHER(instance);
843  instance->MasterServerConnection = tmpinfo;
844  }
845 
846  // Successfully connected //
847  resultvar->set_value(string("ConnectedToMasterServer = " + *tmpaddress + ";"));
848  });
849  }
850 
851  // TODO: run this only when all the tasks fail
852  if(false){
853  // If we got here, we haven't connected to anything //
854  Logger::Get()->Warning("NetworkHandler: could not connect to any fetched master "
855  "servers, you can restart to use a new list");
856 
857  // We can let whoever is waiting for us to go now, and finish some utility
858  // tasks after that
859  resultvar->set_value(std::string("Failed to connect to master server"));
860  }
861 
862  // This needs to be done here //
863  if(DataUpdaterThread.joinable())
864  DataUpdaterThread.join();
865 
866  // Output the current list //
867  instance->_SaveMasterServerList();
868 }
869 
870 
DLLEXPORT bool IsConnectionValid(Connection &connection) const
Checks whether a connection is open and ready for sending.
#define GAMECONFIGURATION_GET_VARIABLEACCESS(x)
DLLEXPORT bool IsAwaitingConnections()
Returns true if connections are marked as awaiting.
DLLEXPORT void Write(const std::string &data) override
Definition: Logger.cpp:113
std::unique_ptr< NetworkCache > _NetworkCache
Networked variable cache.
std::shared_ptr< Connection > MasterServerConnection
Stores a "working" (meaning the server has responded something) master server address.
DLLEXPORT void ShutdownCache()
Destroys the network cache permanently.
virtual DLLEXPORT void UpdateAllConnections()
DLLEXPORT void Info(const std::string &data) override
Definition: Logger.cpp:164
#define LOG_ERROR(x)
Definition: Define.h:96
Non-template class for working with all types of DataBlocks.
Definition: DataBlock.h:425
DLLEXPORT void DisconnectInterface()
Unhooks the NetworkInterfaces from this object.
bool IsThisYours(const sf::IpAddress &sender, unsigned short sentport)
Checks does the sender and port match our corresponding values.
Definition: Connection.h:136
bool _RunUpdateOnce(Lock &guard)
Returns false if the socket has been closed.
NetworkClientInterface * ClientInterface
DLLEXPORT void UpdateStatus()
Called before packets are handled.
DLLEXPORT std::shared_ptr< std::promise< std::string > > QueryMasterServer(const MasterServerInformation &info)
static DLLEXPORT std::string GetServerAddressPartOfAddress(const std::string &fulladdress, const std::string &regextouse="http://.*?/")
Retrieves base address from an http protocol URL For example if passed http://boostslair....
DLLEXPORT void HandlePacket(sf::Packet &packet)
Handles a packet.
Definition: Connection.cpp:563
NETWORKED_TYPE AppType
Type of application.
DLLEXPORT void SetRestrictionMode(CONNECTION_RESTRICTION type)
Adds special restriction on the connection.
static DLLEXPORT std::unique_ptr< ObjectFile > ProcessObjectFile(const std::string &file, LErrorReporter *reporterror)
Reads an ObjectFile to an in-memory data structure.
Base class for all exceptions thrown by Leviathan.
Definition: Exceptions.h:10
void RunGetResponseFromMaster(NetworkHandler *instance, std::shared_ptr< std::promise< std::string >> resultvar)
#define LOG_WARNING(x)
Definition: Define.h:95
DLLEXPORT void VerifyType(NETWORKED_TYPE type) const
Asserts if types don't match.
bool IsValidForSend() const
Returns true if this socket is valid for sending.
Definition: Connection.h:121
static DLLEXPORT bool WriteObjectFile(ObjectFile &data, const std::string &file, LErrorReporter *reporterror)
Writes an ObjectFile's data structure to a file.
DLLEXPORT NetworkHandler(NETWORKED_TYPE ntype, NetworkInterface *packethandler)
DLLEXPORT void _RegisterConnection(std::shared_ptr< Connection > connection)
std::unique_ptr< RStrType > GetUntilNextCharacterOrAll(int charactertolookfor, int specialflags=0)
Gets characters until a character or all remaining characters.
DLLEXPORT bool Add(std::shared_ptr< NamedVariableList > value)
Adds a value.
Definition: NamedVars.cpp:883
std::unique_ptr< GameSpecificPacketHandler > _GameSpecificPacketHandler
Game specific packet handler that allows programs to register their own packets.
DLLEXPORT void Warning(const std::string &data) override
Definition: Logger.cpp:190
Iterator class for getting parts of a string.
#define LOG_WRITE(x)
Definition: Define.h:97
DLLEXPORT std::shared_ptr< Connection > OpenConnectionTo(const std::string &targetaddress)
Opens a new connection to the provided address.
NETWORKED_TYPE
Type of networked application.
Definition: CommonNetwork.h:22
unsigned short uint16_t
Definition: core.h:39
#define GUARD_LOCK_OTHER(x)
Definition: ThreadSafe.h:124
#define LEVIATHAN_ASSERT(x, msg)
Definition: Define.h:104
static DLLEXPORT bool PrintWarningOnce(const std::string &warning, const std::string &message)
Definition: ComplainOnce.cpp:7
static std::string ToString(const T &val)
Definition: Convert.h:72
RemoteConsole * GetRemoteConsole()
Definition: Engine.h:235
Mutex ConnectionsToTerminateMutex
Closes connections on next update.
static DLLEXPORT Logger * Get()
Definition: Logger.cpp:106
std::vector< std::shared_ptr< Connection > > OpenConnections
virtual DLLEXPORT ~NetworkHandler()
DLLEXPORT void SetOwner(NetworkHandler *owner)
virtual DLLEXPORT void RemoveClosedConnections(Lock &guard)
DLLEXPORT std::shared_ptr< Connection > GetConnection(Connection *directptr) const
Returns a persistent pointer to a connection.
Class that handles a single connection to another instance.
Definition: Connection.h:105
virtual DLLEXPORT void Release()
MasterServerInformation StoredMasterServerInfo
void _RunListenerThread()
Constantly listens for packets in a blocked state.
NetworkServerInterface * ServerInterface
#define DLLEXPORT
Definition: Include.h:84
std::vector< std::shared_ptr< std::string > > MasterServers
static DLLEXPORT Engine * Get()
Definition: Engine.cpp:86
The access mask controls which registered functions and classes a script sees.
Definition: GameModule.h:12
Class used to handle remote server commands and receiving messages.
Definition: RemoteConsole.h:45
DLLEXPORT void ReleaseInputHandler()
Destroys the networked input handler and all input objects.
DLLEXPORT void Error(const std::string &data) override
Definition: Logger.cpp:177
std::vector< Connection * > ConnectionsToTerminate
Handles everything related to connections.
virtual DLLEXPORT void CloseConnection(Connection &connection)
Marks a connection as closing.
#define GUARD_LOCK()
Definition: ThreadSafe.h:111
std::unique_ptr< SyncedVariables > VariableSyncer
The syncable variable holder associated with this instance.
Class that encapsulates common networking functionality that is required by all networked programs.
std::unique_lock< std::mutex > Lock
Definition: ThreadSafe.h:18
Represents a sent packet and holds all kinds of data for it.
virtual DLLEXPORT bool Init(const MasterServerInformation &info)