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