Move SSL socket to folly
[folly.git] / folly / io / async / AsyncSSLServerSocket.cpp
1 /*
2  * Copyright 2014 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  */
16
17 #include <folly/io/async/AsyncSSLServerSocket.h>
18
19 #include <folly/io/async/AsyncSSLSocket.h>
20 #include <folly/SocketAddress.h>
21
22 using std::shared_ptr;
23
24 namespace folly {
25
26 AsyncSSLServerSocket::AsyncSSLServerSocket(
27       const shared_ptr<SSLContext>& ctx,
28       EventBase* eventBase)
29     : eventBase_(eventBase)
30     , serverSocket_(new AsyncServerSocket(eventBase))
31     , ctx_(ctx)
32     , sslCallback_(nullptr) {
33 }
34
35 AsyncSSLServerSocket::~AsyncSSLServerSocket() {
36 }
37
38 void AsyncSSLServerSocket::destroy() {
39   // Stop accepting on the underlying socket as soon as destroy is called
40   if (sslCallback_ != nullptr) {
41     serverSocket_->pauseAccepting();
42     serverSocket_->removeAcceptCallback(this, nullptr);
43   }
44   serverSocket_->destroy();
45   serverSocket_ = nullptr;
46   sslCallback_ = nullptr;
47
48   DelayedDestruction::destroy();
49 }
50
51 void AsyncSSLServerSocket::setSSLAcceptCallback(SSLAcceptCallback* callback) {
52   SSLAcceptCallback *oldCallback = sslCallback_;
53   sslCallback_ = callback;
54   if (callback != nullptr && oldCallback == nullptr) {
55     serverSocket_->addAcceptCallback(this, nullptr);
56     serverSocket_->startAccepting();
57   } else if (callback == nullptr && oldCallback != nullptr) {
58     serverSocket_->removeAcceptCallback(this, nullptr);
59     serverSocket_->pauseAccepting();
60   }
61 }
62
63 void AsyncSSLServerSocket::attachEventBase(EventBase* eventBase) {
64   assert(sslCallback_ == nullptr);
65   eventBase_ = eventBase;
66   serverSocket_->attachEventBase(eventBase);
67 }
68
69 void AsyncSSLServerSocket::detachEventBase() {
70   serverSocket_->detachEventBase();
71   eventBase_ = nullptr;
72 }
73
74 void
75 AsyncSSLServerSocket::connectionAccepted(
76   int fd,
77   const folly::SocketAddress& clientAddr) noexcept {
78   shared_ptr<AsyncSSLSocket> sslSock;
79   try {
80     // Create a AsyncSSLSocket object with the fd. The socket should be
81     // added to the event base and in the state of accepting SSL connection.
82     sslSock = AsyncSSLSocket::newSocket(ctx_, eventBase_, fd);
83   } catch (const std::exception &e) {
84     LOG(ERROR) << "Exception %s caught while creating a AsyncSSLSocket "
85       "object with socket " << e.what() << fd;
86     ::close(fd);
87     sslCallback_->acceptError(e);
88     return;
89   }
90
91   // TODO: Perform the SSL handshake before invoking the callback
92   sslCallback_->connectionAccepted(sslSock);
93 }
94
95 void AsyncSSLServerSocket::acceptError(const std::exception& ex)
96   noexcept {
97   LOG(ERROR) << "AsyncSSLServerSocket accept error: " << ex.what();
98   sslCallback_->acceptError(ex);
99 }
100
101 } // namespace