5f4818ee973c69a0c9bc53c0376186f8ad755386
[folly.git] / folly / io / async / test / AsyncSSLSocketTest2.cpp
1 /*
2  * Copyright 2015 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 #include <folly/io/async/test/AsyncSSLSocketTest.h>
17
18 #include <gtest/gtest.h>
19 #include <pthread.h>
20
21 #include <folly/io/async/AsyncSSLSocket.h>
22 #include <folly/io/async/EventBase.h>
23
24 using std::string;
25 using std::vector;
26 using std::min;
27 using std::cerr;
28 using std::endl;
29 using std::list;
30
31 namespace folly {
32
33 class AttachDetachClient : public AsyncSocket::ConnectCallback,
34                            public AsyncTransportWrapper::WriteCallback,
35                            public AsyncTransportWrapper::ReadCallback {
36  private:
37   EventBase *eventBase_;
38   std::shared_ptr<AsyncSSLSocket> sslSocket_;
39   std::shared_ptr<SSLContext> ctx_;
40   folly::SocketAddress address_;
41   char buf_[128];
42   char readbuf_[128];
43   uint32_t bytesRead_;
44  public:
45   AttachDetachClient(EventBase *eventBase, const folly::SocketAddress& address)
46       : eventBase_(eventBase), address_(address), bytesRead_(0) {
47     ctx_.reset(new SSLContext());
48     ctx_->setOptions(SSL_OP_NO_TICKET);
49     ctx_->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
50   }
51
52   void connect() {
53     sslSocket_ = AsyncSSLSocket::newSocket(ctx_, eventBase_);
54     sslSocket_->connect(this, address_);
55   }
56
57   void connectSuccess() noexcept override {
58     cerr << "client SSL socket connected" << endl;
59
60     for (int i = 0; i < 1000; ++i) {
61       sslSocket_->detachSSLContext();
62       sslSocket_->attachSSLContext(ctx_);
63     }
64
65     EXPECT_EQ(ctx_->getSSLCtx()->references, 2);
66
67     sslSocket_->write(this, buf_, sizeof(buf_));
68     sslSocket_->setReadCB(this);
69     memset(readbuf_, 'b', sizeof(readbuf_));
70     bytesRead_ = 0;
71   }
72
73   void connectErr(const AsyncSocketException& ex) noexcept override
74   {
75     cerr << "AttachDetachClient::connectError: " << ex.what() << endl;
76     sslSocket_.reset();
77   }
78
79   void writeSuccess() noexcept override {
80     cerr << "client write success" << endl;
81   }
82
83   void writeErr(size_t bytesWritten, const AsyncSocketException& ex)
84     noexcept override {
85     cerr << "client writeError: " << ex.what() << endl;
86   }
87
88   void getReadBuffer(void** bufReturn, size_t* lenReturn) override {
89     *bufReturn = readbuf_ + bytesRead_;
90     *lenReturn = sizeof(readbuf_) - bytesRead_;
91   }
92   void readEOF() noexcept override {
93     cerr << "client readEOF" << endl;
94   }
95
96   void readErr(const AsyncSocketException& ex) noexcept override {
97     cerr << "client readError: " << ex.what() << endl;
98   }
99
100   void readDataAvailable(size_t len) noexcept override {
101     cerr << "client read data: " << len << endl;
102     bytesRead_ += len;
103     if (len == sizeof(buf_)) {
104       EXPECT_EQ(memcmp(buf_, readbuf_, bytesRead_), 0);
105       sslSocket_->closeNow();
106     }
107   }
108 };
109
110 /**
111  * Test passing contexts between threads
112  */
113 TEST(AsyncSSLSocketTest2, AttachDetachSSLContext) {
114   // Start listening on a local port
115   WriteCallbackBase writeCallback;
116   ReadCallback readCallback(&writeCallback);
117   HandshakeCallback handshakeCallback(&readCallback);
118   SSLServerAcceptCallbackDelay acceptCallback(&handshakeCallback);
119   TestSSLServer server(&acceptCallback);
120
121   EventBase eventBase;
122   EventBaseAborter eba(&eventBase, 3000);
123   std::shared_ptr<AttachDetachClient> client(
124     new AttachDetachClient(&eventBase, server.getAddress()));
125
126   client->connect();
127   eventBase.loop();
128 }
129
130 }
131 ///////////////////////////////////////////////////////////////////////////
132 // init_unit_test_suite
133 ///////////////////////////////////////////////////////////////////////////
134
135 namespace {
136 using folly::SSLContext;
137 struct Initializer {
138   Initializer() {
139     signal(SIGPIPE, SIG_IGN);
140     SSLContext::setSSLLockTypes({
141         {CRYPTO_LOCK_EVP_PKEY, SSLContext::LOCK_NONE},
142         {CRYPTO_LOCK_SSL_SESSION, SSLContext::LOCK_SPINLOCK},
143         {CRYPTO_LOCK_SSL_CTX, SSLContext::LOCK_NONE}});
144   }
145 };
146 Initializer initializer;
147 } // anonymous