GCC Code Coverage Report


Directory: ./
File: Drv/TcpServer/TcpServerComponentImpl.cpp
Date: 2026-09-03 21:13:48
Exec Total Coverage
Lines: 64 74 86.5%
Functions: 14 14 100.0%
Branches: 29 43 67.4%

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
2/2
✓ Branch 10 taken 7 times.
✓ Branch 21 taken 7 times.
7 TcpServerComponentImpl::TcpServerComponentImpl(const char* const compName) : TcpServerComponentBase(compName) {}
26
27 6 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 6 m_allocation_size = buffer_size; // Store the buffer size
33 6 (void)m_socket.configure(ipv4_address, port, send_timeout_seconds, send_timeout_microseconds);
34 6 return startup();
35 }
36
37 14 TcpServerComponentImpl::~TcpServerComponentImpl() {}
38
39 // ----------------------------------------------------------------------
40 // Implementations for socket read task virtual methods
41 // ----------------------------------------------------------------------
42
43 114 U16 TcpServerComponentImpl::getListenPort() {
44 114 return m_socket.getListenPort();
45 }
46
47 665 IpSocket& TcpServerComponentImpl::getSocketHandler() {
48 665 return m_socket;
49 }
50
51 75 Fw::Buffer TcpServerComponentImpl::getBuffer() {
52 75 return allocate_out(0, m_allocation_size);
53 }
54
55 75 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 75 FW_ASSERT((status != SOCK_SUCCESS) || (buffer.getData() != nullptr));
58
1/1
✓ Branch 2 taken 75 times.
75 Drv::ByteStreamStatus recvStatus = ByteStreamStatus::OTHER_ERROR;
59
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 64 times.
75 if (status == SOCK_SUCCESS) {
60
1/1
✓ Branch 2 taken 11 times.
11 recvStatus = ByteStreamStatus::OP_OK;
61
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 11 times.
64 } else if (status == SOCK_NO_DATA_AVAILABLE) {
62
1/1
✓ Branch 2 taken 53 times.
53 recvStatus = ByteStreamStatus::RECV_NO_DATA;
63 } else {
64
1/1
✓ Branch 2 taken 11 times.
11 recvStatus = ByteStreamStatus::OTHER_ERROR;
65 }
66
1/1
✓ Branch 5 taken 75 times.
75 this->recv_out(0, buffer, recvStatus);
67 150 }
68
69 112 void TcpServerComponentImpl::connected() {
70
1/2
✓ Branch 5 taken 112 times.
✗ Branch 6 not taken.
112 if (isConnected_ready_OutputPort(0)) {
71 112 this->ready_out(0);
72 }
73 112 }
74
75 16 bool TcpServerComponentImpl::isStarted() {
76
1/1
✓ Branch 5 taken 16 times.
16 Os::ScopeLock scopedLock(this->m_lock);
77 32 return this->m_descriptor.serverFd != -1;
78 16 }
79
80 9 SocketIpStatus TcpServerComponentImpl::startup() {
81
1/1
✓ Branch 5 taken 9 times.
9 Os::ScopeLock scopedLock(this->m_lock);
82 9 Drv::SocketIpStatus status = SOCK_SUCCESS;
83 // Prevent multiple startup attempts
84
2/2
✓ Branch 6 taken 6 times.
✓ Branch 7 taken 3 times.
9 if (this->m_descriptor.serverFd == -1) {
85
1/1
✓ Branch 9 taken 6 times.
6 status = this->m_socket.startup(this->m_descriptor);
86 }
87 9 return status;
88 9 }
89
90 9 void TcpServerComponentImpl::terminate() {
91
1/1
✓ Branch 6 taken 9 times.
9 this->stop();
92
1/1
✓ Branch 5 taken 9 times.
9 Os::ScopeLock scopedLock(this->m_lock);
93
1/1
✓ Branch 9 taken 9 times.
9 this->m_socket.terminate(this->m_descriptor);
94 9 this->m_descriptor.serverFd = -1;
95 18 }
96
97 3 void TcpServerComponentImpl::readLoop() {
98 3 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 3 status = this->startup();
103
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 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
3/8
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 3 times.
3 } while (this->running() && status != SOCK_SUCCESS && this->getAutomaticOpen());
109 // Loop exit implies startup succeeded, a stop was requested, or reopen is disabled
110 3 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
3/6
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
3 if (this->running() && status == SOCK_SUCCESS) {
114 // Perform the nominal read loop
115 3 SocketComponentHelper::readLoop();
116 }
117 // Terminate the server
118 3 this->terminate();
119 3 }
120
121 // ----------------------------------------------------------------------
122 // Handler implementations for user-defined typed input ports
123 // ----------------------------------------------------------------------
124
125 112 Drv::ByteStreamStatus TcpServerComponentImpl::send_handler(const FwIndexType portNum, Fw::Buffer& fwBuffer) {
126 112 Drv::SocketIpStatus status = this->send(fwBuffer.getData(), fwBuffer.getSize());
127 112 Drv::ByteStreamStatus returnStatus;
128
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
112 switch (status) {
129 case SOCK_INTERRUPTED_TRY_AGAIN:
130 returnStatus = ByteStreamStatus::SEND_RETRY;
131 break;
132 112 case SOCK_SUCCESS:
133
1/1
✓ Branch 3 taken 112 times.
112 returnStatus = ByteStreamStatus::OP_OK;
134 112 break;
135 default:
136 returnStatus = ByteStreamStatus::OTHER_ERROR;
137 break;
138 }
139 112 return returnStatus;
140 }
141
142 1 void TcpServerComponentImpl::recvReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) {
143 1 this->deallocate_out(0, fwBuffer);
144 1 }
145
146 } // end namespace Drv
147