1 /*
2 * Copyright (C) 2019 The Android Open Source Project
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 <https/ServerSocket.h>
18
19 #include <https/ClientSocket.h>
20 #include <https/RunLoop.h>
21 #include <https/SafeCallbackable.h>
22 #include <https/Support.h>
23
24 #include <android-base/logging.h>
25
26 #include <arpa/inet.h>
27 #include <fcntl.h>
28 #include <iostream>
29 #include <netinet/in.h>
30 #include <sys/socket.h>
31 #include <unistd.h>
32
ServerSocket(HTTPServer * server,TransportType transportType,const char * iface,uint16_t port,const std::optional<std::string> & certificate_pem_path,const std::optional<std::string> & private_key_pem_path)33 ServerSocket::ServerSocket(
34 HTTPServer *server,
35 TransportType transportType,
36 const char *iface,
37 uint16_t port,
38 const std::optional<std::string> &certificate_pem_path,
39 const std::optional<std::string> &private_key_pem_path)
40 : mInitCheck(-ENODEV),
41 mServer(server),
42 mCertificatePath(certificate_pem_path),
43 mPrivateKeyPath(private_key_pem_path),
44 mSocket(-1),
45 mTransportType(transportType) {
46 if (mTransportType == TransportType::TLS) {
47 CHECK(mCertificatePath.has_value());
48 CHECK(mPrivateKeyPath.has_value());
49 }
50
51 sockaddr_in addr;
52 int res;
53
54 mSocket = socket(PF_INET, SOCK_STREAM, 0);
55 if (mSocket < 0) {
56 mInitCheck = -errno;
57 goto bail;
58 }
59
60 makeFdNonblocking(mSocket);
61
62 static constexpr int yes = 1;
63 res = setsockopt(mSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
64 if (res < 0) {
65 mInitCheck = -errno;
66 goto bail2;
67 }
68
69 memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
70 addr.sin_family = AF_INET;
71 addr.sin_port = htons(port);
72 addr.sin_addr.s_addr = inet_addr(iface);
73
74 res = bind(mSocket, reinterpret_cast<sockaddr *>(&addr), sizeof(addr));
75 if (res < 0) {
76 mInitCheck = -errno;
77 goto bail2;
78 }
79
80 res = listen(mSocket, 4);
81 if (res < 0) {
82 mInitCheck = -errno;
83 goto bail2;
84 }
85
86 mInitCheck = 0;
87 return;
88
89 bail2:
90 close(mSocket);
91 mSocket = -1;
92
93 bail:
94 ;
95 }
96
~ServerSocket()97 ServerSocket::~ServerSocket() {
98 if (mSocket >= 0) {
99 close(mSocket);
100 mSocket = -1;
101 }
102 }
103
initCheck() const104 int ServerSocket::initCheck() const {
105 return mInitCheck;
106 }
107
transportType() const108 ServerSocket::TransportType ServerSocket::transportType() const {
109 return mTransportType;
110 }
111
run(std::shared_ptr<RunLoop> rl)112 int ServerSocket::run(std::shared_ptr<RunLoop> rl) {
113 if (mInitCheck < 0) {
114 return mInitCheck;
115 }
116
117 if (mRunLoop) {
118 return -EBUSY;
119 }
120
121 mRunLoop = rl;
122 mRunLoop->postSocketRecv(
123 mSocket,
124 makeSafeCallback(this, &ServerSocket::acceptIncomingConnection));
125
126 return 0;
127 }
128
acceptIncomingConnection()129 void ServerSocket::acceptIncomingConnection() {
130 sockaddr_in addr;
131 socklen_t addrLen = sizeof(addr);
132
133 int s = accept(mSocket, reinterpret_cast<sockaddr *>(&addr), &addrLen);
134
135 if (s >= 0) {
136 uint32_t ip = ntohl(addr.sin_addr.s_addr);
137
138 LOG(VERBOSE)
139 << "Accepted incoming connection from "
140 << (ip >> 24)
141 << "."
142 << ((ip >> 16) & 0xff)
143 << "."
144 << ((ip >> 8) & 0xff)
145 << "."
146 << (ip & 0xff)
147 << ":"
148 << ntohs(addr.sin_port);
149
150 makeFdNonblocking(s);
151
152 auto clientSocket =
153 std::make_shared<ClientSocket>(mRunLoop, mServer, this, addr, s);
154
155 clientSocket->run();
156
157 mClientSockets.push_back(clientSocket);
158 }
159
160 mRunLoop->postSocketRecv(
161 mSocket,
162 makeSafeCallback(this, &ServerSocket::acceptIncomingConnection));
163 }
164
onClientSocketClosed(int sock)165 void ServerSocket::onClientSocketClosed(int sock) {
166 for (size_t i = mClientSockets.size(); i--;) {
167 if (mClientSockets[i]->fd() == sock) {
168 LOG(VERBOSE) << "Closing client connection.";
169 mClientSockets.erase(mClientSockets.begin() + i);
170 break;
171 }
172 }
173 }
174
certificate_pem_path() const175 std::optional<std::string> ServerSocket::certificate_pem_path() const {
176 return mCertificatePath;
177 }
178
private_key_pem_path() const179 std::optional<std::string> ServerSocket::private_key_pem_path() const {
180 return mPrivateKeyPath;
181 }
182
183