Commit 23e1c2d3 authored by Maxim Georgiev's avatar Maxim Georgiev Committed by facebook-github-bot-1

Add mechanizm for caching local and peer addresses in AsyncSSLSocket.

Summary: This change adds a flag to AsyncSSLSocket which forces the socket to cache local and remote addresses right after TCP connection is established. Cached address values will be available after the connection is closed. Caching addresses can be halpful in SSL handshake failure investigations.

Reviewed By: yfeldblum

Differential Revision: D2863274

fb-gh-sync-id: d7b415292988c2fb187a80422e8ccbf8ba8ab0e3
parent 13f7a671
...@@ -501,6 +501,13 @@ void AsyncSSLSocket::sslAccept(HandshakeCB* callback, uint32_t timeout, ...@@ -501,6 +501,13 @@ void AsyncSSLSocket::sslAccept(HandshakeCB* callback, uint32_t timeout,
handshakeCallback_ != nullptr) { handshakeCallback_ != nullptr) {
return invalidState(callback); return invalidState(callback);
} }
// Cache local and remote socket addresses to keep them available
// after socket file descriptor is closed.
if (cacheAddrOnFailure_ && -1 != getFd()) {
cacheLocalPeerAddr();
}
handshakeStartTime_ = std::chrono::steady_clock::now(); handshakeStartTime_ = std::chrono::steady_clock::now();
// Make end time at least >= start time. // Make end time at least >= start time.
handshakeEndTime_ = handshakeStartTime_; handshakeEndTime_ = handshakeStartTime_;
...@@ -665,6 +672,19 @@ void AsyncSSLSocket::invokeHandshakeCB() { ...@@ -665,6 +672,19 @@ void AsyncSSLSocket::invokeHandshakeCB() {
} }
} }
void AsyncSSLSocket::cacheLocalPeerAddr() {
SocketAddress address;
try {
getLocalAddress(&address);
getPeerAddress(&address);
} catch (const std::system_error& e) {
// The handle can be still valid while the connection is already closed.
if (e.code() != std::error_code(ENOTCONN, std::system_category())) {
throw;
}
}
}
void AsyncSSLSocket::connect(ConnectCallback* callback, void AsyncSSLSocket::connect(ConnectCallback* callback,
const folly::SocketAddress& address, const folly::SocketAddress& address,
int timeout, int timeout,
...@@ -700,6 +720,12 @@ void AsyncSSLSocket::sslConn(HandshakeCB* callback, uint64_t timeout, ...@@ -700,6 +720,12 @@ void AsyncSSLSocket::sslConn(HandshakeCB* callback, uint64_t timeout,
DestructorGuard dg(this); DestructorGuard dg(this);
assert(eventBase_->isInEventBaseThread()); assert(eventBase_->isInEventBaseThread());
// Cache local and remote socket addresses to keep them available
// after socket file descriptor is closed.
if (cacheAddrOnFailure_ && -1 != getFd()) {
cacheLocalPeerAddr();
}
verifyPeer_ = verifyPeer; verifyPeer_ = verifyPeer;
// Make sure we're in the uninitialized state // Make sure we're in the uninitialized state
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include <iomanip> #include <iomanip>
#include <openssl/ssl.h>
#include <folly/Optional.h> #include <folly/Optional.h>
#include <folly/String.h> #include <folly/String.h>
...@@ -749,6 +748,15 @@ class AsyncSSLSocket : public virtual AsyncSocket { ...@@ -749,6 +748,15 @@ class AsyncSSLSocket : public virtual AsyncSocket {
return X509_UniquePtr(cert); return X509_UniquePtr(cert);
} }
/**
* Force AsyncSSLSocket object to cache local and peer socket addresses.
* If called with "true" before connect() this function forces full local
* and remote socket addresses to be cached in the socket object and available
* through getLocalAddress()/getPeerAddress() methods even after the socket is
* closed.
*/
void forceCacheAddrOnFailure(bool force) { cacheAddrOnFailure_ = force; }
private: private:
void init(); void init();
...@@ -821,6 +829,8 @@ class AsyncSSLSocket : public virtual AsyncSocket { ...@@ -821,6 +829,8 @@ class AsyncSSLSocket : public virtual AsyncSocket {
void invokeHandshakeErr(const AsyncSocketException& ex); void invokeHandshakeErr(const AsyncSocketException& ex);
void invokeHandshakeCB(); void invokeHandshakeCB();
void cacheLocalPeerAddr();
static void sslInfoCallback(const SSL *ssl, int type, int val); static void sslInfoCallback(const SSL *ssl, int type, int val);
// SSL related members. // SSL related members.
...@@ -863,6 +873,7 @@ class AsyncSSLSocket : public virtual AsyncSocket { ...@@ -863,6 +873,7 @@ class AsyncSSLSocket : public virtual AsyncSocket {
static int sslVerifyCallback(int preverifyOk, X509_STORE_CTX* ctx); static int sslVerifyCallback(int preverifyOk, X509_STORE_CTX* ctx);
bool parseClientHello_{false}; bool parseClientHello_{false};
bool cacheAddrOnFailure_{false};
std::unique_ptr<ClientHelloInfo> clientHelloInfo_; std::unique_ptr<ClientHelloInfo> clientHelloInfo_;
// Time taken to complete the ssl handshake. // Time taken to complete the ssl handshake.
......
...@@ -1066,7 +1066,10 @@ bool AsyncSocket::isDetachable() const { ...@@ -1066,7 +1066,10 @@ bool AsyncSocket::isDetachable() const {
} }
void AsyncSocket::getLocalAddress(folly::SocketAddress* address) const { void AsyncSocket::getLocalAddress(folly::SocketAddress* address) const {
address->setFromLocalAddress(fd_); if (!localAddr_.isInitialized()) {
localAddr_.setFromLocalAddress(fd_);
}
*address = localAddr_;
} }
void AsyncSocket::getPeerAddress(folly::SocketAddress* address) const { void AsyncSocket::getPeerAddress(folly::SocketAddress* address) const {
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <glog/logging.h>
#include <folly/SocketAddress.h> #include <folly/SocketAddress.h>
#include <folly/io/ShutdownSocketSet.h> #include <folly/io/ShutdownSocketSet.h>
#include <folly/io/IOBuf.h> #include <folly/io/IOBuf.h>
...@@ -786,11 +785,12 @@ class AsyncSocket : virtual public AsyncTransportWrapper { ...@@ -786,11 +785,12 @@ class AsyncSocket : virtual public AsyncTransportWrapper {
uint8_t shutdownFlags_; ///< Shutdown state (ShutdownFlags) uint8_t shutdownFlags_; ///< Shutdown state (ShutdownFlags)
uint16_t eventFlags_; ///< EventBase::HandlerFlags settings uint16_t eventFlags_; ///< EventBase::HandlerFlags settings
int fd_; ///< The socket file descriptor int fd_; ///< The socket file descriptor
mutable mutable folly::SocketAddress addr_; ///< The address we tried to connect to
folly::SocketAddress addr_; ///< The address we tried to connect to mutable folly::SocketAddress localAddr_;
///< The address we are connecting from
uint32_t sendTimeout_; ///< The send timeout, in milliseconds uint32_t sendTimeout_; ///< The send timeout, in milliseconds
uint16_t maxReadsPerEvent_; ///< Max reads per event loop iteration uint16_t maxReadsPerEvent_; ///< Max reads per event loop iteration
EventBase* eventBase_; ///< The EventBase EventBase* eventBase_; ///< The EventBase
WriteTimeout writeTimeout_; ///< A timeout for connect and write WriteTimeout writeTimeout_; ///< A timeout for connect and write
IoHandler ioHandler_; ///< A EventHandler to monitor the fd IoHandler ioHandler_; ///< A EventHandler to monitor the fd
ImmediateReadCB immediateReadHandler_; ///< LoopCallback for checking read ImmediateReadCB immediateReadHandler_; ///< LoopCallback for checking read
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment