proxygen
EvbHandshakeHelper.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
17 
18 namespace wangle {
19 
23  auto transition =
24  tryTransition(HandshakeState::Invalid, HandshakeState::Started);
25  if (!transition.first) {
26  VLOG(5) << "Ignoring call to start(), since state is currently "
27  << static_cast<unsigned>(transition.second);
28  }
29 
30  callback_ = callback;
31  originalEvb_ = sock->getEventBase();
32  CHECK(originalEvb_);
33 
34  sock->detachEventBase();
35  handshakeEvb_->runInEventBaseThread(
36  [ this, sock = std::move(sock) ]() mutable {
37  sock->attachEventBase(handshakeEvb_);
38  helper_->start(std::move(sock), this);
39  });
40 }
41 
43  CHECK(originalEvb_);
45 
46  auto transition =
48 
49  // Regardless of whether or not we win the race or not, we will set
50  // dropConnectionGuard_ (see case 2) to let a potential C' know that the
51  // connection was dropped. C', seeing this, is responsible for clearing
52  // the dropConnectionGuard.
55  nullptr,
56  folly::make_exception_wrapper<std::runtime_error>("connection dropped"),
57  reason);
58 
59  if (transition.first) {
60  // If we win the race to update the state, though, we are responsible
61  // for ensuring that dropConnection() is called on the handshake thread,
62  // and we are also the one responsible for clearing the dropConnectionGuard_
63  // that we set earlier.
64  handshakeEvb_->runInEventBaseThread([this, reason] {
65  VLOG(5) << "callback has not been received. dropConnection "
66  << "calling underlying helper";
67 
68  helper_->dropConnection(reason);
69 
70  // We need to ensure that the transport is destroyed in the handshake
71  // thread since the transport is currently attached to the handshake's
72  // event base.
73  helper_.reset();
74 
76  [this] { dropConnectionGuard_.clear(); });
77  });
78  }
79 }
80 
83  std::string nextProtocol,
84  SecureTransportType secureTransportType,
86  DCHECK_EQ(transport->getEventBase(), handshakeEvb_);
87 
88  auto transition =
90  if (!transition.first) {
91  VLOG(5) << "Ignoring call to connectionReady(), expected state to be "
92  << static_cast<unsigned>(HandshakeState::Started)
93  << " but actual state was "
94  << static_cast<unsigned>(transition.second);
95  return;
96  }
97 
98  transport->detachEventBase();
99 
101  this,
102  secureTransportType,
103  sslErr,
104  transport = std::move(transport),
105  nextProtocol = std::move(nextProtocol)
106  ]() mutable {
107  DCHECK(callback_);
108  VLOG(5) << "calling underlying callback connectionReady";
109  transport->attachEventBase(originalEvb_);
110 
111  // If a dropConnection call occured by the time this lambda runs, we don't
112  // want to fire the callback. (See Case 2)
115  return;
116  }
117 
119  std::move(transport),
120  std::move(nextProtocol),
121  secureTransportType,
122  sslErr);
123  });
124 }
125 
127  folly::AsyncTransportWrapper* transport,
130  DCHECK(transport->getEventBase() == handshakeEvb_);
131 
132  auto transition =
134  if (!transition.first) {
135  VLOG(5) << "Ignoring call to connectionError(), expected state to be "
136  << static_cast<unsigned>(HandshakeState::Started)
137  << " but actual state was "
138  << static_cast<unsigned>(transition.second);
139  return;
140  }
141 
142  helper_.reset();
144  [this, sslErr, ex = std::move(ex)]() mutable {
145  DCHECK(callback_);
146  VLOG(5) << "calling underlying callback connectionError";
147 
148  // If a dropConnection call occured by the time this lambda runs, we
149  // don't want to fire the callback. (See Case 2)
152  return;
153  }
154  callback_->connectionError(nullptr, std::move(ex), sslErr);
155  });
156 }
157 
158 std::pair<bool, EvbHandshakeHelper::HandshakeState>
160  HandshakeState expected,
162  bool res = state_.compare_exchange_strong(expected, next);
163  return std::make_pair(res, expected);
164 }
165 
167  VLOG(5) << "evbhandshakehelper is destroyed";
168 }
169 }
virtual void connectionError(folly::AsyncTransportWrapper *transport, folly::exception_wrapper ex, folly::Optional< SSLErrorEnum > sslErr) noexceptoverride
SSLErrorEnum
Definition: SSLUtil.h:42
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
void start(folly::AsyncSSLSocket::UniquePtr sock, AcceptorHandshakeHelper::Callback *callback) noexceptoverride
requires E e noexcept(noexcept(s.error(std::move(e))))
AcceptorHandshakeHelper::Callback * callback_
folly::EventBase * originalEvb_
std::unique_ptr< AsyncSSLSocket, Destructor > UniquePtr
std::unique_ptr< AsyncTransportWrapper, Destructor > UniquePtr
virtual void connectionReady(folly::AsyncTransportWrapper::UniquePtr transport, std::string nextProtocol, SecureTransportType secureTransportType, folly::Optional< SSLErrorEnum > sslErr) noexcept=0
void dropConnection(SSLErrorEnum reason=SSLErrorEnum::NO_ERROR) override
FOLLY_CPP14_CONSTEXPR bool hasValue() const noexcept
Definition: Optional.h:300
bool runInEventBaseThread(void(*fn)(T *), T *arg)
Definition: EventBase.h:794
std::pair< bool, HandshakeState > tryTransition(HandshakeState expected, HandshakeState next)
folly::EventBase * handshakeEvb_
virtual void connectionError(folly::AsyncTransportWrapper *transport, folly::exception_wrapper ex, folly::Optional< SSLErrorEnum > sslErr) noexcept=0
Value & emplace(Args &&...args)
Definition: Optional.h:231
void dcheckIsInEventBaseThread() const
Definition: EventBase.h:520
AcceptorHandshakeHelper::UniquePtr helper_
virtual void connectionReady(folly::AsyncTransportWrapper::UniquePtr transport, std::string nextProtocol, SecureTransportType secureTransportType, folly::Optional< SSLErrorEnum > sslErr) noexceptoverride
const char * string
Definition: Conv.cpp:212
folly::Function< void()> callback_
std::atomic< HandshakeState > state_
folly::Optional< folly::DelayedDestruction::DestructorGuard > dropConnectionGuard_
def next(obj)
Definition: ast.py:58
void clear() noexcept
Definition: Optional.h:251