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
31using namespace boost::asio;
32
33namespace Eris
34{
35
37
38BaseConnection::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
65int BaseConnection::connectRemote(const std::string & host, short port)
66{
67 if (_socket) {
68 _socket->detach();
69 _socket.reset();
70 }
71 try {
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
98int 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
125void 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
184void BaseConnection::onConnectTimeout()
185{
186 std::ostringstream os;
187 os << "Connect to " << _host << ':' << _port << " timed out";
188 handleTimeout(os.str());
189 hardDisconnect(true);
190}
191
192void BaseConnection::onNegotiateTimeout()
193{
194 handleTimeout("Atlas negotiation timed out");
195 hardDisconnect(true);
196}
197
199{
200 _status = sc;
201}
202
203const std::string& BaseConnection::getHost() const
204{
205 return _host;
206}
207
209{
210 return _port;
211}
212
213Atlas::Objects::Factories& BaseConnection::getFactories() {
214 return *_factories;
215}
216
217const Atlas::Objects::Factories& BaseConnection::getFactories() const {
218 return *_factories;
219}
220
221} // of namespace
Template specialization which uses boost::asio sockets.
Definition: StreamSocket.h:185
const std::string & getHost() const
virtual void handleFailure(const std::string &msg)=0
derived-class notification when a failure occurs
sigc::signal< void > Connected
sent on successful negotiation of a game server connection
Status _status
current status of the connection
void hardDisconnect(bool emit)
virtual int connectLocal(const std::string &socket)
virtual ~BaseConnection()
destructor, will perform a hard disconnect if necessary
sigc::signal< void > Disconnected
final disconnect (or hard disocnnect) notifcation
Atlas::Bridge * _bridge
virtual void onConnect()
derived-class notification when connection and negotiation is completed
std::string _clientName
the client identified used during connection
short _port
the port we're connected to
std::string _host
the host name we're connected to
virtual void setStatus(Status sc)
update the connection status and generate signals
BaseConnection(boost::asio::io_service &io_service, std::string clientName, std::string id)
create an unconnected instance
virtual int connectRemote(const std::string &host, short port)
Status
possible states for the connection
@ DISCONNECTING
clean disconnection in progress
@ CONNECTING
stream / socket connection in progress
@ DISCONNECTED
finished disconnection
@ NEGOTIATE
Atlas negotiation in progress.
@ CONNECTED
connection fully established
Template specialization which uses boost::asio sockets with resolvers (i.e. TCP and UDP,...
Definition: StreamSocket.h:206
@ DISCONNECTING
clean disconnection in progress
Definition: StreamSocket.h:70
@ NEGOTIATE_TIMEOUT
timeout when negotiating
Definition: StreamSocket.h:65
@ NEGOTIATE_FAILED
failure when negotiating
Definition: StreamSocket.h:66
@ CONNECTED
connection fully established
Definition: StreamSocket.h:67
@ CONNECTING_FAILED
failure when trying to establish a connection
Definition: StreamSocket.h:63
@ CONNECTING_TIMEOUT
timeout when trying to establish a connection
Definition: StreamSocket.h:62
@ CONNECTION_FAILED
connection failed
Definition: StreamSocket.h:68
@ NEGOTIATE
Atlas negotiation in progress.
Definition: StreamSocket.h:64
@ CONNECTING
stream / socket connection in progress
Definition: StreamSocket.h:61
Definition: Account.cpp:33
Methods that are used as callbacks.
Definition: StreamSocket.h:77
std::function< void(Status)> stateChanged
Called when the internal state has changed.
Definition: StreamSocket.h:86
std::function< void()> dispatch
Called when operations have arrived and needs dispatching.
Definition: StreamSocket.h:81