Game no longer crashes at the beginning if no connection was made.
[NALCG.git] / src / client / network.cpp
blob32bc26da0cc8f8453d99c3878d189ec3b68788b4
1 // class dependencies
2 #include "network.h"
4 // system includes
5 #include <iostream>
6 #include <vector>
8 // boost includes
9 #include <boost/bind.hpp>
10 #include <boost/asio.hpp>
11 #include <boost/thread/thread.hpp>
13 class NetworkImpl : public Network
15 public:
16 NetworkImpl();
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();
25 protected:
26 boost::asio::io_service io_service;
27 boost::asio::ip::tcp::socket socket;
28 boost::mutex mutex;
29 std::vector<std::string> linesBuffer;
30 char delimiter;
31 bool connected;
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)
49 try
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";
60 connected = false;
61 return false;
63 connected = true;
64 return true;
67 void NetworkImpl::startBuffering(char delimiter)
69 this->delimiter = delimiter;
70 boost::thread thread(boost::bind(&NetworkImpl::readToBuffer, this));
73 void NetworkImpl::readToBuffer()
75 try {
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()) {
81 std::stringbuf sb;
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.
88 sb.sputc(c);
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.
99 hanging.clear();
101 else {
102 // Line was only partially received, add it to hanging string.
103 hanging += sb.str();
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 :/
129 return line;
133 void NetworkImpl::send(const std::string& message)
135 if (connected)
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();