blob: dae2f73737e215c28dc3d7a91997f276c5fa75ea [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "garnet/bin/network_time/roughtime_server.h"
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <poll.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <thread>
#include "gtest/gtest.h"
#include "src/lib/files/unique_fd.h"
#define PORT 3453
namespace time_server {
TEST(RoughTimeServerTest, TestValid) {
uint8_t key[roughtime::kPublicKeyLength] = {0};
RoughTimeServer server1("name", "address:3424", key,
roughtime::kPublicKeyLength + 1);
EXPECT_EQ(server1.IsValid(), false);
RoughTimeServer server2("name", "address:3424", key,
roughtime::kPublicKeyLength);
EXPECT_EQ(server2.IsValid(), true);
}
#define BUFSIZE 1024
void listen(int sock) {
struct sockaddr_in client;
int attempts = 3;
int ret;
do {
attempts--;
int timeout = 3 * 1000;
pollfd readfd;
readfd.fd = sock;
readfd.events = POLLIN;
ret = poll(&readfd, 1, timeout);
} while (attempts > 0 && ret != 1);
ASSERT_NE(ret, 0) << "poll timeout";
ASSERT_EQ(ret, 1) << "poll: " << strerror(errno);
char buf[BUFSIZE];
socklen_t len = sizeof(client);
int n = recvfrom(sock, buf, BUFSIZE, 0, (struct sockaddr*)&client, &len);
ASSERT_GE(n, 0) << "recvfrom: " << strerror(errno);
struct hostent* host = gethostbyaddr((const char*)&client.sin_addr.s_addr,
sizeof(client.sin_addr.s_addr), AF_INET);
ASSERT_NE(host, nullptr) << "gethostbyaddr: " << strerror(errno);
char* hostaddr = inet_ntoa(client.sin_addr);
ASSERT_NE(hostaddr, nullptr) << "inet_ntoa: " << strerror(errno);
n = sendto(sock, buf, strlen(buf), 0, (struct sockaddr*)&client, len);
ASSERT_GE(n, 0) << "sendto: " << strerror(errno);
}
// Checks that server recieves request from network_time
TEST(RoughTimeServerTest, TestServerRequest) {
uint8_t key[roughtime::kPublicKeyLength] = {0};
RoughTimeServer server("name", "127.0.0.1:" + std::to_string(PORT), key,
roughtime::kPublicKeyLength);
EXPECT_EQ(server.IsValid(), true);
// Start server
struct sockaddr_in serveraddr;
memset(&serveraddr, 0, sizeof(serveraddr));
fxl::UniqueFD sock_ufd(socket(AF_INET, SOCK_DGRAM, 0));
ASSERT_TRUE(sock_ufd.is_valid())
<< "udp server: socket call" << strerror(errno);
int sock = sock_ufd.get();
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = INADDR_ANY;
serveraddr.sin_port = htons(PORT);
ASSERT_EQ(bind(sock, (struct sockaddr*)&serveraddr, sizeof(serveraddr)), 0)
<< "binding udp: " << strerror(errno);
std::thread t1(listen, sock);
std::pair<time_server::Status, std::optional<zx::time_utc>> ret;
int attempts = 3;
do {
attempts--;
ret = server.GetTimeFromServer();
} while (attempts > 0 && ret.first == time_server::Status::NETWORK_ERROR);
t1.join();
}
} // namespace time_server