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_handler.h"
10 #include "utilities/dequeue_buffer.h"
12 SecondaryTcpServer::SecondaryTcpServer(
MsgHandler &msg_handler,
const std::string &primary_ip, in_port_t primary_port,
13 in_port_t port,
bool reboot_after_install)
14 : msg_handler_(msg_handler),
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 bool first_connection =
true;
46 while (keep_running_.load()) {
47 sockaddr_storage peer_sa{};
48 socklen_t peer_sa_size =
sizeof(sockaddr_storage);
50 LOG_DEBUG <<
"Waiting for connection from Primary...";
51 int con_fd = accept(*listen_socket_,
reinterpret_cast<sockaddr *
>(&peer_sa), &peer_sa_size);
60 LOG_INFO <<
"Socket accept failed, aborting.";
64 if (first_connection) {
65 LOG_INFO <<
"Primary connected.";
66 first_connection =
false;
68 LOG_DEBUG <<
"Primary reconnected.";
70 auto continue_running = HandleOneConnection(*
Socket(con_fd));
71 if (!continue_running) {
72 keep_running_.store(
false);
74 LOG_DEBUG <<
"Primary disconnected.";
78 std::unique_lock<std::mutex> lock(running_condition_mutex_);
80 running_condition_.notify_all();
83 LOG_INFO <<
"Secondary TCP server exiting.";
86 void SecondaryTcpServer::stop() {
87 LOG_DEBUG <<
"Stopping Secondary TCP server...";
88 keep_running_.store(
false);
93 in_port_t SecondaryTcpServer::port()
const {
return listen_socket_.port(); }
94 SecondaryTcpServer::ExitReason SecondaryTcpServer::exit_reason()
const {
return exit_reason_; }
96 static bool sendResponseMessage(
int socket_fd,
const Asn1Message::Ptr &resp_msg);
98 bool SecondaryTcpServer::HandleOneConnection(
int socket) {
104 bool keep_running_server =
true;
105 bool keep_running_current_session =
true;
107 while (keep_running_current_session) {
109 AKIpUptaneMes_t *m =
nullptr;
111 asn_codec_ctx_s context{};
115 received = recv(socket, buffer.
Tail(), buffer.
TailSpace(), 0);
117 res = ber_decode(&context, &asn_DEF_AKIpUptaneMes,
reinterpret_cast<void **
>(&m), buffer.
Head(), buffer.
Size());
119 }
while (res.code == RC_WMORE && received > 0);
124 LOG_TRACE <<
"Primary has closed a connection socket";
129 LOG_ERROR <<
"Error while reading message data from a socket: " << strerror(errno);
133 if (res.code != RC_OK) {
134 LOG_ERROR <<
"Failed to decode a message received from Primary";
138 LOG_DEBUG <<
"Received a request from Primary: " << request_msg->toStr();
140 MsgHandler::ReturnCode handle_status_code = msg_handler_.handleMsg(request_msg, response_msg);
142 switch (handle_status_code) {
143 case MsgHandler::ReturnCode::kRebootRequired: {
144 exit_reason_ = ExitReason::kRebootNeeded;
145 keep_running_current_session = sendResponseMessage(socket, response_msg);
146 if (reboot_after_install_) {
147 keep_running_server = keep_running_current_session =
false;
151 case MsgHandler::ReturnCode::kOk: {
152 keep_running_current_session = sendResponseMessage(socket, response_msg);
155 case MsgHandler::ReturnCode::kUnkownMsg:
158 keep_running_current_session =
false;
159 LOG_INFO <<
"Unknown message received from Primary!";
165 return keep_running_server;
171 void SecondaryTcpServer::wait_until_running(
int timeout) {
172 std::unique_lock<std::mutex> lock(running_condition_mutex_);
173 running_condition_.wait_for(lock, std::chrono::seconds(timeout), [&] {
return is_running_; });
176 bool sendResponseMessage(
int socket_fd,
const Asn1Message::Ptr &resp_msg) {
177 LOG_DEBUG <<
"Encoding and sending response message";
180 setsockopt(socket_fd, IPPROTO_TCP, TCP_NODELAY, &optval,
sizeof(
int));
181 asn_enc_rval_t encode_result = der_encode(&asn_DEF_AKIpUptaneMes, &resp_msg->msg_, Asn1SocketWriteCallback,
182 reinterpret_cast<void *
>(&socket_fd));
183 if (encode_result.encoded == -1) {
184 LOG_ERROR <<
"Failed to encode a response message";
188 setsockopt(socket_fd, IPPROTO_TCP, TCP_NODELAY, &optval,
sizeof(
int));