handshakeCallback_ != nullptr) {
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();
// Make end time at least >= start time.
handshakeEndTime_ = handshakeStartTime_;
}
}
+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,
const folly::SocketAddress& address,
int timeout,
DestructorGuard dg(this);
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;
// Make sure we're in the uninitialized state
#include <arpa/inet.h>
#include <iomanip>
-#include <openssl/ssl.h>
#include <folly/Optional.h>
#include <folly/String.h>
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:
void init();
void invokeHandshakeErr(const AsyncSocketException& ex);
void invokeHandshakeCB();
+ void cacheLocalPeerAddr();
+
static void sslInfoCallback(const SSL *ssl, int type, int val);
// SSL related members.
static int sslVerifyCallback(int preverifyOk, X509_STORE_CTX* ctx);
bool parseClientHello_{false};
+ bool cacheAddrOnFailure_{false};
std::unique_ptr<ClientHelloInfo> clientHelloInfo_;
// Time taken to complete the ssl handshake.
}
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 {
#include <sys/types.h>
#include <sys/socket.h>
-#include <glog/logging.h>
#include <folly/SocketAddress.h>
#include <folly/io/ShutdownSocketSet.h>
#include <folly/io/IOBuf.h>
uint8_t shutdownFlags_; ///< Shutdown state (ShutdownFlags)
uint16_t eventFlags_; ///< EventBase::HandlerFlags settings
int fd_; ///< The socket file descriptor
- mutable
- folly::SocketAddress addr_; ///< The address we tried to connect to
+ mutable 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
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
IoHandler ioHandler_; ///< A EventHandler to monitor the fd
ImmediateReadCB immediateReadHandler_; ///< LoopCallback for checking read