1 #include "secondary_tcp_server.h"
3 #include <netinet/tcp.h>
5 #include "AKInstallationResultCode.h"
6 #include "AKIpUptaneMes.h"
7 #include "asn1/asn1_message.h"
8 #include "logging/logging.h"
9 #include "msg_dispatcher.h"
10 #include "utilities/dequeue_buffer.h"
12 SecondaryTcpServer::SecondaryTcpServer(
MsgDispatcher &msg_dispatcher,
const std::string &primary_ip,
13 in_port_t primary_port, in_port_t port,
bool reboot_after_install)
14 : msg_dispatcher_(msg_dispatcher),
17 reboot_after_install_(reboot_after_install),
19 if (primary_ip.empty()) {
23 ConnectionSocket conn_socket(primary_ip, primary_port, listen_socket_.port());
24 if (conn_socket.connect() == 0) {
25 LOG_INFO <<
"Connected to Primary, sending info about this Secondary.";
26 HandleOneConnection(*conn_socket);
28 LOG_INFO <<
"Failed to connect to Primary.";
33 if (listen(*listen_socket_, SOMAXCONN) < 0) {
34 throw std::system_error(errno, std::system_category(),
"listen");
36 LOG_INFO <<
"Secondary TCP server listening on " << listen_socket_.toString();
39 std::unique_lock<std::mutex> lock(running_condition_mutex_);
41 running_condition_.notify_all();
44 while (keep_running_.load()) {
45 sockaddr_storage peer_sa{};
46 socklen_t peer_sa_size =
sizeof(sockaddr_storage);
48 LOG_DEBUG <<
"Waiting for connection from Primary...";
49 int con_fd = accept(*listen_socket_, reinterpret_cast<sockaddr *>(&peer_sa), &peer_sa_size);
58 LOG_INFO <<
"Socket accept failed, aborting.";
62 LOG_DEBUG <<
"Primary connected.";
63 auto continue_running = HandleOneConnection(*
Socket(con_fd));
64 if (!continue_running) {
65 keep_running_.store(
false);
67 LOG_DEBUG <<
"Primary disconnected.";
71 std::unique_lock<std::mutex> lock(running_condition_mutex_);
73 running_condition_.notify_all();
76 LOG_INFO <<
"Secondary TCP server exiting.";
79 void SecondaryTcpServer::stop() {
80 LOG_DEBUG <<
"Stopping Secondary TCP server...";
81 keep_running_.store(
false);
86 in_port_t SecondaryTcpServer::port()
const {
return listen_socket_.port(); }
87 SecondaryTcpServer::ExitReason SecondaryTcpServer::exit_reason()
const {
return exit_reason_; }
89 static bool sendResponseMessage(
int socket_fd, Asn1Message::Ptr &resp_msg);
91 bool SecondaryTcpServer::HandleOneConnection(
int socket) {
97 bool keep_running_server =
true;
98 bool keep_running_current_session =
true;
100 while (keep_running_current_session) {
102 AKIpUptaneMes_t *m =
nullptr;
104 asn_codec_ctx_s context{};
108 received = recv(socket, buffer.
Tail(), buffer.
TailSpace(), 0);
110 res = ber_decode(&context, &asn_DEF_AKIpUptaneMes, reinterpret_cast<void **>(&m), buffer.
Head(), buffer.
Size());
112 }
while (res.code == RC_WMORE && received > 0);
117 LOG_DEBUG <<
"Primary has closed a connection socket";
121 if (res.code != RC_OK) {
122 LOG_ERROR <<
"Failed to receive and/or decode a message from Primary";
126 LOG_DEBUG <<
"Received message from Primary, try to decode it...";
128 MsgDispatcher::HandleStatusCode handle_status_code = msg_dispatcher_.handleMsg(request_msg, response_msg);
130 switch (handle_status_code) {
131 case MsgDispatcher::HandleStatusCode::kRebootRequired: {
132 exit_reason_ = ExitReason::kRebootNeeded;
133 keep_running_current_session = sendResponseMessage(socket, response_msg);
134 if (reboot_after_install_) {
135 keep_running_server = keep_running_current_session =
false;
139 case MsgDispatcher::HandleStatusCode::kOk: {
140 keep_running_current_session = sendResponseMessage(socket, response_msg);
143 case MsgDispatcher::HandleStatusCode::kUnkownMsg:
146 keep_running_current_session =
false;
147 LOG_INFO <<
"Unknown message received from Primary!";
153 return keep_running_server;
159 void SecondaryTcpServer::wait_until_running(
int timeout) {
160 std::unique_lock<std::mutex> lock(running_condition_mutex_);
161 running_condition_.wait_for(lock, std::chrono::seconds(timeout), [&] {
return is_running_; });
164 bool sendResponseMessage(
int socket_fd, Asn1Message::Ptr &resp_msg) {
165 LOG_DEBUG <<
"Encoding and sending response message";
168 setsockopt(socket_fd, IPPROTO_TCP, TCP_NODELAY, &optval,
sizeof(
int));
169 asn_enc_rval_t encode_result = der_encode(&asn_DEF_AKIpUptaneMes, &resp_msg->msg_, Asn1SocketWriteCallback,
170 reinterpret_cast<void *>(&socket_fd));
171 if (encode_result.encoded == -1) {
172 LOG_ERROR <<
"Failed to encode a response message";
176 setsockopt(socket_fd, IPPROTO_TCP, TCP_NODELAY, &optval,
sizeof(
int));