Commit ff9b70f3 authored by Dave Watson's avatar Dave Watson Committed by Pavlo Kushnir

Move SSL socket to folly

Summary: One of the last thrift -> folly moves.  The only change was the exception types - there are small wrapper classes in thrift/lib/cpp/async left to convert from AsyncSocketException to TTransportException.

Test Plan: run unit tests

Reviewed By: dcsommer@fb.com

Subscribers: jdperlow, trunkagent, doug, bmatheny, ssl-diffs@, njormrod, mshneer, folly-diffs@, fugalh, jsedgwick, andrewcox, alandau

FB internal diff: D1632425

Signature: t1:1632425:1414526483:339ae107bacb073bdd8cf0942fd0f6b70990feb4
parent a91ed7e3
......@@ -132,7 +132,9 @@ nobase_follyinclude_HEADERS = \
io/async/AsyncTimeout.h \
io/async/AsyncTransport.h \
io/async/AsyncServerSocket.h \
io/async/AsyncSSLServerSocket.h \
io/async/AsyncSocket.h \
io/async/AsyncSSLSocket.h \
io/async/AsyncSocketException.h \
io/async/DelayedDestruction.h \
io/async/EventBase.h \
......@@ -265,7 +267,9 @@ libfolly_la_SOURCES = \
io/ShutdownSocketSet.cpp \
io/async/AsyncTimeout.cpp \
io/async/AsyncServerSocket.cpp \
io/async/AsyncSSLServerSocket.cpp \
io/async/AsyncSocket.cpp \
io/async/AsyncSSLSocket.cpp \
io/async/EventBase.cpp \
io/async/EventBaseManager.cpp \
io/async/EventHandler.cpp \
......
/*
* Copyright 2014 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <folly/io/async/AsyncSSLServerSocket.h>
#include <folly/io/async/AsyncSSLSocket.h>
#include <folly/SocketAddress.h>
using std::shared_ptr;
namespace folly {
AsyncSSLServerSocket::AsyncSSLServerSocket(
const shared_ptr<SSLContext>& ctx,
EventBase* eventBase)
: eventBase_(eventBase)
, serverSocket_(new AsyncServerSocket(eventBase))
, ctx_(ctx)
, sslCallback_(nullptr) {
}
AsyncSSLServerSocket::~AsyncSSLServerSocket() {
}
void AsyncSSLServerSocket::destroy() {
// Stop accepting on the underlying socket as soon as destroy is called
if (sslCallback_ != nullptr) {
serverSocket_->pauseAccepting();
serverSocket_->removeAcceptCallback(this, nullptr);
}
serverSocket_->destroy();
serverSocket_ = nullptr;
sslCallback_ = nullptr;
DelayedDestruction::destroy();
}
void AsyncSSLServerSocket::setSSLAcceptCallback(SSLAcceptCallback* callback) {
SSLAcceptCallback *oldCallback = sslCallback_;
sslCallback_ = callback;
if (callback != nullptr && oldCallback == nullptr) {
serverSocket_->addAcceptCallback(this, nullptr);
serverSocket_->startAccepting();
} else if (callback == nullptr && oldCallback != nullptr) {
serverSocket_->removeAcceptCallback(this, nullptr);
serverSocket_->pauseAccepting();
}
}
void AsyncSSLServerSocket::attachEventBase(EventBase* eventBase) {
assert(sslCallback_ == nullptr);
eventBase_ = eventBase;
serverSocket_->attachEventBase(eventBase);
}
void AsyncSSLServerSocket::detachEventBase() {
serverSocket_->detachEventBase();
eventBase_ = nullptr;
}
void
AsyncSSLServerSocket::connectionAccepted(
int fd,
const folly::SocketAddress& clientAddr) noexcept {
shared_ptr<AsyncSSLSocket> sslSock;
try {
// Create a AsyncSSLSocket object with the fd. The socket should be
// added to the event base and in the state of accepting SSL connection.
sslSock = AsyncSSLSocket::newSocket(ctx_, eventBase_, fd);
} catch (const std::exception &e) {
LOG(ERROR) << "Exception %s caught while creating a AsyncSSLSocket "
"object with socket " << e.what() << fd;
::close(fd);
sslCallback_->acceptError(e);
return;
}
// TODO: Perform the SSL handshake before invoking the callback
sslCallback_->connectionAccepted(sslSock);
}
void AsyncSSLServerSocket::acceptError(const std::exception& ex)
noexcept {
LOG(ERROR) << "AsyncSSLServerSocket accept error: " << ex.what();
sslCallback_->acceptError(ex);
}
} // namespace
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#pragma once
#include <folly/io/async/SSLContext.h>
#include <folly/io/async/AsyncServerSocket.h>
namespace folly {
class SocketAddress;
class AsyncSSLSocket;
class AsyncSSLServerSocket : public DelayedDestruction,
private AsyncServerSocket::AcceptCallback {
public:
class SSLAcceptCallback {
public:
virtual ~SSLAcceptCallback() {}
/**
* connectionAccepted() is called whenever a new client connection is
* received.
*
* The SSLAcceptCallback will remain installed after connectionAccepted()
* returns.
*
* @param sock The newly accepted client socket. The
* SSLAcceptCallback
* assumes ownership of this socket, and is responsible
* for closing it when done.
*/
virtual void connectionAccepted(
const std::shared_ptr<AsyncSSLSocket> &sock)
noexcept = 0;
/**
* acceptError() is called if an error occurs while accepting.
*
* The SSLAcceptCallback will remain installed even after an accept error.
* If the callback wants to uninstall itself and stop trying to accept new
* connections, it must explicit call setAcceptCallback(nullptr).
*
* @param ex An exception representing the error.
*/
virtual void acceptError(const std::exception& ex) noexcept = 0;
};
/**
* Create a new TAsyncSSLServerSocket with the specified EventBase.
*
* @param eventBase The EventBase to use for driving the asynchronous I/O.
* If this parameter is nullptr, attachEventBase() must be
* called before this socket can begin accepting
* connections. All TAsyncSSLSocket objects accepted by
* this server socket will be attached to this EventBase
* when they are created.
*/
explicit AsyncSSLServerSocket(
const std::shared_ptr<folly::SSLContext>& ctx,
EventBase* eventBase = nullptr);
/**
* Destroy the socket.
*
* destroy() must be called to destroy the socket. The normal destructor is
* private, and should not be invoked directly. This prevents callers from
* deleting a TAsyncSSLServerSocket while it is invoking a callback.
*/
virtual void destroy();
virtual void bind(const folly::SocketAddress& address) {
serverSocket_->bind(address);
}
virtual void bind(uint16_t port) {
serverSocket_->bind(port);
}
void getAddress(folly::SocketAddress* addressReturn) {
serverSocket_->getAddress(addressReturn);
}
virtual void listen(int backlog) {
serverSocket_->listen(backlog);
}
/**
* Helper function to create a shared_ptr<TAsyncSSLServerSocket>.
*
* This passes in the correct destructor object, since TAsyncSSLServerSocket's
* destructor is protected and cannot be invoked directly.
*/
static std::shared_ptr<AsyncSSLServerSocket> newSocket(
const std::shared_ptr<folly::SSLContext>& ctx,
EventBase* evb) {
return std::shared_ptr<AsyncSSLServerSocket>(
new AsyncSSLServerSocket(ctx, evb),
Destructor());
}
/**
* Set the accept callback.
*
* This method may only be invoked from the EventBase's loop thread.
*
* @param callback The callback to invoke when a new socket
* connection is accepted and a new TAsyncSSLSocket is
* created.
*
* Throws TTransportException on error.
*/
void setSSLAcceptCallback(SSLAcceptCallback* callback);
SSLAcceptCallback *getSSLAcceptCallback() const {
return sslCallback_;
}
void attachEventBase(EventBase* eventBase);
void detachEventBase();
/**
* Returns the EventBase that the handler is currently attached to.
*/
EventBase* getEventBase() const {
return eventBase_;
}
protected:
/**
* Protected destructor.
*
* Invoke destroy() instead to destroy the TAsyncSSLServerSocket.
*/
virtual ~AsyncSSLServerSocket();
protected:
virtual void connectionAccepted(int fd,
const folly::SocketAddress& clientAddr)
noexcept;
virtual void acceptError(const std::exception& ex) noexcept;
EventBase* eventBase_;
AsyncServerSocket* serverSocket_;
// SSL context
std::shared_ptr<folly::SSLContext> ctx_;
// The accept callback
SSLAcceptCallback* sslCallback_;
};
} // namespace
This diff is collapsed.
This diff is collapsed.
......@@ -175,6 +175,14 @@ class AsyncSocket::WriteRequest {
struct iovec writeOps_[]; ///< write operation(s) list
};
AsyncSocket::AsyncSocket()
: eventBase_(nullptr)
, writeTimeout_(this, nullptr)
, ioHandler_(this, nullptr) {
VLOG(5) << "new AsyncSocket(" << ")";
init();
}
AsyncSocket::AsyncSocket(EventBase* evb)
: eventBase_(evb)
, writeTimeout_(this, evb)
......
......@@ -184,6 +184,7 @@ class AsyncSocket : virtual public AsyncTransport {
noexcept = 0;
};
explicit AsyncSocket();
/**
* Create a new unconnected AsyncSocket.
*
......@@ -549,6 +550,14 @@ class AsyncSocket : virtual public AsyncTransport {
return setsockopt(fd_, level, optname, optval, sizeof(T));
}
enum class StateEnum : uint8_t {
UNINIT,
CONNECTING,
ESTABLISHED,
CLOSED,
ERROR
};
protected:
enum ReadResultEnum {
READ_EOF = 0,
......@@ -565,14 +574,6 @@ class AsyncSocket : virtual public AsyncTransport {
*/
~AsyncSocket();
enum class StateEnum : uint8_t {
UNINIT,
CONNECTING,
ESTABLISHED,
CLOSED,
ERROR
};
friend std::ostream& operator << (std::ostream& os, const StateEnum& state);
enum ShutdownFlags {
......
......@@ -44,9 +44,11 @@ AsyncTimeout::AsyncTimeout(EventBase* eventBase)
event_set(&event_, -1, EV_TIMEOUT, &AsyncTimeout::libeventCallback, this);
event_.ev_base = nullptr;
timeoutManager_->attachTimeoutManager(
if (eventBase) {
timeoutManager_->attachTimeoutManager(
this,
TimeoutManager::InternalEnum::NORMAL);
}
RequestContext::getStaticContext();
}
......
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