GCC Code Coverage Report


Directory: /home/runner/work/fprime/fprime/Drv/TcpServer/
File: TcpServerComponentImpl.cpp
Date: 2026-09-03 22:12:45
Exec Total Coverage
Lines: 0 74 0.0%
Functions: 0 14 0.0%
Branches: 0 43 0.0%

Line Branch Exec Source
1 // ======================================================================
2 // \title TcpServerComponentImpl.cpp
3 // \author mstarch
4 // \brief cpp file for TcpServerComponentImpl component implementation class
5 //
6 // \copyright
7 // Copyright 2009-2020, by the California Institute of Technology.
8 // ALL RIGHTS RESERVED. United States Government Sponsorship
9 // acknowledged.
10 //
11 // ======================================================================
12
13 #include <Drv/TcpServer/TcpServerComponentImpl.hpp>
14 #include <Fw/FPrimeBasicTypes.hpp>
15 #include <limits>
16 #include "Fw/Logger/Logger.hpp"
17 #include "Fw/Types/Assert.hpp"
18
19 namespace Drv {
20
21 // ----------------------------------------------------------------------
22 // Construction, initialization, and destruction
23 // ----------------------------------------------------------------------
24
25 TcpServerComponentImpl::TcpServerComponentImpl(const char* const compName) : TcpServerComponentBase(compName) {}
26
27 SocketIpStatus TcpServerComponentImpl::configure(const char* const ipv4_address,
28 const U16 port,
29 const U32 send_timeout_seconds,
30 const U32 send_timeout_microseconds,
31 FwSizeType buffer_size) {
32 m_allocation_size = buffer_size; // Store the buffer size
33 (void)m_socket.configure(ipv4_address, port, send_timeout_seconds, send_timeout_microseconds);
34 return startup();
35 }
36
37 TcpServerComponentImpl::~TcpServerComponentImpl() {}
38
39 // ----------------------------------------------------------------------
40 // Implementations for socket read task virtual methods
41 // ----------------------------------------------------------------------
42
43 U16 TcpServerComponentImpl::getListenPort() {
44 return m_socket.getListenPort();
45 }
46
47 IpSocket& TcpServerComponentImpl::getSocketHandler() {
48 return m_socket;
49 }
50
51 Fw::Buffer TcpServerComponentImpl::getBuffer() {
52 return allocate_out(0, m_allocation_size);
53 }
54
55 void TcpServerComponentImpl::sendBuffer(Fw::Buffer buffer, SocketIpStatus status) {
56 // A successful receive must have produced a buffer with backing data (size may be zero)
57 FW_ASSERT((status != SOCK_SUCCESS) || (buffer.getData() != nullptr));
58 Drv::ByteStreamStatus recvStatus = ByteStreamStatus::OTHER_ERROR;
59 if (status == SOCK_SUCCESS) {
60 recvStatus = ByteStreamStatus::OP_OK;
61 } else if (status == SOCK_NO_DATA_AVAILABLE) {
62 recvStatus = ByteStreamStatus::RECV_NO_DATA;
63 } else {
64 recvStatus = ByteStreamStatus::OTHER_ERROR;
65 }
66 this->recv_out(0, buffer, recvStatus);
67 }
68
69 void TcpServerComponentImpl::connected() {
70 if (isConnected_ready_OutputPort(0)) {
71 this->ready_out(0);
72 }
73 }
74
75 bool TcpServerComponentImpl::isStarted() {
76 Os::ScopeLock scopedLock(this->m_lock);
77 return this->m_descriptor.serverFd != -1;
78 }
79
80 SocketIpStatus TcpServerComponentImpl::startup() {
81 Os::ScopeLock scopedLock(this->m_lock);
82 Drv::SocketIpStatus status = SOCK_SUCCESS;
83 // Prevent multiple startup attempts
84 if (this->m_descriptor.serverFd == -1) {
85 status = this->m_socket.startup(this->m_descriptor);
86 }
87 return status;
88 }
89
90 void TcpServerComponentImpl::terminate() {
91 this->stop();
92 Os::ScopeLock scopedLock(this->m_lock);
93 this->m_socket.terminate(this->m_descriptor);
94 this->m_descriptor.serverFd = -1;
95 }
96
97 void TcpServerComponentImpl::readLoop() {
98 Drv::SocketIpStatus status = Drv::SocketIpStatus::SOCK_NOT_STARTED;
99 // Keep trying to reconnect until the status is good, told to stop, or reconnection is turned off
100 // @non-terminating@: retry loop bounded by stop request
101 do {
102 status = this->startup();
103 if (status != SOCK_SUCCESS) {
104 Fw::Logger::log("[WARNING] Failed to listen on port %hu with status %d\n", this->getListenPort(), status);
105 (void)Os::Task::delay(SOCKET_RETRY_INTERVAL);
106 continue;
107 }
108 } while (this->running() && status != SOCK_SUCCESS && this->getAutomaticOpen());
109 // Loop exit implies startup succeeded, a stop was requested, or reopen is disabled
110 FW_ASSERT(status == SOCK_SUCCESS || (not this->running()) || (not this->getAutomaticOpen()),
111 static_cast<FwAssertArgType>(status));
112 // If start up was successful then perform normal operations
113 if (this->running() && status == SOCK_SUCCESS) {
114 // Perform the nominal read loop
115 SocketComponentHelper::readLoop();
116 }
117 // Terminate the server
118 this->terminate();
119 }
120
121 // ----------------------------------------------------------------------
122 // Handler implementations for user-defined typed input ports
123 // ----------------------------------------------------------------------
124
125 Drv::ByteStreamStatus TcpServerComponentImpl::send_handler(const FwIndexType portNum, Fw::Buffer& fwBuffer) {
126 Drv::SocketIpStatus status = this->send(fwBuffer.getData(), fwBuffer.getSize());
127 Drv::ByteStreamStatus returnStatus;
128 switch (status) {
129 case SOCK_INTERRUPTED_TRY_AGAIN:
130 returnStatus = ByteStreamStatus::SEND_RETRY;
131 break;
132 case SOCK_SUCCESS:
133 returnStatus = ByteStreamStatus::OP_OK;
134 break;
135 default:
136 returnStatus = ByteStreamStatus::OTHER_ERROR;
137 break;
138 }
139 return returnStatus;
140 }
141
142 void TcpServerComponentImpl::recvReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) {
143 this->deallocate_out(0, fwBuffer);
144 }
145
146 } // end namespace Drv
147