GCC Code Coverage Report


Directory: ./
File: Drv/Ip/TcpServerSocket.cpp
Date: 2026-11-03 21:15:54
Exec Total Coverage
Lines: 43 60 71.7%
Functions: 7 7 100.0%
Branches: 15 30 50.0%

Line Branch Exec Source
1 // ======================================================================
2 // \title TcpServerSocket.cpp
3 // \author mstarch
4 // \brief cpp file for TcpServerSocket core implementation classes
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 #include <Drv/Ip/TcpServerSocket.hpp>
13 #include <Fw/FPrimeBasicTypes.hpp>
14 #include <Fw/Logger/Logger.hpp>
15 #include <Fw/Types/Assert.hpp>
16
17 #include <cstring>
18
19 namespace Drv {
20
21 17 TcpServerSocket::TcpServerSocket() : IpSocket() {}
22
23 223 U16 TcpServerSocket::getListenPort() {
24 223 U16 port = this->m_port;
25 223 return port;
26 }
27
28 16 SocketIpStatus TcpServerSocket::startup(SocketDescriptor& socketDescriptor) {
29 16 struct sockaddr_in address;
30 // Acquire a socket, or return error
31 16 int serverFd = ::socket(AF_INET, SOCK_STREAM, 0);
32
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (serverFd == -1) {
33 ✗ return SOCK_FAILED_TO_GET_SOCKET;
34 }
35 // Set up the address port and name
36 16 address.sin_family = AF_INET;
37 16 address.sin_port = htons(this->m_port);
38
39 // OS specific settings
40 #if defined TGT_OS_TYPE_VXWORKS || TGT_OS_TYPE_DARWIN
41 address.sin_len = static_cast<U8>(sizeof(struct sockaddr_in));
42 #endif
43 // Convert the configured IPv4 address (dotted-quad) to a network-order in_addr.
44
1/1
✓ Branch 3 taken 16 times.
16 const SocketIpStatus addressStatus = IpSocket::addressToIp4(this->m_ipv4_address, &(address.sin_addr));
45
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (addressStatus != SOCK_SUCCESS) {
46 ✗ (void)::close(serverFd);
47 ✗ return SOCK_INVALID_IP_ADDRESS;
48 };
49
50
2/3
✓ Branch 5 taken 16 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 16 times.
16 if (IpSocket::setupSocketOptions(serverFd) != SOCK_SUCCESS) {
51 ✗ (void)::close(serverFd);
52 ✗ return SOCK_FAILED_TO_SET_SOCKET_OPTIONS;
53 }
54
55 // TCP requires bind to an address to the socket
56
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
16 if (::bind(serverFd, reinterpret_cast<struct sockaddr*>(&address), sizeof(address)) < 0) {
57 ✗ (void)::close(serverFd);
58 ✗ return SOCK_FAILED_TO_BIND;
59 }
60
61 16 socklen_t size = sizeof(address);
62 16 const int socknameStatus = ::getsockname(serverFd, reinterpret_cast<struct sockaddr*>(&address), &size);
63
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 if (socknameStatus == -1) {
64 ✗ (void)::close(serverFd);
65 ✗ return SOCK_FAILED_TO_READ_BACK_PORT;
66 }
67 // TCP requires listening on the socket. Since we only expect a single client, set the TCP backlog (second argument)
68 // to 1 to prevent queuing of multiple clients.
69
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
16 if (::listen(serverFd, 1) < 0) {
70 ✗ (void)::close(serverFd);
71 ✗ return SOCK_FAILED_TO_LISTEN; // What we have here is a failure to communicate
72 }
73
1/1
✓ Branch 8 taken 16 times.
16 Fw::Logger::log("Listening for single client at %s:%hu\n", this->m_ipv4_address, this->m_port);
74 16 FW_ASSERT(serverFd != -1);
75 16 socketDescriptor.serverFd = serverFd;
76 16 this->m_port = ntohs(address.sin_port);
77 16 return SOCK_SUCCESS;
78 }
79
80 19 void TcpServerSocket::terminate(const SocketDescriptor& socketDescriptor) {
81
2/2
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 3 times.
19 if (socketDescriptor.serverFd >= 0) {
82 16 (void)::shutdown(socketDescriptor.serverFd, SHUT_RDWR); // Shutdown first to avoid hanging "accept" calls
83 16 (void)::close(socketDescriptor.serverFd);
84 }
85 19 }
86
87 327 SocketIpStatus TcpServerSocket::openProtocol(SocketDescriptor& socketDescriptor) {
88 327 int clientFd = -1;
89 327 int serverFd = socketDescriptor.serverFd;
90
91 // Check for not started yet, may be true in the case of start-up reconnect attempts
92
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 327 times.
327 if (serverFd == -1) {
93 ✗ return SOCK_NOT_STARTED;
94 }
95
96 // TCP requires accepting on the socket to get the client socket file descriptor.
97 327 clientFd = ::accept(serverFd, nullptr, nullptr);
98
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 327 times.
327 if (clientFd < 0) {
99 ✗ return SOCK_FAILED_TO_ACCEPT; // What we have here is a failure to communicate
100 }
101 // Setup client send timeouts
102
1/2
✗ Branch 5 not taken.
✓ Branch 6 taken 327 times.
327 if (IpSocket::setupTimeouts(clientFd) != SOCK_SUCCESS) {
103 ✗ (void)::close(clientFd);
104 ✗ return SOCK_FAILED_TO_SET_SOCKET_OPTIONS;
105 }
106 // Sends to a client that has disconnected must not raise SIGPIPE
107
1/2
✗ Branch 5 not taken.
✓ Branch 6 taken 327 times.
327 if (IpSocket::setupNoSigPipe(clientFd) != SOCK_SUCCESS) {
108 ✗ (void)::close(clientFd);
109 ✗ return SOCK_FAILED_TO_SET_SOCKET_OPTIONS;
110 }
111
112 327 Fw::Logger::log("Accepted client at %s:%hu\n", this->m_ipv4_address, this->m_port);
113 327 socketDescriptor.fd = clientFd;
114 327 return SOCK_SUCCESS;
115 }
116
117 226 FwSignedSizeType TcpServerSocket::sendProtocol(const SocketDescriptor& socketDescriptor,
118 const U8* const data,
119 const FwSizeType size) {
120 return static_cast<FwSignedSizeType>(
121 226 ::send(socketDescriptor.fd, data, static_cast<size_t>(size), SOCKET_IP_SEND_FLAGS | SEND_NO_SIGNAL_FLAGS));
122 }
123
124 551 FwSignedSizeType TcpServerSocket::recvProtocol(const SocketDescriptor& socketDescriptor,
125 U8* const data,
126 const FwSizeType size) {
127 // recv will return 0 if the client has done an orderly shutdown
128 return static_cast<FwSignedSizeType>(
129 551 ::recv(socketDescriptor.fd, data, static_cast<size_t>(size), SOCKET_IP_RECV_FLAGS));
130 }
131
132 } // namespace Drv
133