Kea  2.5.3
tcp_connection.h
Go to the documentation of this file.
1 // Copyright (C) 2022 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #ifndef TCP_CONNECTION_H
8 #define TCP_CONNECTION_H
9 
10 #include <asiolink/asio_wrapper.h>
12 #include <asiolink/io_service.h>
14 
15 #include <boost/enable_shared_from_this.hpp>
16 #include <boost/system/error_code.hpp>
17 #include <boost/shared_ptr.hpp>
18 
19 #include <array>
20 #include <functional>
21 #include <string>
22 #include <iostream>
23 
24 #include <mutex>
25 
26 namespace isc {
27 namespace tcp {
28 
30 typedef std::vector<uint8_t> WireData;
31 typedef boost::shared_ptr<WireData> WireDataPtr;
32 
34 class TcpMessage {
35 public:
37  virtual ~TcpMessage(){
38  };
39 
43  const uint8_t* getWireData() const {
44  if (wire_data_.empty()) {
45  isc_throw(InvalidOperation, "TcpMessage::getWireData() - cannot access empty wire data");
46  }
47 
48  return (wire_data_.data());
49  }
50 
52  size_t getWireDataSize() const {
53  return (wire_data_.size());
54  }
55 
56 protected:
59 };
60 
62 class TcpRequest : public TcpMessage {
63 public:
65  virtual ~TcpRequest(){};
66 
72  virtual size_t postBuffer(const void* buf, const size_t nbytes) = 0;
73 
77  virtual bool needData() const = 0;
78 
84  virtual std::string logFormatRequest(const size_t limit = 0) const = 0;
85 
87  virtual void unpack() = 0;
88 
89 private:
90 
96  std::string logFormatRequestSafe(const size_t limit = 0) const;
97 };
98 
100 typedef boost::shared_ptr<TcpRequest> TcpRequestPtr;
101 
103 class TcpResponse : public TcpMessage {
104 public:
107  : send_in_progress_(false) {};
108 
110  virtual ~TcpResponse() {};
111 
117  bool wireDataAvail() const {
118  return (!wire_data_.empty());
119  }
120 
122  virtual void pack() = 0;
123 
127  virtual void consumeWireData(const size_t length);
128 
129  bool sendInProgress() {
130  return (send_in_progress_);
131  }
132 
133 private:
135  bool send_in_progress_;
136 };
137 
138 typedef boost::shared_ptr<TcpResponse> TcpResponsePtr;
139 
142 public:
143  TcpConnectionError(const char* file, size_t line, const char* what) :
144  isc::Exception(file, line, what) { };
145 };
146 
151 class TcpConnectionPool;
152 
154 typedef std::function<bool(const boost::asio::ip::tcp::endpoint&)> TcpConnectionFilterCallback;
155 
157 class TcpConnection : public boost::enable_shared_from_this<TcpConnection> {
158 private:
159 
162  typedef std::function<void(boost::system::error_code ec, size_t length)>
163  SocketCallbackFunction;
164 
168  class SocketCallback {
169  public:
170 
175  SocketCallback(SocketCallbackFunction socket_callback)
176  : callback_(socket_callback) {
177  }
178 
188  void operator()(boost::system::error_code ec, size_t length = 0);
189 
190  private:
192  SocketCallbackFunction callback_;
193  };
194 
195 public:
196 
212  const TcpConnectionAcceptorPtr& acceptor,
213  const asiolink::TlsContextPtr& tls_context,
214  TcpConnectionPool& connection_pool,
215  const TcpConnectionAcceptorCallback& acceptor_callback,
216  const TcpConnectionFilterCallback& connection_filter,
217  const long idle_timeout,
218  const size_t read_max = 32768);
219 
223  virtual ~TcpConnection();
224 
229  void asyncAccept();
230 
232  virtual void shutdown();
233 
235  virtual void close();
236 
241  void doHandshake();
242 
255  void doRead(TcpRequestPtr request = TcpRequestPtr());
256 
270  TcpRequestPtr postData(TcpRequestPtr request, WireData& input_data);
271 
276  virtual void requestReceived(TcpRequestPtr request) = 0;
277 
286 
290  size_t getReadMax() const {
291  return (read_max_);
292  }
293 
298  void setReadMax(const size_t read_max);
299 
304  virtual bool responseSent(TcpResponsePtr response) = 0;
305 
309  static const boost::asio::ip::tcp::endpoint& NO_ENDPOINT() {
310  static boost::asio::ip::tcp::endpoint endpoint;
311  return (endpoint);
312  }
313 
318  const boost::asio::ip::tcp::endpoint getRemoteEndpoint() const {
319  return (remote_endpoint_);
320  }
321 
322 protected:
323 
332  void doWrite(TcpResponsePtr response);
333 
339  void asyncSendResponse(TcpResponsePtr response);
340 
349  void acceptorCallback(const boost::system::error_code& ec);
350 
357  void handshakeCallback(const boost::system::error_code& ec);
358 
369  void socketReadCallback(TcpRequestPtr request,
370  boost::system::error_code ec,
371  size_t length);
372 
379  virtual void socketWriteCallback(TcpResponsePtr request,
380  boost::system::error_code ec,
381  size_t length);
382 
390  void shutdownCallback(const boost::system::error_code& ec);
391 
393  void setupIdleTimer();
394 
396  void idleTimeoutCallback();
397 
401  virtual void shutdownConnection();
402 
404  virtual void stopThisConnection();
405 
407  std::string getRemoteEndpointAddressAsText() const;
408 
412  unsigned char* getInputBufData() {
413  if (input_buf_.empty()) {
414  isc_throw(InvalidOperation, "TcpConnection::getInputBufData() - cannot access empty buffer");
415  }
416 
417  return (input_buf_.data());
418  }
419 
421  size_t getInputBufSize() const {
422  return (input_buf_.size());
423  }
424 
427 
431 
434 
436  std::unique_ptr<asiolink::TCPSocket<SocketCallback> > tcp_socket_;
437 
439  std::unique_ptr<asiolink::TLSSocket<SocketCallback> > tls_socket_;
440 
443 
446 
449 
452 
454  size_t read_max_;
455 
458 
460  boost::asio::ip::tcp::endpoint remote_endpoint_;
461 };
462 
464 typedef boost::shared_ptr<TcpConnection> TcpConnectionPtr;
465 
466 } // end of namespace isc::tcp
467 } // end of namespace isc
468 
469 #endif
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if a function is called in a prohibited way.
Generic error reported within TcpConnection class.
TcpConnectionError(const char *file, size_t line, const char *what)
Pool of active TCP connections.
Accepts and handles a single TCP connection.
void doWrite(TcpResponsePtr response)
Starts asynchronous write to the socket.
virtual TcpRequestPtr createRequest()=0
Creates a new, empty request.
void shutdownCallback(const boost::system::error_code &ec)
Callback invoked when TLS shutdown is performed.
void acceptorCallback(const boost::system::error_code &ec)
Local callback invoked when new connection is accepted.
void asyncAccept()
Asynchronously accepts new connection.
static const boost::asio::ip::tcp::endpoint & NO_ENDPOINT()
Returns an empty end point.
size_t getInputBufSize() const
Returns input buffer size.
virtual void shutdown()
Shutdown the socket.
size_t getReadMax() const
Fetches the maximum number of bytes read during single socket read.
boost::asio::ip::tcp::endpoint remote_endpoint_
Remote endpoint.
virtual void requestReceived(TcpRequestPtr request)=0
Processes a request once it has been completely received.
virtual void shutdownConnection()
Shuts down current connection.
unsigned char * getInputBufData()
Returns pointer to the first byte of the input buffer.
virtual void stopThisConnection()
Stops current connection.
void setReadMax(const size_t read_max)
Sets the maximum number of bytes read during single socket read.
TcpConnectionAcceptorPtr acceptor_
Pointer to the TCP acceptor used to accept new connections.
virtual void close()
Closes the socket.
asiolink::TlsContextPtr tls_context_
TLS context.
WireData input_buf_
Buffer for a single socket read.
void socketReadCallback(TcpRequestPtr request, boost::system::error_code ec, size_t length)
Callback invoked when new data is received over the socket.
void setupIdleTimer()
Reset timer for detecting idle timeout in connections.
virtual void socketWriteCallback(TcpResponsePtr request, boost::system::error_code ec, size_t length)
Callback invoked when data is sent over the socket.
TcpConnection(asiolink::IOService &io_service, const TcpConnectionAcceptorPtr &acceptor, const asiolink::TlsContextPtr &tls_context, TcpConnectionPool &connection_pool, const TcpConnectionAcceptorCallback &acceptor_callback, const TcpConnectionFilterCallback &connection_filter, const long idle_timeout, const size_t read_max=32768)
Constructor.
void asyncSendResponse(TcpResponsePtr response)
Sends TCP response asynchronously.
std::string getRemoteEndpointAddressAsText() const
returns remote address in textual form
TcpConnectionFilterCallback connection_filter_
External callback for filtering connections by IP address.
const boost::asio::ip::tcp::endpoint getRemoteEndpoint() const
Fetches the remote endpoint for the connection's socket.
std::unique_ptr< asiolink::TCPSocket< SocketCallback > > tcp_socket_
TCP socket used by this connection.
void doRead(TcpRequestPtr request=TcpRequestPtr())
Starts asynchronous read from the socket.
virtual ~TcpConnection()
Destructor.
asiolink::IntervalTimer idle_timer_
Timer used to detect idle Timeout.
virtual bool responseSent(TcpResponsePtr response)=0
Determines behavior after a response has been sent.
TcpConnectionAcceptorCallback acceptor_callback_
External TCP acceptor callback.
size_t read_max_
Maximum bytes to read in a single socket read.
TcpConnectionPool & connection_pool_
Connection pool holding this connection.
void doHandshake()
Asynchronously performs TLS handshake.
TcpRequestPtr postData(TcpRequestPtr request, WireData &input_data)
Appends newly received raw data to the given request.
std::unique_ptr< asiolink::TLSSocket< SocketCallback > > tls_socket_
TLS socket used by this connection.
void handshakeCallback(const boost::system::error_code &ec)
Local callback invoked when TLS handshake is performed.
void idleTimeoutCallback()
Callback invoked when the client has been idle.
long idle_timeout_
Timeout after which the a TCP connection is shut down by the server.
Base class for TCP messages.
virtual ~TcpMessage()
Destructor.
WireData wire_data_
Buffer used for data in wire format data.
const uint8_t * getWireData() const
Returns pointer to the first byte of the wire data.
size_t getWireDataSize() const
Returns current size of the wire data.
Abstract class used to receive an inbound message.
virtual bool needData() const =0
Returns true if the request is incomplete.
virtual std::string logFormatRequest(const size_t limit=0) const =0
Returns request contents formatted for log output.
virtual void unpack()=0
Unpacks wire data once the message has been completely received.
virtual size_t postBuffer(const void *buf, const size_t nbytes)=0
Adds data to an incomplete request.
virtual ~TcpRequest()
Destructor.
Abstract class used to create and send an outbound response.
virtual ~TcpResponse()
Destructor.
virtual void consumeWireData(const size_t length)
Erases n bytes from the beginning of the wire data.
virtual void pack()=0
Prepares the wire data content for writing.
bool wireDataAvail() const
Checks if the output buffer contains some data to be sent.
TcpResponse()
Constructor.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
std::function< bool(const boost::asio::ip::tcp::endpoint &)> TcpConnectionFilterCallback
Type of the callback for filtering new connections by ip address.
boost::shared_ptr< TcpConnectionAcceptor > TcpConnectionAcceptorPtr
Type of shared pointer to TCP acceptors.
boost::shared_ptr< TcpRequest > TcpRequestPtr
Defines a smart pointer to a TcpRequest.
boost::shared_ptr< TcpConnection > TcpConnectionPtr
Pointer to the TcpConnection.
boost::shared_ptr< TcpResponse > TcpResponsePtr
std::vector< uint8_t > WireData
Defines a data structure for storing raw bytes of data on the wire.
boost::shared_ptr< WireData > WireDataPtr
std::function< void(const boost::system::error_code &)> TcpConnectionAcceptorCallback
Type of the callback for the TCP acceptor used in this library.
Defines the logger used by the top-level component of kea-lfc.