GCC Code Coverage Report


Directory: Drv/Ip/
File: TcpServerSocket.cpp
Date: 2026-09-03 21:14:31
Exec Total Coverage
Lines: 42 57 73.7%
Functions: 7 7 100.0%
Branches: 13 28 46.4%

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