summaryrefslogtreecommitdiffstats
path: root/src/lib/asiolink/tcp_socket.h
diff options
context:
space:
mode:
authorMarcin Siodelski <marcin@isc.org>2018-01-05 21:43:49 +0100
committerMarcin Siodelski <marcin@isc.org>2018-01-05 21:43:49 +0100
commit95923b6c408da923e4556a18b32660ac51539711 (patch)
tree6b0662978d0c21f8b367f17382c01b5c105451da /src/lib/asiolink/tcp_socket.h
parent[5451] Implemented HTTP response parser. (diff)
downloadkea-95923b6c408da923e4556a18b32660ac51539711.tar.xz
kea-95923b6c408da923e4556a18b32660ac51539711.zip
[5451] Implemented HTTP client.
Diffstat (limited to 'src/lib/asiolink/tcp_socket.h')
-rw-r--r--src/lib/asiolink/tcp_socket.h49
1 files changed, 47 insertions, 2 deletions
diff --git a/src/lib/asiolink/tcp_socket.h b/src/lib/asiolink/tcp_socket.h
index adf74d1f0f..8465c0705e 100644
--- a/src/lib/asiolink/tcp_socket.h
+++ b/src/lib/asiolink/tcp_socket.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -90,6 +90,47 @@ public:
return (false);
}
+ /// \brief Checks if the connection is usable.
+ ///
+ /// The connection is usable if the peer has closed it.
+ ///
+ /// \return true if the connection is usable.
+ bool isUsable() const {
+ // If the socket is open it doesn't mean that it is still usable. The connection
+ // could have been closed on the other end. We have to check if we can still
+ // use this socket.
+ if (socket_.is_open()) {
+ // Remember the current non blocking setting.
+ const bool non_blocking_orig = socket_.non_blocking();
+ // Set the socket to non blocking mode. We're going to test if the socket
+ // returns would_block status on the attempt to read from it.
+ socket_.non_blocking(true);
+
+ boost::system::error_code ec;
+ char data[2];
+
+ // Use receive with message peek flag to avoid removing the data awaiting
+ // to be read.
+ socket_.receive(boost::asio::buffer(data, sizeof(data)),
+ boost::asio::socket_base::message_peek,
+ ec);
+
+ // Revert the original non_blocking flag on the socket.
+ socket_.non_blocking(non_blocking_orig);
+
+ // If the connection is alive we'd typically get would_block status code.
+ // If there are any data that haven't been read we may also get success
+ // status. We're guessing that try_again may also be returned by some
+ // implementations in some situations. Any other error code indicates a
+ // problem with the connection so we assume that the connection has been
+ // closed.
+ return (!ec || (ec.value() == boost::asio::error::try_again) ||
+ (ec.value() == boost::asio::error::would_block));
+ }
+
+ return (false);
+ }
+
/// \brief Open Socket
///
/// Opens the TCP socket. This is an asynchronous operation, completion of
@@ -227,7 +268,11 @@ TCPSocket<C>::~TCPSocket()
template <typename C> void
TCPSocket<C>::open(const IOEndpoint* endpoint, C& callback) {
-
+ // If socket is open on this end but has been closed by the peer,
+ // we need to reconnect.
+ if (socket_.is_open() && !isUsable()) {
+ close();
+ }
// Ignore opens on already-open socket. Don't throw a failure because
// of uncertainties as to what precedes whan when using asynchronous I/O.
// At also allows us a treat a passed-in socket as a self-managed socket.