Commit 104d728c authored by Brandon Schlinker's avatar Brandon Schlinker Committed by Facebook GitHub Bot

Construct from existing raw pointer

Summary:
This diff adds a constructor that takes an `AsyncSocket*`, so that lifecycle observers are informed via `move` when a socket is transformed.

If one `AsyncSocket` is constructed from another using the `AsyncSocket(AsyncSocket* oldAsyncSocket)` constructor, then `move(oldSocket, newSocket)` will be triggered for attached observers, allowing the observers to detach from the old socket and attach to the new socket. However, we currently transform between `AsyncSocket` by detaching the fd and event base, and passing them to the new constructor:

```
# from FizzAcceptorHandshakeHelper.cpp
auto evb = transport_->getEventBase();
auto fd = transport_->getUnderlyingTransport<folly::AsyncSocket>()
                ->detachNetworkSocket()
                .toFd();
transport_.reset();
sslSocket_ = createSSLSocket(sslContext_, evb, fd);
```

When this happens, any `AsyncSocket::LifecycleObserver` that were attached on accept to become separated from the fd/socket that they're attempting to follow. With this change, we can do the following instead (next diff):

```
 sslSocket_ = createSSLSocket(
      sslContext_, transport_->getUnderlyingTransport<folly::AsyncSocket>());
transport_.reset();
```

Because `createSSLSocket` uses the `AsyncSocket*` constructor, the `move` observer event will be triggered.

Differential Revision: D21614835

fbshipit-source-id: 6c995f879fe41935850247a28ff8af2b33349445
parent 5e4b2f87
...@@ -253,10 +253,10 @@ AsyncSSLSocket::AsyncSSLSocket( ...@@ -253,10 +253,10 @@ AsyncSSLSocket::AsyncSSLSocket(
AsyncSSLSocket::AsyncSSLSocket( AsyncSSLSocket::AsyncSSLSocket(
shared_ptr<SSLContext> ctx, shared_ptr<SSLContext> ctx,
AsyncSocket::UniquePtr oldAsyncSocket, AsyncSocket* oldAsyncSocket,
bool server, bool server,
bool deferSecurityNegotiation) bool deferSecurityNegotiation)
: AsyncSocket(std::move(oldAsyncSocket)), : AsyncSocket(oldAsyncSocket),
server_(server), server_(server),
ctx_(std::move(ctx)), ctx_(std::move(ctx)),
handshakeTimeout_(this, AsyncSocket::getEventBase()), handshakeTimeout_(this, AsyncSocket::getEventBase()),
...@@ -272,6 +272,17 @@ AsyncSSLSocket::AsyncSSLSocket( ...@@ -272,6 +272,17 @@ AsyncSSLSocket::AsyncSSLSocket(
} }
} }
AsyncSSLSocket::AsyncSSLSocket(
shared_ptr<SSLContext> ctx,
AsyncSocket::UniquePtr oldAsyncSocket,
bool server,
bool deferSecurityNegotiation)
: AsyncSSLSocket(
ctx,
oldAsyncSocket.get(),
server,
deferSecurityNegotiation) {}
#if FOLLY_OPENSSL_HAS_SNI #if FOLLY_OPENSSL_HAS_SNI
/** /**
* Create a client AsyncSSLSocket and allow tlsext_hostname * Create a client AsyncSSLSocket and allow tlsext_hostname
......
...@@ -228,6 +228,16 @@ class AsyncSSLSocket : public AsyncSocket { ...@@ -228,6 +228,16 @@ class AsyncSSLSocket : public AsyncSocket {
bool server = true, bool server = true,
bool deferSecurityNegotiation = false); bool deferSecurityNegotiation = false);
/**
* Create a server/client AsyncSSLSocket from an already connected
* AsyncSocket.
*/
AsyncSSLSocket(
std::shared_ptr<folly::SSLContext> ctx,
AsyncSocket* oldAsyncSocket,
bool server = true,
bool deferSecurityNegotiation = false);
/** /**
* Create a server/client AsyncSSLSocket from an already connected * Create a server/client AsyncSSLSocket from an already connected
* AsyncSocket. * AsyncSocket.
......
...@@ -344,7 +344,7 @@ AsyncSocket::AsyncSocket( ...@@ -344,7 +344,7 @@ AsyncSocket::AsyncSocket(
state_ = StateEnum::ESTABLISHED; state_ = StateEnum::ESTABLISHED;
} }
AsyncSocket::AsyncSocket(AsyncSocket::UniquePtr oldAsyncSocket) AsyncSocket::AsyncSocket(AsyncSocket* oldAsyncSocket)
: AsyncSocket( : AsyncSocket(
oldAsyncSocket->getEventBase(), oldAsyncSocket->getEventBase(),
oldAsyncSocket->detachNetworkSocket(), oldAsyncSocket->detachNetworkSocket(),
...@@ -357,11 +357,14 @@ AsyncSocket::AsyncSocket(AsyncSocket::UniquePtr oldAsyncSocket) ...@@ -357,11 +357,14 @@ AsyncSocket::AsyncSocket(AsyncSocket::UniquePtr oldAsyncSocket)
for (const auto& cb : oldAsyncSocket->lifecycleObservers_) { for (const auto& cb : oldAsyncSocket->lifecycleObservers_) {
// only available for observers derived from AsyncSocket::LifecycleObserver // only available for observers derived from AsyncSocket::LifecycleObserver
if (auto dCb = dynamic_cast<AsyncSocket::LifecycleObserver*>(cb)) { if (auto dCb = dynamic_cast<AsyncSocket::LifecycleObserver*>(cb)) {
dCb->move(oldAsyncSocket.get(), this); dCb->move(oldAsyncSocket, this);
} }
} }
} }
AsyncSocket::AsyncSocket(AsyncSocket::UniquePtr oldAsyncSocket)
: AsyncSocket(oldAsyncSocket.get()) {}
// init() method, since constructor forwarding isn't supported in most // init() method, since constructor forwarding isn't supported in most
// compilers yet. // compilers yet.
void AsyncSocket::init() { void AsyncSocket::init() {
......
...@@ -288,6 +288,15 @@ class AsyncSocket : public AsyncTransport { ...@@ -288,6 +288,15 @@ class AsyncSocket : public AsyncTransport {
*/ */
explicit AsyncSocket(AsyncSocket::UniquePtr); explicit AsyncSocket(AsyncSocket::UniquePtr);
/**
* Create an AsyncSocket from a different, already connected AsyncSocket.
*
* Similar to AsyncSocket(evb, fd) when fd was previously owned by an
* AsyncSocket. Caller must call destroy on old AsyncSocket unless it is
* in a smart pointer with appropriate destructor.
*/
explicit AsyncSocket(AsyncSocket*);
/** /**
* Helper function to create an AsyncSocket.. * Helper function to create an AsyncSocket..
* *
......
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