eris 1.4.0
A WorldForge client library.
StreamSocket.cpp
1/*
2 Copyright (C) 2014 Erik Ogenvik
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19#ifdef HAVE_CONFIG_H
20#include "config.h"
21#endif
22
23#include "StreamSocket.h"
24#include "Log.h"
25
26#include <Atlas/Codec.h>
27#include <Atlas/Net/Stream.h>
28#include <Atlas/Objects/Encoder.h>
29
30using namespace boost::asio;
31
32static const int NEGOTIATE_TIMEOUT_SECONDS = 5;
33
34namespace Eris {
35
36StreamSocket::StreamSocket(io_service& io_service,
37 const std::string& client_name,
38 Atlas::Bridge& bridge,
39 Callbacks callbacks) :
40 m_io_service(io_service),
41 _bridge(bridge),
42 _callbacks(std::move(callbacks)),
43 mWriteBuffer(new boost::asio::streambuf()),
44 mSendBuffer(new boost::asio::streambuf()),
45 mInStream(&mReadBuffer),
46 mOutStream(mWriteBuffer.get()),
47 mShouldSend(false),
48 mIsSending(false),
49 _sc(new Atlas::Net::StreamConnect(client_name, mInStream, mOutStream)),
50 _negotiateTimer(io_service), _connectTimer(io_service),
51 m_codec(nullptr),
52 m_encoder(nullptr),
53 m_is_connected(false) {
54}
55
56StreamSocket::~StreamSocket() = default;
57
58void StreamSocket::detach() {
59 _callbacks = Callbacks();
60}
61
62void StreamSocket::startNegotiation() {
63 auto self(this->shared_from_this());
64 _negotiateTimer.expires_from_now(
65 std::chrono::seconds(NEGOTIATE_TIMEOUT_SECONDS));
66 _negotiateTimer.async_wait([this, self](const boost::system::error_code& ec) {
67 //If the negotiator still exists after the deadline it means that the negotation hasn't
68 //completed yet; we'll consider that a "timeout".
69 if (_sc != nullptr) {
70 if (_callbacks.stateChanged) {
71 debug() << "Client disconnected because of negotiation timeout.";
72// log(NOTICE, "Client disconnected because of negotiation timeout.");
73 _callbacks.stateChanged(DISCONNECTING);
74// mSocket.close();
75 }
76 }
77 });
78 _callbacks.stateChanged(NEGOTIATE);
79
80 _sc->poll();
81
82 write();
83 negotiate_read();
84}
85
86Atlas::Negotiate::State StreamSocket::negotiate() {
87 // poll and check if negotiation is complete
88 _sc->poll();
89
90 if (_sc->getState() == Atlas::Negotiate::IN_PROGRESS) {
91 return _sc->getState();
92 }
93
94 // Check if negotiation failed
95 if (_sc->getState() == Atlas::Negotiate::FAILED) {
96 return _sc->getState();
97 }
98 // Negotiation was successful
99
100 _negotiateTimer.cancel();
101
102 // Get the codec that negotiation established
103 m_codec = _sc->getCodec(_bridge);
104
105 // Acceptor is now finished with
106 _sc.reset();
107
108 if (m_codec == nullptr) {
109 error() << "Could not create codec during negotiation.";
110 return Atlas::Negotiate::FAILED;
111 }
112 // Create a new encoder to send high level objects to the codec
113 m_encoder = std::make_unique<Atlas::Objects::ObjectsEncoder>(*m_codec);
114
115 // This should always be sent at the beginning of a session
116 m_codec->streamBegin();
117
118 _callbacks.stateChanged(CONNECTED);
119
120 return Atlas::Negotiate::SUCCEEDED;
121}
122
123Atlas::Codec& StreamSocket::getCodec() {
124 assert(m_codec);
125 return *m_codec;
126}
127
128Atlas::Objects::ObjectsEncoder& StreamSocket::getEncoder() {
129 assert(m_encoder);
130 return *m_encoder;
131}
132
133}
Definition: Account.cpp:33
Methods that are used as callbacks.
Definition: StreamSocket.h:77