Babel
Epitech's C++ VoIP project
AsioTCPConnection.hpp
Go to the documentation of this file.
1 //
2 // Created by cbihan on 28/09/2021.
3 //
4 
5 #pragma once
6 
7 #include <functional>
8 #include <asio.hpp>
9 #include <bit>
10 #include "Utilities/SwapEndian.hpp"
12 #include "Network/Message.hpp"
13 
14 namespace Babel
15 {
17  template<typename T>
19  {
20  public:
22  void connect(const std::string &hostname, uint16_t port) override;
23 
25  void disconnect() override;
26 
28  bool isConnected() const override;
29 
31  void send(Message<T> message) override;
32 
34  void readForMessages() override;
35 
37  uint64_t getId() const override;
38 
40  std::string getPeerIp() const override;
41 
43  uint16_t getPeerPort() const override;
44 
46  void setId(uint64_t id) override;
47 
49  void setCallbackOnMessage(std::function<void(Message<T>)> callMessageReceived) override;
50 
51  explicit AsioTCPConnection(asio::io_context &ioContext,
52  asio::ip::tcp::socket socket
53  );
54 
55  ~AsioTCPConnection() override;
56 
57  private:
58 
60  void writeHeader();
62  void writeBody();
64  void readHeader();
66  void readBody();
67 
68 
70  asio::io_context &_ioContext;
72  asio::ip::tcp::socket _socket;
74  std::function<void(Message<T>)> _callbackMessageReceived;
82  uint64_t _id;
83 
84  };
85 
86  template<typename T>
87  AsioTCPConnection<T>::AsioTCPConnection(asio::io_context &ioContext,
88  asio::ip::tcp::socket socket
89  )
90  : _ioContext(ioContext),
91  _socket(std::move(socket)),
92  _callbackMessageReceived([](auto) {}),
93  _id(0)
94  {
95  }
96 
97  template<typename T>
99  )
100  {
101  this->disconnect();
102  }
103 
104  template<typename T>
105  void AsioTCPConnection<T>::connect(const std::string &, uint16_t)
106  {
107  }
108 
109  template<typename T>
111  {
112  return this->_id;
113  }
114 
115  template<typename T>
116  void AsioTCPConnection<T>::setId(uint64_t id)
117  {
118  this->_id = id;
119  }
120 
121  template<typename T>
123  {
124  if (this->isConnected()) {
125  asio::post(this->_ioContext, [this]() { this->_socket.close(); });
126  }
127  }
128 
129  template<typename T>
131  {
132  return this->_socket.is_open();
133  }
134 
135  template<typename T>
137  {
138  message.header.handleEndianness();
139  asio::post(this->_ioContext, [this, message] {
140  bool isMessageBeingSend = this->_messagesOut.empty();
141 
142  this->_messagesOut.pushBack(message);
143  if (isMessageBeingSend) {
144  this->writeHeader();
145  }
146  });
147  }
148 
149  template<typename T>
150  void AsioTCPConnection<T>::setCallbackOnMessage(std::function<void(Message<T>)> callMessageReceived)
151  {
152  this->_callbackMessageReceived = std::move(callMessageReceived);
153  }
154 
155  template<typename T>
157  {
158  this->readHeader();
159  }
160 
161  template<typename T>
163  {
164  asio::async_write(this->_socket, asio::buffer(&this->_messagesOut.front().header, sizeof(MessageHeader<T>)),
165  [this](std::error_code ec, std::size_t) {
166  if (!ec) {
167  if (this->_messagesOut.front().body.size() > 0) {
168  this->writeBody();
169  } else {
170  this->_messagesOut.popFront();
171 
172  if (!this->_messagesOut.empty()) {
173  this->writeHeader();
174  }
175  }
176  } else {
177  std::cout << "[" << this->_id << "] Write Header Fail." << std::endl;
178  this->_socket.close();
179  }
180  });
181  }
182 
183  template<typename T>
185  {
186  asio::async_write(this->_socket,
187  asio::buffer(this->_messagesOut.front().body.data(), this->_messagesOut.front().body.size()),
188  [this](std::error_code ec, std::size_t) {
189  if (!ec) {
190  this->_messagesOut.popFront();
191 
192  if (!this->_messagesOut.empty()) {
193  this->writeHeader();
194  }
195  } else {
196  std::cout << "[" << this->_id << "] Write Body Fail." << std::endl;
197  this->_socket.close();
198  }
199  });
200  }
201 
202  template<typename T>
204  {
205  asio::async_read(this->_socket, asio::buffer(&this->_tmpMessage.header, sizeof(MessageHeader<T>)),
206  [this](std::error_code ec, std::size_t) {
207  if (!ec) {
208  this->_tmpMessage.header.handleEndianness();
209  if (this->_tmpMessage.header.bodySize > 0) {
210  this->_tmpMessage.body.resize(this->_tmpMessage.header.bodySize);
211  this->readBody();
212  } else {
213  this->_messagesIn.pushBack(this->_tmpMessage);
214  this->_callbackMessageReceived(this->_tmpMessage);
215  this->readHeader();
216  }
217  } else {
218  std::cout << "[" << this->_id << "] Read Header Fail." << std::endl;
219  this->_socket.close();
220  }
221  });
222  }
223 
224  template<typename T>
226  {
227  asio::async_read(this->_socket, asio::buffer(this->_tmpMessage.body.data(), this->_tmpMessage.body.size()),
228  [this](std::error_code ec, std::size_t) {
229  if (!ec) {
230  this->_messagesIn.pushBack(this->_tmpMessage);
231  this->_callbackMessageReceived(this->_tmpMessage);
232  this->readHeader();
233  } else {
234  std::cout << "[" << this->_id << "] Read Body Fail." << std::endl;
235  this->_socket.close();
236  }
237  });
238  }
239 
240  template<typename T>
242  {
243  return this->_socket.remote_endpoint().address().to_string();
244  }
245 
246  template<typename T>
248  {
249  return this->_socket.remote_endpoint().port();
250  }
251 }
Message.hpp
Babel::AsioTCPConnection::_id
uint64_t _id
id used to identify the connection
Definition: AsioTCPConnection.hpp:82
Babel::AsioTCPConnection::~AsioTCPConnection
~AsioTCPConnection() override
Definition: AsioTCPConnection.hpp:98
Babel::AsioTCPConnection::AsioTCPConnection
AsioTCPConnection(asio::io_context &ioContext, asio::ip::tcp::socket socket)
Definition: AsioTCPConnection.hpp:87
Babel::AsioTCPConnection::connect
void connect(const std::string &hostname, uint16_t port) override
connect to a hostname and a port
Definition: AsioTCPConnection.hpp:105
Babel::AsioTCPConnection::setCallbackOnMessage
void setCallbackOnMessage(std::function< void(Message< T >)> callMessageReceived) override
set the callback to be called when a message is received
Definition: AsioTCPConnection.hpp:150
Babel::AsioTCPConnection::_tmpMessage
Message< T > _tmpMessage
Message used when reading a message.
Definition: AsioTCPConnection.hpp:80
Babel::Message::header
MessageHeader< T > header
The message metadata.
Definition: Message.hpp:49
Babel::MessageHeader
Definition: Message.hpp:20
ITCPConnection.hpp
Babel::Message
Definition: Message.hpp:46
Babel::AsioTCPConnection::getPeerPort
uint16_t getPeerPort() const override
get the connected pair port
Definition: AsioTCPConnection.hpp:247
Babel::AsioTCPConnection::_callbackMessageReceived
std::function< void(Message< T >)> _callbackMessageReceived
The function called when a message has been fully received.
Definition: AsioTCPConnection.hpp:74
SwapEndian.hpp
Babel::AsioTCPConnection::readForMessages
void readForMessages() override
listen for new messages
Definition: AsioTCPConnection.hpp:156
Babel
Definition: IAudioManager.hpp:13
Babel::AsioTCPConnection::writeBody
void writeBody()
write a message body
Definition: AsioTCPConnection.hpp:184
Babel::AsioTCPConnection::getId
uint64_t getId() const override
Get the id of this connection.
Definition: AsioTCPConnection.hpp:110
Babel::TSQueue
Thread Safe queue.
Definition: TSQueue.hpp:17
Babel::AsioTCPConnection::getPeerIp
std::string getPeerIp() const override
Get the connected pair address.
Definition: AsioTCPConnection.hpp:241
Babel::ITCPConnection
Definition: ITCPConnection.hpp:16
Babel::AsioTCPConnection
Asio implementation of a tcp communication.
Definition: AsioTCPConnection.hpp:18
Babel::AsioTCPConnection::setId
void setId(uint64_t id) override
set the id of the connection
Definition: AsioTCPConnection.hpp:116
Babel::AsioTCPConnection::readBody
void readBody()
read a message body
Definition: AsioTCPConnection.hpp:225
Babel::AsioTCPConnection::writeHeader
void writeHeader()
write a message header
Definition: AsioTCPConnection.hpp:162
Babel::AsioTCPConnection::readHeader
void readHeader()
read a message header
Definition: AsioTCPConnection.hpp:203
Babel::AsioTCPConnection::_messagesIn
TSQueue< Message< T > > _messagesIn
All the received messages.
Definition: AsioTCPConnection.hpp:76
Babel::AsioTCPConnection::disconnect
void disconnect() override
disconnect the connection
Definition: AsioTCPConnection.hpp:122
Babel::AsioTCPConnection::isConnected
bool isConnected() const override
Tells if the connection is up.
Definition: AsioTCPConnection.hpp:130
Babel::AsioTCPConnection::_ioContext
asio::io_context & _ioContext
The asio context to link everything.
Definition: AsioTCPConnection.hpp:70
Babel::AsioTCPConnection::send
void send(Message< T > message) override
Send the message.
Definition: AsioTCPConnection.hpp:136
Babel::AsioTCPConnection::_socket
asio::ip::tcp::socket _socket
The connection's socket.
Definition: AsioTCPConnection.hpp:72
Babel::AsioTCPConnection::_messagesOut
TSQueue< Message< T > > _messagesOut
All the messages that need to be sent.
Definition: AsioTCPConnection.hpp:78