F´ Flight Software - C/C++ Documentation
A framework for building embedded system applications to NASA flight quality standards.
TcpServerSocket.cpp
Go to the documentation of this file.
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 // ======================================================================
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 
42 
44  U16 port = this->m_port;
45  return port;
46 }
47 
49  int serverFd = -1;
50  struct sockaddr_in address;
51  // Acquire a socket, or return error
52  if ((serverFd = ::socket(AF_INET, SOCK_STREAM, 0)) == -1) {
54  }
55  // Set up the address port and name
56  address.sin_family = AF_INET;
57  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  if (IpSocket::addressToIp4(this->m_ipv4_address, &(address.sin_addr)) != SOCK_SUCCESS) {
65  ::close(serverFd);
67  };
68 
69  if (IpSocket::setupSocketOptions(serverFd) != SOCK_SUCCESS) {
70  ::close(serverFd);
72  }
73 
74  // TCP requires bind to an address to the socket
75  if (::bind(serverFd, reinterpret_cast<struct sockaddr*>(&address), sizeof(address)) < 0) {
76  ::close(serverFd);
77  return SOCK_FAILED_TO_BIND;
78  }
79 
80  socklen_t size = sizeof(address);
81  if (::getsockname(serverFd, reinterpret_cast<struct sockaddr*>(&address), &size) == -1) {
82  ::close(serverFd);
84  }
85  // TCP requires listening on the socket. Since we only expect a single client, set the TCP backlog (second argument)
86  // to 1 to prevent queuing of multiple clients.
87  if (::listen(serverFd, 1) < 0) {
88  ::close(serverFd);
89  return SOCK_FAILED_TO_LISTEN; // What we have here is a failure to communicate
90  }
91  Fw::Logger::log("Listening for single client at %s:%hu\n", this->m_ipv4_address, this->m_port);
92  FW_ASSERT(serverFd != -1);
93  socketDescriptor.serverFd = serverFd;
94  this->m_port = ntohs(address.sin_port);
95  return SOCK_SUCCESS;
96 }
97 
98 void TcpServerSocket::terminate(const SocketDescriptor& socketDescriptor) {
99  (void)::shutdown(socketDescriptor.serverFd, SHUT_RDWR); // Shutdown first to avoid hanging "accept" calls
100  (void)::close(socketDescriptor.serverFd);
101 }
102 
104  int clientFd = -1;
105  int serverFd = socketDescriptor.serverFd;
106 
107  // Check for not started yet, may be true in the case of start-up reconnect attempts
108  if (serverFd == -1) {
109  return SOCK_NOT_STARTED;
110  }
111 
112  // TCP requires accepting on the socket to get the client socket file descriptor.
113  clientFd = ::accept(serverFd, nullptr, nullptr);
114  if (clientFd < 0) {
115  return SOCK_FAILED_TO_ACCEPT; // What we have here is a failure to communicate
116  }
117  // Setup client send timeouts
118  if (IpSocket::setupTimeouts(clientFd) != SOCK_SUCCESS) {
119  ::close(clientFd);
121  }
122 
123  Fw::Logger::log("Accepted client at %s:%hu\n", this->m_ipv4_address, this->m_port);
124  socketDescriptor.fd = clientFd;
125  return SOCK_SUCCESS;
126 }
127 
129  const U8* const data,
130  const FwSizeType size) {
131  return static_cast<FwSignedSizeType>(
132  ::send(socketDescriptor.fd, data, static_cast<size_t>(size), SOCKET_IP_SEND_FLAGS));
133 }
134 
136  U8* const data,
137  const FwSizeType size) {
138  // recv will return 0 if the client has done an orderly shutdown
139  return static_cast<FwSignedSizeType>(
140  ::recv(socketDescriptor.fd, data, static_cast<size_t>(size), SOCKET_IP_RECV_FLAGS));
141 }
142 
143 } // namespace Drv
Socket open failed.
Definition: IpSocket.hpp:31
SocketIpStatus startup(SocketDescriptor &socketDescriptor)
Opens the server socket and listens, does not block.
Failed to configure socket.
Definition: IpSocket.hpp:35
PlatformSizeType FwSizeType
SocketIpStatus recv(const SocketDescriptor &fd, U8 *const data, FwSizeType &size)
receive data from the IP socket from the given buffer
Definition: IpSocket.cpp:179
FwSignedSizeType sendProtocol(const SocketDescriptor &socketDescriptor, const U8 *const data, const FwSizeType size) override
Protocol specific implementation of send. Called directly with retry from send.
SocketIpStatus setupTimeouts(int socketFd)
setup the socket timeout properties of the opened outgoing socket
Definition: IpSocket.cpp:75
static void log(const char *format,...)
log a formated string with supplied arguments
Definition: Logger.cpp:21
static SocketIpStatus addressToIp4(const char *const ipv4_address, void *const out)
converts a given IPv4 address in dotted-quad form "x.x.x.x" to a network-order in_addr structure...
Definition: IpSocket.cpp:92
int fd
Used for all sockets to track the communication file descriptor.
Definition: IpSocket.hpp:22
PlatformSignedSizeType FwSignedSizeType
virtual SocketIpStatus send(const SocketDescriptor &socketDescriptor, const U8 *const data, const FwSizeType size)
send data out the IP socket from the given buffer
Definition: IpSocket.cpp:144
Bad IP address supplied.
Definition: IpSocket.hpp:33
void shutdown(const SocketDescriptor &socketDescriptor)
shutdown the socket
Definition: IpSocket.cpp:123
Failed to listen on socket.
Definition: IpSocket.hpp:40
U16 m_port
IP address port used.
Definition: IpSocket.hpp:250
Failed to accept connection.
Definition: IpSocket.hpp:41
Socket operation successful.
Definition: IpSocket.hpp:30
U16 getListenPort()
get the port being listened on
SocketIpStatus setupSocketOptions(int socketFd)
setup the socket options of the input socket as defined in IpCfg.hpp
Definition: IpSocket.cpp:229
TcpServerSocket()
Constructor for client socket tcp implementation.
Failed to read back port from connection.
Definition: IpSocket.hpp:44
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:53
char m_ipv4_address[SOCKET_MAX_IPV4_ADDRESS_SIZE]
IPv4 address (dotted-quad "x.x.x.x")
Definition: IpSocket.hpp:251
void close(const SocketDescriptor &socketDescriptor)
closes the socket
Definition: IpSocket.cpp:119
SocketIpStatus
Status enumeration for socket return values.
Definition: IpSocket.hpp:29
void terminate(const SocketDescriptor &socketDescriptor)
close the server socket created by the startup call
Socket has not been started.
Definition: IpSocket.hpp:43
Helper base-class for setting up Berkeley sockets.
Definition: IpSocket.hpp:57
Failed to bind to socket.
Definition: IpSocket.hpp:39
SocketIpStatus openProtocol(SocketDescriptor &socketDescriptor) override
Tcp specific implementation for opening a client socket connected to this server. ...
#define FW_ASSERT(...)
Definition: Assert.hpp:14
FwSignedSizeType recvProtocol(const SocketDescriptor &socketDescriptor, U8 *const data, const FwSizeType size) override
Protocol specific implementation of recv. Called directly with error handling from recv...
int serverFd
Used for server sockets to track the listening file descriptor.
Definition: IpSocket.hpp:23