1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
#include "Swiften/Network/BoostConnection.h"
#include <iostream>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include "Swiften/EventLoop/MainEventLoop.h"
#include "Swiften/Base/String.h"
#include "Swiften/Base/ByteArray.h"
#include "Swiften/Network/DomainNameResolver.h"
#include "Swiften/Network/DomainNameResolveException.h"
namespace Swift {
static const size_t BUFFER_SIZE = 4096;
// -----------------------------------------------------------------------------
// A reference-counted non-modifiable buffer class.
class SharedBuffer {
public:
SharedBuffer(const ByteArray& data) :
data_(new std::vector<char>(data.begin(), data.end())),
buffer_(boost::asio::buffer(*data_)) {
}
// ConstBufferSequence requirements.
typedef boost::asio::const_buffer value_type;
typedef const boost::asio::const_buffer* const_iterator;
const boost::asio::const_buffer* begin() const { return &buffer_; }
const boost::asio::const_buffer* end() const { return &buffer_ + 1; }
private:
boost::shared_ptr< std::vector<char> > data_;
boost::asio::const_buffer buffer_;
};
// -----------------------------------------------------------------------------
BoostConnection::BoostConnection(boost::asio::io_service* ioService) :
socket_(*ioService), readBuffer_(BUFFER_SIZE) {
}
BoostConnection::~BoostConnection() {
}
void BoostConnection::listen() {
doRead();
}
void BoostConnection::connect(const String& domain) {
DomainNameResolver resolver;
try {
HostAddressPort addressPort = resolver.resolve(domain.getUTF8String());
boost::asio::ip::tcp::endpoint endpoint(
boost::asio::ip::address::from_string(addressPort.getAddress().toString()), addressPort.getPort());
socket_.async_connect(
endpoint,
boost::bind(&BoostConnection::handleConnectFinished, shared_from_this(), boost::asio::placeholders::error));
}
catch (const DomainNameResolveException& e) {
onError(DomainNameResolveError);
}
}
void BoostConnection::disconnect() {
//MainEventLoop::removeEventsFromOwner(shared_from_this());
socket_.close();
}
void BoostConnection::write(const ByteArray& data) {
boost::asio::async_write(socket_, SharedBuffer(data),
boost::bind(&BoostConnection::handleDataWritten, shared_from_this(), boost::asio::placeholders::error));
}
void BoostConnection::handleConnectFinished(const boost::system::error_code& error) {
if (!error) {
MainEventLoop::postEvent(boost::bind(boost::ref(onConnected)), shared_from_this());
doRead();
}
else if (error != boost::asio::error::operation_aborted) {
MainEventLoop::postEvent(boost::bind(boost::ref(onError), ConnectionError), shared_from_this());
}
}
void BoostConnection::doRead() {
socket_.async_read_some(
boost::asio::buffer(readBuffer_),
boost::bind(&BoostConnection::handleSocketRead, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}
void BoostConnection::handleSocketRead(const boost::system::error_code& error, size_t bytesTransferred) {
if (!error) {
MainEventLoop::postEvent(boost::bind(boost::ref(onDataRead), ByteArray(&readBuffer_[0], bytesTransferred)), shared_from_this());
doRead();
}
else if (error != boost::asio::error::operation_aborted) {
MainEventLoop::postEvent(boost::bind(boost::ref(onError), ReadError), shared_from_this());
}
}
void BoostConnection::handleDataWritten(const boost::system::error_code& error) {
if (error && error != boost::asio::error::operation_aborted) {
MainEventLoop::postEvent(boost::bind(boost::ref(onError), WriteError), shared_from_this());
}
}
}
|