Leviathan  0.8.0.0
Leviathan game engine
RemoteConsole.cpp
Go to the documentation of this file.
1 // ------------------------------------ //
2 #include "RemoteConsole.h"
3 
4 #include "../TimeIncludes.h"
6 #include "Connection.h"
7 #include "NetworkRequest.h"
8 #include "NetworkResponse.h"
9 using namespace Leviathan;
10 using namespace std;
11 // ------------------------------------ //
13  CloseIfNoRemoteConsole(false), CanClose(false)
14 {}
15 
17 // ------------------------------------ //
19 {
20 
21  GUARD_LOCK();
22  // Check awaiting connections //
23  auto timenow = Time::GetCurrentTimePoint();
24 
25  for(size_t i = 0; i < AwaitingConnections.size(); i++) {
26  if(AwaitingConnections[i]->TimeoutTime < timenow) {
27  // Time it out //
28  Logger::Get()->Warning("RemoteConsole: Remote console wait connection timed out, "
29  "token " +
30  Convert::ToString(AwaitingConnections[i]->SessionToken));
31 
32  AwaitingConnections.erase(AwaitingConnections.begin() + i);
33  i--;
34  continue;
35  }
36  }
37 
38  // Special checks //
39  if(CloseIfNoRemoteConsole && CanClose) {
40  // Send close to application if no connection (or waiting for one) //
41  if(AwaitingConnections.size() == 0 && RemoteConsoleConnections.size() == 0) {
42  // Time to close //
43 
44  Logger::Get()->Info("RemoteConsole: closing the program because "
45  "CloseIfNoRemoteConsole, and no active connections");
47  }
48  }
49 
50  for(auto iter = RemoteConsoleConnections.begin();
51  iter != RemoteConsoleConnections.end();) {
52  if((*iter)->TerminateSession && !(*iter)->GetConnection()->IsValidForSend()) {
53 
54  Logger::Get()->Info("RemoteConsole: removing kill-queued session, token: " +
55  Convert::ToString((*iter)->SessionToken));
56  iter = RemoteConsoleConnections.erase(iter);
57  } else {
58  ++iter;
59  }
60  }
61 }
62 // ------------------------------------ //
64 {
65  return AwaitingConnections.size() != 0;
66 }
67 
69  const std::string& assignname /*= ""*/, bool onlylocalhost /*= false*/,
70  const MillisecondDuration& timeout /*= std::chrono::seconds(30)*/)
71 {
72  GUARD_LOCK();
73 
74  AwaitingConnections.push_back(shared_ptr<RemoteConsoleExpect>(
75  new RemoteConsoleExpect(assignname, SessionToken, onlylocalhost, timeout)));
76 }
77 // ------------------------------------ //
79  std::shared_ptr<Connection> connection, std::shared_ptr<NetworkRequest> request)
80 {
81  // Get data from the packet //
82  bool local = connection->IsTargetHostLocalhost();
83 
84  switch(request->GetType()) {
86  DEBUG_BREAK;
87  return true;
88  }
90  auto* opennew = static_cast<RequestRemoteConsoleOpen*>(request.get());
91 
92  int sessiontoken = opennew->SessionToken;
93 
94  // Look for a matching awaiting connection //
95  for(size_t i = 0; i < AwaitingConnections.size(); i++) {
96  if((AwaitingConnections[i]->OnlyLocalhost && local) ||
97  !AwaitingConnections[i]->OnlyLocalhost) {
98  if(AwaitingConnections[i]->SessionToken == sessiontoken) {
99  // Match found //
100  Logger::Get()->Info("RemoteConsole: matching connection request got!");
101 
102  // Add to real connections //
103  RemoteConsoleConnections.push_back(std::make_shared<RemoteConsoleSession>(
104  AwaitingConnections[i]->ConnectionName, connection,
105  AwaitingConnections[i]->SessionToken));
106 
107  // Open new, send succeed packet back //
108  connection->SendPacketToConnection(
109  std::make_shared<ResponseNone>(
111  request->GetIDForResponse()),
113 
114  AwaitingConnections.erase(AwaitingConnections.begin() + i);
115  return true;
116  }
117  }
118  }
119  }
120  default: return false;
121  }
122 }
123 // ------------------------------------ //
125  std::shared_ptr<Connection> connectiontouse, const std::string& connectionname, int token)
126 {
127  GUARD_LOCK();
128 
129  // Add to the expected connections //
130  AwaitingConnections.push_back(
131  shared_ptr<RemoteConsoleExpect>(new RemoteConsoleExpect(connectionname, token,
132  connectiontouse->IsTargetHostLocalhost(), std::chrono::seconds(15))));
133 
134  // Send a request that the target connects to us //
135  connectiontouse->SendPacketToConnection(
136  std::make_shared<RequestDoRemoteConsoleOpen>(token), RECEIVE_GUARANTEE::Critical);
137 }
138 // ------------------------------------ //
140  std::shared_ptr<NetworkRequest> request, std::shared_ptr<Connection> connection)
141 {
142  // First check if it should be handled by CanOpenNewConnection which handless
143  // all open connection packets //
146  CanOpenNewConnection(connection, request);
147  return;
148  }
149 
150  GUARD_LOCK();
151 
152  // Handle normal RemoteConsole request //
153  switch(request->GetType()) {
155  // Kill connection //
156  GetRemoteConsoleSessionForConnection(guard, *connection)->KillConnection();
157  Logger::Get()->Info("RemoteConsole: closing connection due to close request");
158 
159  connection->SendPacketToConnection(
160  std::make_shared<ResponseNone>(
163  return;
164  }
165  default: LOG_ERROR("RemoteConsole unhandled request type");
166  }
167 
168  DEBUG_BREAK;
169 }
170 
172  std::shared_ptr<NetworkResponse> response, Connection& connection,
173  std::shared_ptr<NetworkRequest> potentialrequest)
174 {
175  // We can detect close messages //
176  switch(response->GetType()) {
179  // These shouldn't be received //
180  Logger::Get()->Warning(
181  "RemoteConsole: HandleRemoteConsoleResponse: got a "
182  "packet of type remote opened/"
183  "remote closed, not expected to be received without us requesting it");
184  } break;
185  default:
186  Logger::Get()->Warning("RemoteConsole: HandleRemoteConsoleResponse: got a "
187  "packet of unknown type, "
188  "maybe this should not have been passed to RemoteConsole");
189  DEBUG_BREAK;
190  }
191 }
192 // ------------------------------------ //
194 {
195  CloseIfNoRemoteConsole = state;
196 }
197 
199  Lock& guard, Connection& connection)
200 {
201  // Loop over and compare pointers //
202  for(size_t i = 0; i < RemoteConsoleConnections.size(); i++) {
203  if(RemoteConsoleConnections[i]->GetConnection() == &connection) {
204  // Found a matching one //
205  return RemoteConsoleConnections[i].get();
206  }
207  }
208 
209  return nullptr;
210 }
211 // ------------------------------------ //
213 {
214  return RemoteConsoleConnections.size();
215 }
216 
217 DLLEXPORT std::shared_ptr<Leviathan::Connection>
219 {
220  for(auto& connection : RemoteConsoleConnections) {
221  if(connection->ConnectionName == name) {
222 
223  return connection->CorrespondingConnection;
224  }
225  }
226 
227  return nullptr;
228 }
229 // ------------------------------------ //
231 {
232  CanClose = true;
233 }
234 // ------------------ RemoteConsoleExpect ------------------ //
235 Leviathan::RemoteConsole::RemoteConsoleExpect::RemoteConsoleExpect(const std::string& name,
236  int token, bool onlylocalhost, const MillisecondDuration& timeout) :
237  ConnectionName(name),
238  SessionToken(token), OnlyLocalhost(onlylocalhost),
239  TimeoutTime(Time::GetCurrentTimePoint() + timeout)
240 {}
241 // ------------------ RemoteConsoleSession ------------------ //
243 {
244  // Send close request //
245  if(CorrespondingConnection->IsValidForSend()) {
246 
247  CorrespondingConnection->SendPacketToConnection(
248  std::make_shared<RequestNone>(NETWORK_REQUEST_TYPE::CloseRemoteConsole),
250  }
251 }
252 // ------------------------------------ //
254 {
255  return CorrespondingConnection.get();
256 }
257 
259 {
260  TerminateSession = true;
261 }
NETWORK_REQUEST_TYPE GetType() const
DLLEXPORT bool IsAwaitingConnections()
Returns true if connections are marked as awaiting.
DLLEXPORT void HandleRemoteConsoleRequestPacket(std::shared_ptr< NetworkRequest > request, std::shared_ptr< Connection > connection)
DLLEXPORT std::shared_ptr< SentRequest > SendPacketToConnection(const std::shared_ptr< NetworkRequest > &request, RECEIVE_GUARANTEE guarantee)
Definition: Connection.cpp:139
DLLEXPORT bool CanOpenNewConnection(std::shared_ptr< Connection > connection, std::shared_ptr< NetworkRequest > request)
Returns true if request from connection is allowed to open a remote console session.
DLLEXPORT void Info(const std::string &data) override
Definition: Logger.cpp:164
#define LOG_ERROR(x)
Definition: Define.h:96
Helper class for getting the time.
Definition: TimeIncludes.h:23
DLLEXPORT void UpdateStatus()
Called before packets are handled.
DLLEXPORT void ExpectNewConnection(int SessionToken, const std::string &assignname="", bool onlylocalhost=false, const MillisecondDuration &timeout=std::chrono::seconds(30))
DLLEXPORT void KillConnection()
Sets the connection as closing.
DLLEXPORT RemoteConsoleSession * GetRemoteConsoleSessionForConnection(Lock &guard, Connection &connection)
Gets a matching RemoteConsoleSession from Connection.
DLLEXPORT void HandleRemoteConsoleResponse(std::shared_ptr< NetworkResponse > response, Connection &connection, std::shared_ptr< NetworkRequest > potentialrequest)
NETWORK_RESPONSE_TYPE GetType() const
The receiving side is now allowed to open a remote console with the token.
DLLEXPORT void SetCloseIfNoRemoteConsole(bool state)
Sets the remote console to close the game if there are no connections.
DLLEXPORT void MarkAsClosing()
Thread safely marks the game to close sometime.
DLLEXPORT void Warning(const std::string &data) override
Definition: Logger.cpp:190
uint32_t GetIDForResponse() const
The id number for a response to this is the same as the message number that this request is in.
DLLEXPORT size_t GetActiveConnectionCount()
Returns active number of connections.
std::chrono::duration< int64_t, std::milli > MillisecondDuration
Definition: TimeIncludes.h:14
static DLLEXPORT TimePoint GetCurrentTimePoint()
DLLEXPORT std::shared_ptr< Connection > GetConnectionForRemoteConsoleSession(const std::string &name)
Gets the corresponding Connection object from a RemoteConsoleSession session indicated by name.
static std::string ToString(const T &val)
Definition: Convert.h:72
static DLLEXPORT Logger * Get()
Definition: Logger.cpp:106
static DLLEXPORT LeviathanApplication * Get()
Definition: Application.cpp:32
Class that handles a single connection to another instance.
Definition: Connection.h:105
#define DLLEXPORT
Definition: Include.h:84
DLLEXPORT bool IsTargetHostLocalhost()
The access mask controls which registered functions and classes a script sees.
Definition: GameModule.h:12
DLLEXPORT void OfferConnectionTo(std::shared_ptr< Connection > connectiontouse, const std::string &connectionname, int token)
Does everything needed to allow the client on the connection to connect to us.
#define GUARD_LOCK()
Definition: ThreadSafe.h:111
DLLEXPORT Connection * GetConnection()
std::unique_lock< std::mutex > Lock
Definition: ThreadSafe.h:18
void SetAllowClose()
Called by Engine after command line has been processed.