GCC Code Coverage Report


Directory: ./
File: TcpServerSocket.cpp
Date: 2026-11-03 22:10:30
Exec Total Coverage
Lines: 0 59 0.0%
Functions: 0 7 0.0%
Branches: 0 30 0.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 ✗ TcpServerSocket::TcpServerSocket() : IpSocket() {}
22
23 ✗ U16 TcpServerSocket::getListenPort() {
24 ✗ U16 port = this->m_port;
25 ✗ return port;
26 }
27
28 ✗ SocketIpStatus TcpServerSocket::startup(SocketDescriptor& socketDescriptor) {
29 struct sockaddr_in address;
30 // Acquire a socket, or return error
31 ✗ int serverFd = ::socket(AF_INET, SOCK_STREAM, 0);
32 ✗ if (serverFd == -1) {
33 ✗ return SOCK_FAILED_TO_GET_SOCKET;
34 }
35 // Set up the address port and name
36 ✗ address.sin_family = AF_INET;
37 ✗ 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 ✗ const SocketIpStatus addressStatus = IpSocket::addressToIp4(this->m_ipv4_address, &(address.sin_addr));
45 ✗ if (addressStatus != SOCK_SUCCESS) {
46 ✗ (void)::close(serverFd);
47 ✗ return SOCK_INVALID_IP_ADDRESS;
48 };
49
50 ✗ 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 ✗ if (::bind(serverFd, reinterpret_cast<struct sockaddr*>(&address), sizeof(address)) < 0) {
57 ✗ (void)::close(serverFd);
58 ✗ return SOCK_FAILED_TO_BIND;
59 }
60
61 ✗ socklen_t size = sizeof(address);
62 ✗ const int socknameStatus = ::getsockname(serverFd, reinterpret_cast<struct sockaddr*>(&address), &size);
63 ✗ 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 ✗ 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 ✗ Fw::Logger::log("Listening for single client at %s:%hu\n", this->m_ipv4_address, this->m_port);
74 ✗ FW_ASSERT(serverFd != -1);
75 ✗ socketDescriptor.serverFd = serverFd;
76 ✗ this->m_port = ntohs(address.sin_port);
77 ✗ return SOCK_SUCCESS;
78 }
79
80 ✗ void TcpServerSocket::terminate(const SocketDescriptor& socketDescriptor) {
81 ✗ if (socketDescriptor.serverFd >= 0) {
82 ✗ (void)::shutdown(socketDescriptor.serverFd, SHUT_RDWR); // Shutdown first to avoid hanging "accept" calls
83 ✗ (void)::close(socketDescriptor.serverFd);
84 }
85 ✗ }
86
87 ✗ SocketIpStatus TcpServerSocket::openProtocol(SocketDescriptor& socketDescriptor) {
88 ✗ int clientFd = -1;
89 ✗ int serverFd = socketDescriptor.serverFd;
90
91 // Check for not started yet, may be true in the case of start-up reconnect attempts
92 ✗ 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 ✗ clientFd = ::accept(serverFd, nullptr, nullptr);
98 ✗ 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 ✗ 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 ✗ if (IpSocket::setupNoSigPipe(clientFd) != SOCK_SUCCESS) {
108 ✗ (void)::close(clientFd);
109 ✗ return SOCK_FAILED_TO_SET_SOCKET_OPTIONS;
110 }
111
112 ✗ Fw::Logger::log("Accepted client at %s:%hu\n", this->m_ipv4_address, this->m_port);
113 ✗ socketDescriptor.fd = clientFd;
114 ✗ return SOCK_SUCCESS;
115 }
116
117 ✗ FwSignedSizeType TcpServerSocket::sendProtocol(const SocketDescriptor& socketDescriptor,
118 const U8* const data,
119 const FwSizeType size) {
120 return static_cast<FwSignedSizeType>(
121 ✗ ::send(socketDescriptor.fd, data, static_cast<size_t>(size), SOCKET_IP_SEND_FLAGS | SEND_NO_SIGNAL_FLAGS));
122 }
123
124 ✗ 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 ✗ ::recv(socketDescriptor.fd, data, static_cast<size_t>(size), SOCKET_IP_RECV_FLAGS));
130 }
131
132 } // namespace Drv
133