/* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include ServerSocket::ServerSocket( HTTPServer *server, TransportType transportType, const char *iface, uint16_t port, const std::optional &certificate_pem_path, const std::optional &private_key_pem_path) : mInitCheck(-ENODEV), mServer(server), mCertificatePath(certificate_pem_path), mPrivateKeyPath(private_key_pem_path), mSocket(-1), mTransportType(transportType) { if (mTransportType == TransportType::TLS) { CHECK(mCertificatePath.has_value()); CHECK(mPrivateKeyPath.has_value()); } sockaddr_in addr; int res; mSocket = socket(PF_INET, SOCK_STREAM, 0); if (mSocket < 0) { mInitCheck = -errno; goto bail; } makeFdNonblocking(mSocket); static constexpr int yes = 1; res = setsockopt(mSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); if (res < 0) { mInitCheck = -errno; goto bail2; } memset(addr.sin_zero, 0, sizeof(addr.sin_zero)); addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = inet_addr(iface); res = bind(mSocket, reinterpret_cast(&addr), sizeof(addr)); if (res < 0) { mInitCheck = -errno; goto bail2; } res = listen(mSocket, 4); if (res < 0) { mInitCheck = -errno; goto bail2; } mInitCheck = 0; return; bail2: close(mSocket); mSocket = -1; bail: ; } ServerSocket::~ServerSocket() { if (mSocket >= 0) { close(mSocket); mSocket = -1; } } int ServerSocket::initCheck() const { return mInitCheck; } ServerSocket::TransportType ServerSocket::transportType() const { return mTransportType; } int ServerSocket::run(std::shared_ptr rl) { if (mInitCheck < 0) { return mInitCheck; } if (mRunLoop) { return -EBUSY; } mRunLoop = rl; mRunLoop->postSocketRecv( mSocket, makeSafeCallback(this, &ServerSocket::acceptIncomingConnection)); return 0; } void ServerSocket::acceptIncomingConnection() { sockaddr_in addr; socklen_t addrLen = sizeof(addr); int s = accept(mSocket, reinterpret_cast(&addr), &addrLen); if (s >= 0) { uint32_t ip = ntohl(addr.sin_addr.s_addr); LOG(VERBOSE) << "Accepted incoming connection from " << (ip >> 24) << "." << ((ip >> 16) & 0xff) << "." << ((ip >> 8) & 0xff) << "." << (ip & 0xff) << ":" << ntohs(addr.sin_port); makeFdNonblocking(s); auto clientSocket = std::make_shared(mRunLoop, mServer, this, addr, s); clientSocket->run(); mClientSockets.push_back(clientSocket); } mRunLoop->postSocketRecv( mSocket, makeSafeCallback(this, &ServerSocket::acceptIncomingConnection)); } void ServerSocket::onClientSocketClosed(int sock) { for (size_t i = mClientSockets.size(); i--;) { if (mClientSockets[i]->fd() == sock) { LOG(VERBOSE) << "Closing client connection."; mClientSockets.erase(mClientSockets.begin() + i); break; } } } std::optional ServerSocket::certificate_pem_path() const { return mCertificatePath; } std::optional ServerSocket::private_key_pem_path() const { return mPrivateKeyPath; }