Kea 3.3.3
tcp_connection.h
Go to the documentation of this file.
1// Copyright (C) 2022-2026 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
12#include <asiolink/io_service.h>
14#include <tcp/wire_data.h>
15
16#include <boost/enable_shared_from_this.hpp>
17#include <boost/system/error_code.hpp>
18#include <boost/shared_ptr.hpp>
19
20#include <array>
21#include <functional>
22#include <string>
23#include <iostream>
24
25#include <mutex>
26
27namespace isc {
28namespace tcp {
29
32public:
34 virtual ~TcpMessage() = default;
35
37 virtual const uint8_t* getWireData() const = 0;
38
40 virtual size_t getWireDataSize() const = 0;
41
42protected:
48 const uint8_t* getWireData(size_t position) const {
49 if (position >= wire_data_.size()) {
50 isc_throw(InvalidOperation, "position " << position
51 << " is not less than size " << wire_data_.size());
52 }
53
54 return (&wire_data_[position]);
55 }
56
62 size_t getWireDataSize(size_t position) const {
63 if (position > wire_data_.size()) {
64 isc_throw(InvalidOperation, "position " << position
65 << " is not less than size " << wire_data_.size());
66 }
67 return (wire_data_.size() - position);
68 }
69
72
74 size_t position_;
75};
76
78class TcpRequest : public TcpMessage {
79public:
81 virtual ~TcpRequest(){};
82
84 virtual const uint8_t* getWireData() const {
85 return (TcpMessage::getWireData(0));
86 }
87
89 virtual size_t getWireDataSize() const {
91 }
92
98 virtual size_t postBuffer(const void* buf, const size_t nbytes) = 0;
99
103 virtual bool needData() const = 0;
104
110 virtual std::string logFormatRequest(const size_t limit = 0) const = 0;
111
113 virtual void unpack() = 0;
114
115private:
116
122 std::string logFormatRequestSafe(const size_t limit = 0) const;
123};
124
126typedef boost::shared_ptr<TcpRequest> TcpRequestPtr;
127
129class TcpResponse : public TcpMessage {
130public:
132 TcpResponse() : send_in_progress_(false), position_(0) {}
133
135 virtual ~TcpResponse() {}
136
138 virtual const uint8_t* getWireData() const {
139 return (TcpMessage::getWireData(position_));
140 }
141
143 virtual size_t getWireDataSize() const {
144 return (TcpMessage::getWireDataSize(position_));
145 }
146
152 bool wireDataAvail() const {
153 return (position_ < wire_data_.size());
154 }
155
157 virtual void pack() = 0;
158
162 virtual void consumeWireData(const size_t length) {
163 send_in_progress_ = true;
164 if (length > wire_data_.size() - position_) {
165 position_ = wire_data_.size();
166 } else {
167 position_ += length;
168 }
169 }
170
172 return (send_in_progress_);
173 }
174
175private:
177 bool send_in_progress_;
178
180 size_t position_;
181};
182
183typedef boost::shared_ptr<TcpResponse> TcpResponsePtr;
184
187public:
188 TcpConnectionError(const char* file, size_t line, const char* what) :
189 isc::Exception(file, line, what) { }
190};
191
196class TcpConnectionPool;
197
199typedef std::function<bool(const boost::asio::ip::tcp::endpoint&)> TcpConnectionFilterCallback;
200
202class TcpConnection : public boost::enable_shared_from_this<TcpConnection> {
203private:
204
207 typedef std::function<void(boost::system::error_code ec, size_t length)>
208 SocketCallbackFunction;
209
213 class SocketCallback {
214 public:
215
220 SocketCallback(SocketCallbackFunction socket_callback)
221 : callback_(socket_callback) {
222 }
223
233 void operator()(boost::system::error_code ec, size_t length = 0);
234
235 private:
237 SocketCallbackFunction callback_;
238 };
239
240public:
241
256 TcpConnection(const asiolink::IOServicePtr& io_service,
257 const TcpConnectionAcceptorPtr& acceptor,
258 const asiolink::TlsContextPtr& tls_context,
259 TcpConnectionPool& connection_pool,
260 const TcpConnectionAcceptorCallback& acceptor_callback,
261 const TcpConnectionFilterCallback& connection_filter,
262 const long idle_timeout,
263 const size_t read_max = 32768);
264
268 virtual ~TcpConnection();
269
274 void asyncAccept();
275
277 virtual void shutdown();
278
280 virtual void close();
281
286 void doHandshake();
287
300 void doRead(TcpRequestPtr request = TcpRequestPtr());
301
315 TcpRequestPtr postData(TcpRequestPtr request, WireData& input_data);
316
321 virtual void requestReceived(TcpRequestPtr request) = 0;
322
331
335 size_t getReadMax() const {
336 return (read_max_);
337 }
338
343 void setReadMax(const size_t read_max);
344
349 virtual bool responseSent(TcpResponsePtr response) = 0;
350
354 static const boost::asio::ip::tcp::endpoint& NO_ENDPOINT() {
355 static boost::asio::ip::tcp::endpoint endpoint;
356 return (endpoint);
357 }
358
363 const boost::asio::ip::tcp::endpoint getRemoteEndpoint() const {
364 return (remote_endpoint_);
365 }
366
367protected:
368
377 void doWrite(TcpResponsePtr response);
378
384 void asyncSendResponse(TcpResponsePtr response);
385
394 void acceptorCallback(const boost::system::error_code& ec);
395
402 void handshakeCallback(const boost::system::error_code& ec);
403
415 boost::system::error_code ec,
416 size_t length);
417
424 virtual void socketWriteCallback(TcpResponsePtr request,
425 boost::system::error_code ec,
426 size_t length);
427
435 void shutdownCallback(const boost::system::error_code& ec);
436
438 void setupIdleTimer();
439
441 void idleTimeoutCallback();
442
446 virtual void shutdownConnection();
447
449 virtual void stopThisConnection();
450
452 std::string getRemoteEndpointAddressAsText() const;
453
457 unsigned char* getInputBufData() {
458 if (input_buf_.empty()) {
459 isc_throw(InvalidOperation, "TcpConnection::getInputBufData() - cannot access empty buffer");
460 }
461
462 return (input_buf_.data());
463 }
464
466 size_t getInputBufSize() const {
467 return (input_buf_.size());
468 }
469
472
475
479
482
484 std::unique_ptr<asiolink::TCPSocket<SocketCallback> > tcp_socket_;
485
487 std::unique_ptr<asiolink::TLSSocket<SocketCallback> > tls_socket_;
488
491
494
497
500
502 size_t read_max_;
503
506
508 boost::asio::ip::tcp::endpoint remote_endpoint_;
509};
510
512typedef boost::shared_ptr<TcpConnection> TcpConnectionPtr;
513
514} // end of namespace isc::tcp
515} // end of namespace isc
516
517#endif
Exception(const char *file, size_t line, const char *what)
Constructor for a given type for exceptions with file name and file line number.
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.
TcpConnectionError(const char *file, size_t line, const char *what)
Pool of active TCP connections.
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.
unsigned char * getInputBufData()
Returns pointer to the first byte of the input buffer.
void acceptorCallback(const boost::system::error_code &ec)
Local callback invoked when new connection is accepted.
void asyncAccept()
Asynchronously accepts new connection.
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.
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.
void asyncSendResponse(TcpResponsePtr response)
Sends TCP response asynchronously.
asiolink::IOServicePtr io_service_
The IO service used to handle events.
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.
static const boost::asio::ip::tcp::endpoint & NO_ENDPOINT()
Returns an empty end point.
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.
TcpConnection(const asiolink::IOServicePtr &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.
long idle_timeout_
Timeout after which the a TCP connection is shut down by the server.
Base class for TCP messages.
size_t getWireDataSize(size_t position) const
Returns current size of the wire data.
size_t position_
Position in the data.
WireData wire_data_
Buffer used for data in wire format data.
virtual ~TcpMessage()=default
Destructor.
virtual size_t getWireDataSize() const =0
Returns current size of the wire data.
virtual const uint8_t * getWireData() const =0
Returns pointer to the first byte of the wire data.
const uint8_t * getWireData(size_t position) const
Returns pointer to current byte of the wire data.
Abstract class used to receive an inbound message.
virtual const uint8_t * getWireData() const
Returns pointer to the first byte of the wire data.
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 size_t getWireDataSize() const
Returns current size of the wire data.
virtual ~TcpRequest()
Destructor.
virtual ~TcpResponse()
Destructor.
virtual void consumeWireData(const size_t length)
Erases n bytes from the beginning of the wire data.
virtual size_t getWireDataSize() const
Returns current size of the wire data.
virtual const uint8_t * getWireData() const
Returns pointer to the first byte 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.
Definition wire_data.h:17
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.