9 #include <boost/bind.hpp>
10 #include <boost/asio.hpp>
11 #include <boost/thread/thread.hpp>
13 class NetworkImpl
: public Network
17 virtual ~NetworkImpl();
18 virtual bool connect(const char* ip
, const char* port
);
19 virtual void send(const std::string
& message
);
20 virtual void sendln(const std::string
& message
);
21 virtual void startBuffering(char delimiter
= '\n');
22 virtual bool hasLines();
23 virtual std::string
popLine();
26 boost::asio::io_service io_service
;
27 boost::asio::ip::tcp::socket socket
;
29 std::vector
<std::string
> linesBuffer
;
33 virtual void readToBuffer();
36 using boost::asio::ip::tcp
;
38 NetworkImpl::NetworkImpl() : socket(io_service
), delimiter(0), connected(false)
43 NetworkImpl::~NetworkImpl()
47 bool NetworkImpl::connect(const char* ip
, const char* port
)
51 tcp::resolver
resolver(io_service
);
52 tcp::resolver::query
query(tcp::v4(), ip
, port
);
53 tcp::resolver::iterator iterator
= resolver
.resolve(query
);
55 socket
.connect(*iterator
);
57 catch (std::exception
& e
)
59 std::cerr
<< "Exception: " << e
.what() << "\n";
67 void NetworkImpl::startBuffering(char delimiter
)
69 this->delimiter
= delimiter
;
70 boost::thread
thread(boost::bind(&NetworkImpl::readToBuffer
, this));
73 void NetworkImpl::readToBuffer()
76 boost::asio::streambuf input
;
77 std::string hanging
; // Stores partial lines
78 while (boost::asio::read(socket
, input
, boost::asio::transfer_at_least(1))) {
79 std::istream
inputStream(&input
);
80 while (inputStream
.good()) {
82 // Get data until '\n' and take it too.
83 // Or until the end of the stream.
84 while (inputStream
.good()) {
85 int c
= inputStream
.get();
86 if (c
== delimiter
) { break; } // End of line.
87 if (c
< 0) { break; } // End of stream.
90 // If the stream hasn't ended yet, then a complete line has been received.
91 if (inputStream
.good()) {
92 // If there was a partially received line then connect it to its end that was just received.
93 std::string line
= hanging
+ sb
.str();
96 boost::mutex::scoped_lock
l(mutex
);
97 linesBuffer
.push_back(line
); // Storing the line.
102 // Line was only partially received, add it to hanging string.
108 catch (std::exception
& e
)
110 std::cerr
<< "Exception: " << e
.what() << "\n";
114 bool NetworkImpl::hasLines()
117 boost::mutex::scoped_lock
l(mutex
);
118 return linesBuffer
.size() > 0;
122 std::string
NetworkImpl::popLine()
125 boost::mutex::scoped_lock
l(mutex
);
126 std::string line
= linesBuffer
.front(); // FIFO
127 // Can't do front & back swap since we need to preserve the order.
128 linesBuffer
.erase(linesBuffer
.begin()); // O(n) erase :/
133 void NetworkImpl::send(const std::string
& message
)
137 boost::asio::write(socket
, boost::asio::buffer(message
, message
.size()));
141 void NetworkImpl::sendln(const std::string
& message
)
143 send(message
+ "\n");
146 Network
* Network::createNewNetwork()
148 return new NetworkImpl();