eris  1.4.0
A WorldForge client library.
BaseConnection.cpp
1 #include <utility>
2 
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
6 
7 #include "BaseConnection.h"
8 
9 #include "Exceptions.h"
10 #include "Log.h"
11 #include "StreamSocket_impl.h"
12 
13 #include <Atlas/Codec.h>
14 #include <Atlas/Net/Stream.h>
15 #include <Atlas/Objects/Encoder.h>
16 
17 #include <sigc++/slot.h>
18 
19 #include <sstream>
20 #include <Atlas/Objects/Factories.h>
21 #include "CustomEntities.h"
22 
23 #ifdef _WIN32
24 
25 #ifndef snprintf
26 #define snprintf _snprintf
27 #endif
28 
29 #endif // _WIN32
30 
31 using namespace boost::asio;
32 
33 namespace Eris
34 {
35 
37 
38 BaseConnection::BaseConnection(io_service& io_service,
39  std::string clientName,
40  std::string id) :
41  _io_service(io_service),
42  _factories(new Atlas::Objects::Factories()),
43  _status(DISCONNECTED),
44  _id(std::move(id)),
45  _clientName(std::move(clientName)),
46  _bridge(nullptr),
47  _port(0) {
48  if (!_factories->hasFactory("sys")) {
49  Atlas::Objects::Entity::SYS_NO = _factories->addFactory("sys",
50  &Atlas::Objects::factory<Atlas::Objects::Entity::SysData>, &Atlas::Objects::defaultInstance<Atlas::Objects::Entity::SysData>);
51  }
52 }
53 
55 {
56  if (_status != DISCONNECTED) {
57  hardDisconnect(true);
58  }
59  if (_socket) {
60  _socket->detach();
61  _socket.reset();
62  }
63 }
64 
65 int BaseConnection::connectRemote(const std::string & host, short port)
66 {
67  if (_socket) {
68  _socket->detach();
69  _socket.reset();
70  }
71  try {
72  StreamSocket::Callbacks callbacks;
73  callbacks.dispatch = [&] {this->dispatch();};
74  callbacks.stateChanged =
75  [&](StreamSocket::Status state) {
76  if (state == StreamSocket::NEGOTIATE) {
77  //Turn off Nagle's algorithm to increase responsiveness.
78  ((ResolvableAsioStreamSocket<ip::tcp>*)_socket.get())->getAsioSocket().set_option(ip::tcp::no_delay(true));
79  }
80  this->stateChanged(state);};
81  auto socket = new ResolvableAsioStreamSocket<ip::tcp>(_io_service, _clientName,
82  *_bridge, callbacks);
83  _socket.reset(socket);
84  std::stringstream ss;
85  ss << port;
86  ip::tcp::resolver::query query(host, ss.str());
88  socket->connectWithQuery(query);
89  } catch (const std::exception& e) {
90  error() << "Error when trying to connect to " << host << " on port "
91  << port << ": " << e.what();
92  hardDisconnect(true);
93  return -1;
94  }
95  return 0;
96 }
97 
98 int BaseConnection::connectLocal(const std::string & filename)
99 {
100  if (_socket) {
101  _socket->detach();
102  _socket.reset();
103  }
104 #ifdef _WIN32
105  return 0;
106 #else
107  try {
108  StreamSocket::Callbacks callbacks;
109  callbacks.dispatch = [&] {this->dispatch();};
110  callbacks.stateChanged =
111  [&](StreamSocket::Status state) {this->stateChanged(state);};
113  _io_service, _clientName, *_bridge, callbacks);
114  _socket.reset(socket);
116  socket->connect(local::stream_protocol::endpoint(filename));
117  } catch (const std::exception& e) {
118  hardDisconnect(true);
119  return -1;
120  }
121  return 0;
122 #endif
123 }
124 
125 void BaseConnection::stateChanged(StreamSocket::Status status)
126 {
127  switch (status) {
130  break;
132  onConnectTimeout();
133  break;
135  handleFailure("Failed to connect to " + _host);
136  hardDisconnect(true);
137  break;
140  break;
142  hardDisconnect(true);
143  break;
145  onNegotiateTimeout();
146  break;
149  onConnect();
150  break;
152  hardDisconnect(true);
153  break;
156  break;
157  default:
158  break;
159  }
160 }
161 
163 {
164  if (_status == DISCONNECTED)
165  return;
166 
167  if (_socket) {
168  _socket->detach();
169  _socket.reset();
170  }
171 
173  if (emit) {
174  Disconnected.emit();
175  }
176 }
177 
179 {
180  // tell anyone who cares with a signal
181  Connected.emit();
182 }
183 
184 void BaseConnection::onConnectTimeout()
185 {
186  std::ostringstream os;
187  os << "Connect to " << _host << ':' << _port << " timed out";
188  handleTimeout(os.str());
189  hardDisconnect(true);
190 }
191 
192 void BaseConnection::onNegotiateTimeout()
193 {
194  handleTimeout("Atlas negotiation timed out");
195  hardDisconnect(true);
196 }
197 
199 {
200  _status = sc;
201 }
202 
203 const std::string& BaseConnection::getHost() const
204 {
205  return _host;
206 }
207 
209 {
210  return _port;
211 }
212 
213 Atlas::Objects::Factories& BaseConnection::getFactories() {
214  return *_factories;
215 }
216 
217 const Atlas::Objects::Factories& BaseConnection::getFactories() const {
218  return *_factories;
219 }
220 
221 } // of namespace
Status
possible states for the connection
virtual int connectLocal(const std::string &socket)
connection fully established
Definition: StreamSocket.h:67
void hardDisconnect(bool emit)
STL namespace.
stream / socket connection in progress
Definition: StreamSocket.h:61
virtual int connectRemote(const std::string &host, short port)
std::string _clientName
the client identified used during connection
connection fully established
failure when trying to establish a connection
Definition: StreamSocket.h:63
stream / socket connection in progress
Methods that are used as callbacks.
Definition: StreamSocket.h:76
clean disconnection in progress
Definition: StreamSocket.h:70
clean disconnection in progress
virtual ~BaseConnection()
destructor, will perform a hard disconnect if necessary
virtual void handleFailure(const std::string &msg)=0
derived-class notification when a failure occurs
virtual void setStatus(Status sc)
update the connection status and generate signals
const std::string & getHost() const
Definition: Account.cpp:33
Template specialization which uses boost::asio sockets.
Definition: StreamSocket.h:184
Template specialization which uses boost::asio sockets with resolvers (i.e. TCP and UDP...
Definition: StreamSocket.h:205
Atlas::Bridge * _bridge
sigc::signal< void > Connected
sent on successful negotiation of a game server connection
Atlas negotiation in progress.
std::function< void(Status)> stateChanged
Called when the internal state has changed.
Definition: StreamSocket.h:86
Status _status
current status of the connection
short _port
the port we&#39;re connected to
std::function< void()> dispatch
Called when operations have arrived and needs dispatching.
Definition: StreamSocket.h:81
failure when negotiating
Definition: StreamSocket.h:66
short getPort() const
virtual void onConnect()
derived-class notification when connection and negotiation is completed
timeout when trying to establish a connection
Definition: StreamSocket.h:62
std::string _host
the host name we&#39;re connected to
sigc::signal< void > Disconnected
final disconnect (or hard disocnnect) notifcation
timeout when negotiating
Definition: StreamSocket.h:65
Atlas negotiation in progress.
Definition: StreamSocket.h:64