Do not use not existing release function on socket.
[clanbomber-server.git] / src / client.cpp
1 /**
2  * @file client.cpp
3  * @author Johannes Posch
4  * @date 6 Dec 2018
5  * @brief File containing a basic session to communicate with the clients.
6  */
7
8 #include "client.h"
9 #include "jsonparser.h"
10 #include <boost/array.hpp>
11
12 using namespace std;
13 /* ----------------------------------------------------------------------------
14  *      PUBLIC FUNCTIONS
15  * ----------------------------------------------------------------------------
16  */
17
18 packet::ClientPacket Client::getInput()
19 {
20         // receive data from socket
21         this->receive();
22
23         while (!this->_receivePacketBuffer.empty())
24         {
25                 // packet structure for the input element
26                 packet::ClientPacket inputPacket;
27                 // get the first element
28                 string tmp = this->_receivePacketBuffer.front();
29                 this->_receivePacketBuffer.pop_front();
30                 if (this->_parser->strToClientPacket(tmp, inputPacket))
31                 {
32                         // check the states and configure them
33                         this->_clientState.state = inputPacket.state;
34                         this->_clientState.placeBomb = inputPacket.placeBomb;
35                 }
36         }
37
38         return this->_clientState;
39 }
40
41 void Client::sendFrame(packet::ServerPacket packet)
42 {
43         //packet.id = this->_Id;
44         this->send(this->_parser->serverPacketToStr(packet));
45 }
46
47 bool Client::isConnected() const
48 {
49         return this->_socket.is_open();
50 }
51
52 size_t Client::getID() const
53 {
54         return this->_Id;
55 }
56
57 boost::asio::ip::tcp::socket &Client::getSocket()
58 {
59         return this->_socket;
60 }
61
62 void Client::resetStates(){
63         this->_clientState.placeBomb = false;
64         this->_clientState.state = packet::types::ClientInputState::IDLE;
65 }
66
67 Client::~Client()
68 {
69         if (this->isConnected())
70         {
71                 this->_socket.close();
72         }
73         if (this->_ios != nullptr)
74         {
75                 delete this->_ios;
76                 this->_ios = nullptr;
77         }
78         if (this->_parser != nullptr)
79         {
80                 delete this->_parser;
81                 this->_parser = nullptr;
82         }
83 }
84
85 Client::UPtr Client::create(size_t const id, boost::asio::io_service *const ios)
86 {
87         return Client::UPtr(new Client(id, ios));
88 }
89
90 /* ----------------------------------------------------------------------------
91  *      PRIVATE FUNCTIONS
92  * ----------------------------------------------------------------------------
93  */
94
95 Client::Client(size_t const id, boost::asio::io_service *const ios) : _Id(id),
96                                                                                                                                           _ios(ios),
97                                                                                                                                           _socket(*ios),
98                                                                                                                                           _parser(new JSONParser()),
99                                                                                                                                           _clientState({this->_Id, packet::types::ClientInputState::IDLE, false}),
100                                                                                                                                           _receiveBuffer(this->_receiveBufSize) {}
101
102 void Client::receive()
103 {
104         if (!this->isConnected())
105         {
106                 return;
107         }
108
109         boost::array<char, 128> buf;
110         boost::system::error_code err;
111         try
112         {
113                 // receive as long as we have enough space in the receive buffer
114                 size_t read = 0;
115                 while (!err && this->_receiveBuffer.reserve() >= buf.size() && (read = this->_socket.read_some(boost::asio::buffer(buf), err)) > 0)
116                 {
117                         if (!err)
118                         {
119                                 std::copy(buf.begin(), buf.begin() + read, std::back_inserter(this->_receiveBuffer));
120                         }
121                 }
122
123                 // extract the packages
124                 boost::circular_buffer<char>::iterator pos;
125
126                 do
127                 {
128                         pos = find(this->_receiveBuffer.begin(), this->_receiveBuffer.end(), this->_packetTerminatingChar);
129                         if (pos != this->_receiveBuffer.end())
130                         {
131                                 string tmp;
132                                 copy(this->_receiveBuffer.begin(), pos, std::back_inserter(tmp));
133                                 //std::cout << tmp << std::endl;
134                                 this->_receiveBuffer.erase(this->_receiveBuffer.begin(), pos + 1);
135                                 this->_receivePacketBuffer.push_back(tmp);
136                         }
137                 } while (pos != this->_receiveBuffer.end());
138         }
139         catch (boost::exception const &)
140         {
141                 this->_socket.close();
142         }
143 }
144
145 void Client::send(string const &data)
146 {
147         if (!this->isConnected())
148         {
149                 return;
150         }
151
152         try
153         {
154                 this->_socket.write_some(boost::asio::buffer(data.c_str(), data.length() + 1));
155         }
156         catch (boost::exception const &)
157         {
158                 this->_socket.close();
159         }
160 }