1 /*
2 * Copyright (c) Facebook, Inc. and its affiliates.
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 <signal.h>
18
19 #include <iostream>
20
21 #include <folly/Random.h>
22 #include <folly/String.h>
23 #include <folly/init/Init.h>
24 #include <folly/ssl/Init.h>
25
26 #include <thrift/lib/cpp2/server/ThriftServer.h>
27 #include <thrift/perf/cpp/AsyncLoadHandler2.h>
28
29 using std::cout;
30 using namespace apache::thrift;
31
32 DEFINE_int32(port, 1234, "server port");
33 DEFINE_int64(num_threads, 4, "number of worker threads");
34 DEFINE_int64(num_queue_threads, 4, "number of task queue threads");
35 DEFINE_int32(max_conn_pool_size, 0, "maximum size of idle connection pool");
36 DEFINE_int32(idle_timeout, 0, "idle timeout (in milliseconds)");
37 DEFINE_int32(task_timeout, 0, "task timeout (in milliseconds)");
38 DEFINE_int32(
39 handshake_timeout,
40 0,
41 "SSL handshake timeout (in milliseconds). "
42 "Default is 0, which is to not set a granular timeout for SSL handshakes. "
43 "Connections that stall during handshakes may still be timed out "
44 "with --idle_timeout");
45 DEFINE_int32(max_connections, 0, "DEPRECATED (REMOVE ME)");
46 DEFINE_int32(max_requests, 0, "max active requests");
47 DEFINE_string(cert, "", "server SSL certificate file");
48 DEFINE_string(key, "", "server SSL private key file");
49 DEFINE_string(client_ca_list, "", "file pointing to a client CA or list");
50 DEFINE_string(ticket_seeds, "", "server Ticket seeds file");
51 DEFINE_string(
52 ecc_curve, "prime256v1", "The ECC curve to use for EC handshakes");
53 DEFINE_bool(enable_tfo, true, "Enable TFO");
54 DEFINE_int32(tfo_queue_size, 1000, "TFO queue size");
55
setTunables(ThriftServer * server)56 void setTunables(ThriftServer* server) {
57 if (FLAGS_idle_timeout > 0) {
58 server->setIdleTimeout(std::chrono::milliseconds(FLAGS_idle_timeout));
59 }
60 if (FLAGS_task_timeout > 0) {
61 server->setTaskExpireTime(std::chrono::milliseconds(FLAGS_task_timeout));
62 }
63 if (FLAGS_handshake_timeout > 0) {
64 server->setSSLHandshakeTimeout(
65 std::chrono::milliseconds(FLAGS_handshake_timeout));
66 }
67 }
68
69 ThriftServer* g_server = nullptr;
70
sigHandler(int)71 [[noreturn]] void sigHandler(int /* signo */) {
72 g_server->stop();
73 exit(0);
74 }
75
main(int argc,char * argv[])76 int main(int argc, char* argv[]) {
77 folly::init(&argc, &argv);
78
79 if (argc != 1) {
80 fprintf(stderr, "error: unhandled arguments:");
81 for (int n = 1; n < argc; ++n) {
82 fprintf(stderr, " %s", argv[n]);
83 }
84 fprintf(stderr, "\n");
85 return 1;
86 }
87
88 auto handler = std::make_shared<AsyncLoadHandler2>();
89
90 std::shared_ptr<ThriftServer> server;
91 server.reset(new ThriftServer());
92 server->setInterface(handler);
93 server->setPort(FLAGS_port);
94 server->setNumIOWorkerThreads(FLAGS_num_threads);
95 server->setNumCPUWorkerThreads(FLAGS_num_queue_threads);
96 server->setMaxRequests(FLAGS_max_requests);
97 server->setFastOpenOptions(FLAGS_enable_tfo, FLAGS_tfo_queue_size);
98
99 if (FLAGS_cert.length() > 0 && FLAGS_key.length() > 0) {
100 auto sslContext = std::make_shared<wangle::SSLContextConfig>();
101 sslContext->setCertificate(FLAGS_cert, FLAGS_key, "");
102 sslContext->clientCAFile = FLAGS_client_ca_list;
103 sslContext->eccCurveName = FLAGS_ecc_curve;
104 server->setSSLConfig(sslContext);
105 }
106 if (!FLAGS_ticket_seeds.empty()) {
107 server->watchTicketPathForChanges(FLAGS_ticket_seeds);
108 } else {
109 // Generate random seeds to use for all workers. If no seeds are set, then
110 // each worker gets its own random seeds, so session resumptions fail across
111 // workers.
112 wangle::TLSTicketKeySeeds seeds;
113 for (auto* seed : {&seeds.oldSeeds, &seeds.currentSeeds, &seeds.newSeeds}) {
114 auto randomData = folly::Random::secureRandom<uint64_t>();
115 auto asHex = folly::hexlify(folly::ByteRange(
116 (const unsigned char*)&randomData, sizeof(uint64_t)));
117 seed->push_back(std::move(asHex));
118 }
119 server->setTicketSeeds(std::move(seeds));
120 }
121
122 // Set tunable server parameters
123 setTunables(server.get());
124
125 g_server = server.get();
126 signal(SIGINT, sigHandler);
127
128 cout << "Serving requests on port " << FLAGS_port << "...\n";
129 server->serve();
130
131 cout << "Exiting normally" << std::endl;
132
133 return 0;
134 }
135