2023-08-31 21:05:17 +08:00
|
|
|
// Copyright 2023 Google LLC
|
|
|
|
//
|
|
|
|
// 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
|
|
|
|
//
|
|
|
|
// https://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 "sandboxed_api/sandbox2/network_proxy/testing.h"
|
|
|
|
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <netinet/in.h>
|
2023-09-05 15:56:21 +08:00
|
|
|
#include <poll.h>
|
|
|
|
#include <sys/eventfd.h>
|
2023-08-31 21:05:17 +08:00
|
|
|
#include <sys/socket.h>
|
|
|
|
|
2023-09-05 15:56:21 +08:00
|
|
|
#include <cstddef>
|
|
|
|
#include <cstdint>
|
|
|
|
#include <memory>
|
2023-08-31 21:05:17 +08:00
|
|
|
#include <thread>
|
2023-09-05 15:56:21 +08:00
|
|
|
#include <utility>
|
2023-08-31 21:05:17 +08:00
|
|
|
|
2023-09-05 15:56:21 +08:00
|
|
|
#include "absl/base/macros.h"
|
|
|
|
#include "absl/log/check.h"
|
|
|
|
#include "absl/memory/memory.h"
|
2023-08-31 21:05:17 +08:00
|
|
|
#include "absl/status/status.h"
|
|
|
|
#include "absl/strings/string_view.h"
|
|
|
|
#include "sandboxed_api/util/fileops.h"
|
2023-09-05 15:56:21 +08:00
|
|
|
#include "sandboxed_api/util/status_macros.h"
|
2023-08-31 21:05:17 +08:00
|
|
|
|
|
|
|
namespace sandbox2 {
|
|
|
|
namespace {
|
2023-09-05 15:56:21 +08:00
|
|
|
|
|
|
|
using sapi::file_util::fileops::FDCloser;
|
|
|
|
|
|
|
|
absl::StatusOr<FDCloser> CreateServerSocket(int port, bool ipv6 = true) {
|
|
|
|
// Listen to localhost only
|
|
|
|
sockaddr_in6 addr6;
|
|
|
|
sockaddr_in addr4;
|
|
|
|
addr6.sin6_family = AF_INET6;
|
|
|
|
addr4.sin_family = AF_INET;
|
|
|
|
addr4.sin_port = addr6.sin6_port = htons(port);
|
|
|
|
PCHECK(inet_pton(AF_INET, "127.0.0.1", &addr4.sin_addr.s_addr) == 1);
|
|
|
|
PCHECK(inet_pton(AF_INET6, "::1", &addr6.sin6_addr.s6_addr) == 1);
|
|
|
|
sockaddr* addr = ipv6 ? reinterpret_cast<sockaddr*>(&addr6)
|
|
|
|
: reinterpret_cast<sockaddr*>(&addr4);
|
|
|
|
size_t addr_size = ipv6 ? sizeof(addr6) : sizeof(addr4);
|
|
|
|
sapi::file_util::fileops::FDCloser s(
|
|
|
|
socket(addr->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0));
|
2023-08-31 21:05:17 +08:00
|
|
|
if (s.get() < 0) {
|
2023-09-05 15:56:21 +08:00
|
|
|
return absl::InternalError("socket() failed");
|
2023-08-31 21:05:17 +08:00
|
|
|
}
|
2023-09-05 15:56:21 +08:00
|
|
|
int enable = 1;
|
|
|
|
if (setsockopt(s.get(), SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) <
|
|
|
|
0) {
|
|
|
|
return absl::InternalError("setsockopt() failed");
|
2023-08-31 21:05:17 +08:00
|
|
|
}
|
2023-09-05 15:56:21 +08:00
|
|
|
if (bind(s.get(), addr, addr_size) < 0) {
|
|
|
|
return absl::InternalError("bind() failed");
|
2023-08-31 21:05:17 +08:00
|
|
|
}
|
2023-09-05 15:56:21 +08:00
|
|
|
if (listen(s.get(), 1) < 0) {
|
|
|
|
return absl::InternalError("listen() failed");
|
2023-08-31 21:05:17 +08:00
|
|
|
}
|
2023-09-05 15:56:21 +08:00
|
|
|
return s;
|
|
|
|
}
|
2023-08-31 21:05:17 +08:00
|
|
|
|
2023-09-05 15:56:21 +08:00
|
|
|
} // namespace
|
|
|
|
|
|
|
|
absl::StatusOr<std::unique_ptr<NetworkProxyTestServer>>
|
|
|
|
NetworkProxyTestServer::Start(bool ipv6) {
|
|
|
|
static int port = 8085;
|
|
|
|
FDCloser event_fd(eventfd(0, 0));
|
|
|
|
if (event_fd.get() < 0) {
|
|
|
|
return absl::InternalError("eventfd() failed");
|
2023-08-31 21:05:17 +08:00
|
|
|
}
|
2023-09-05 15:56:21 +08:00
|
|
|
SAPI_ASSIGN_OR_RETURN(FDCloser server_socket, CreateServerSocket(port, ipv6));
|
|
|
|
auto server = absl::WrapUnique(new NetworkProxyTestServer(
|
|
|
|
port, std::move(server_socket), std::move(event_fd)));
|
|
|
|
server->Spawn();
|
|
|
|
return server;
|
|
|
|
}
|
2023-08-31 21:05:17 +08:00
|
|
|
|
2023-09-05 15:56:21 +08:00
|
|
|
void NetworkProxyTestServer::Stop() {
|
|
|
|
if (event_fd_.get() < 0) {
|
2023-08-31 21:05:17 +08:00
|
|
|
return;
|
|
|
|
}
|
2023-09-05 15:56:21 +08:00
|
|
|
uint64_t value = 1;
|
|
|
|
PCHECK(write(event_fd_.get(), &value, sizeof(value)) == sizeof(value));
|
|
|
|
thread_.join();
|
|
|
|
event_fd_.Close();
|
|
|
|
server_socket_.Close();
|
|
|
|
}
|
2023-08-31 21:05:17 +08:00
|
|
|
|
2023-09-05 15:56:21 +08:00
|
|
|
void NetworkProxyTestServer::Run() {
|
|
|
|
struct pollfd pfds[] = {
|
|
|
|
{.fd = server_socket_.get(), .events = POLLIN},
|
|
|
|
{.fd = event_fd_.get(), .events = POLLIN},
|
|
|
|
};
|
|
|
|
do {
|
|
|
|
PCHECK(poll(pfds, ABSL_ARRAYSIZE(pfds), -1) > 0);
|
|
|
|
if (pfds[1].revents & POLLIN) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} while (!(pfds[0].revents & POLLIN));
|
|
|
|
FDCloser client(accept(server_socket_.get(), 0, 0));
|
|
|
|
PCHECK(client.get() >= 0);
|
2023-08-31 21:05:17 +08:00
|
|
|
constexpr absl::string_view kMsg = "Hello World\n";
|
2023-09-05 15:56:21 +08:00
|
|
|
PCHECK(write(client.get(), kMsg.data(), kMsg.size()) == kMsg.size());
|
2023-08-31 21:05:17 +08:00
|
|
|
}
|
|
|
|
|
2023-09-05 15:56:21 +08:00
|
|
|
void NetworkProxyTestServer::Spawn() {
|
|
|
|
thread_ = std::thread([this] { Run(); });
|
2023-08-31 21:05:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace sandbox2
|