F´ Flight Software - C/C++ Documentation  devel
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/Logger/Logger.hpp>
14 #include <Fw/Types/Assert.hpp>
15 #include <FpConfig.hpp>
16 
17 #ifdef TGT_OS_TYPE_VXWORKS
18  #include <socket.h>
19  #include <inetLib.h>
20  #include <fioLib.h>
21  #include <hostLib.h>
22  #include <ioLib.h>
23  #include <vxWorks.h>
24  #include <sockLib.h>
25  #include <taskLib.h>
26  #include <sysLib.h>
27  #include <errnoLib.h>
28  #include <cstring>
29 #elif defined TGT_OS_TYPE_LINUX || TGT_OS_TYPE_DARWIN
30  #include <sys/socket.h>
31  #include <unistd.h>
32  #include <arpa/inet.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  PlatformIntType 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  // First IP address to socket sin_addr
64  if (IpSocket::addressToIp4(m_hostname, &(address.sin_addr)) != SOCK_SUCCESS) {
65  ::close(serverFd);
67  };
68 
69  // TCP requires bind to an address to the socket
70  if (::bind(serverFd, reinterpret_cast<struct sockaddr*>(&address), sizeof(address)) < 0) {
71  ::close(serverFd);
72  return SOCK_FAILED_TO_BIND;
73  }
74 
75  socklen_t size = sizeof(address);
76  if (::getsockname(serverFd, reinterpret_cast<struct sockaddr *>(&address), &size) == -1) {
77  ::close(serverFd);
79  }
80  // TCP requires listening on the socket. Since we only expect a single client, set the TCP backlog (second argument) to 1 to prevent queuing of multiple clients.
81  if (::listen(serverFd, 1) < 0) {
82  ::close(serverFd);
83  return SOCK_FAILED_TO_LISTEN; // What we have here is a failure to communicate
84  }
85  Fw::Logger::log("Listening for single client at %s:%hu\n", m_hostname, m_port);
86  FW_ASSERT(serverFd != -1);
87  socketDescriptor.serverFd = serverFd;
88  this->m_port = ntohs(address.sin_port);
89  return SOCK_SUCCESS;
90 }
91 
92 void TcpServerSocket::terminate(const SocketDescriptor& socketDescriptor) {
93  (void)::close(socketDescriptor.serverFd);
94 }
95 
97  PlatformIntType clientFd = -1;
98  PlatformIntType serverFd = socketDescriptor.serverFd;
99 
100  // Check for not started yet, may be true in the case of start-up reconnect attempts
101  if (serverFd == -1) {
102  return SOCK_NOT_STARTED;
103  }
104 
105  // TCP requires accepting on the socket to get the client socket file descriptor.
106  clientFd = ::accept(serverFd, nullptr, nullptr);
107  if (clientFd < 0) {
108  return SOCK_FAILED_TO_ACCEPT; // What we have here is a failure to communicate
109  }
110  // Setup client send timeouts
111  if (IpSocket::setupTimeouts(clientFd) != SOCK_SUCCESS) {
112  ::close(clientFd);
114  }
115 
116  Fw::Logger::log("Accepted client at %s:%hu\n", m_hostname, m_port);
117  socketDescriptor.fd = clientFd;
118  return SOCK_SUCCESS;
119 }
120 
121 I32 TcpServerSocket::sendProtocol(const SocketDescriptor& socketDescriptor, const U8* const data, const U32 size) {
122  return static_cast<I32>(::send(socketDescriptor.fd, data, size, SOCKET_IP_SEND_FLAGS));
123 }
124 
125 I32 TcpServerSocket::recvProtocol(const SocketDescriptor& socketDescriptor, U8* const data, const U32 size) {
126  I32 size_buf;
127  // recv will return 0 if the client has done an orderly shutdown
128  size_buf = static_cast<I32>(::recv(socketDescriptor.fd, data, size, SOCKET_IP_RECV_FLAGS));
129  return size_buf;
130 }
131 
132 } // namespace Drv
#define FW_ASSERT(...)
Definition: Assert.hpp:14
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:30
int PlatformIntType
DefaultTypes.hpp provides fallback defaults for the platform types.
C++-compatible configuration header for fprime configuration.
@ SOCKET_IP_RECV_FLAGS
Definition: IpCfg.hpp:20
@ SOCKET_IP_SEND_FLAGS
Definition: IpCfg.hpp:19
Helper base-class for setting up Berkeley sockets.
Definition: IpSocket.hpp:55
U16 m_port
IP address port used.
Definition: IpSocket.hpp:210
char m_hostname[SOCKET_MAX_HOSTNAME_SIZE]
Hostname to supply.
Definition: IpSocket.hpp:211
SocketIpStatus setupTimeouts(PlatformIntType socketFd)
setup the socket timeout properties of the opened outgoing socket
Definition: IpSocket.cpp:68
static SocketIpStatus addressToIp4(const char *address, void *ip4)
converts a given address in dot form x.x.x.x to an ip address. ONLY works for IPv4.
Definition: IpSocket.cpp:85
SocketIpStatus send(const SocketDescriptor &socketDescriptor, const U8 *const data, const U32 size)
send data out the IP socket from the given buffer
Definition: IpSocket.cpp:131
SocketIpStatus recv(const SocketDescriptor &fd, U8 *const data, U32 &size)
receive data from the IP socket from the given buffer
Definition: IpSocket.cpp:163
void close(const SocketDescriptor &socketDescriptor)
closes the socket
Definition: IpSocket.cpp:106
TcpServerSocket()
Constructor for client socket tcp implementation.
SocketIpStatus startup(SocketDescriptor &socketDescriptor)
Opens the server socket and listens, does not block.
SocketIpStatus openProtocol(SocketDescriptor &socketDescriptor) override
Tcp specific implementation for opening a client socket connected to this server.
I32 sendProtocol(const SocketDescriptor &socketDescriptor, const U8 *const data, const U32 size) override
Protocol specific implementation of send. Called directly with retry from send.
I32 recvProtocol(const SocketDescriptor &socketDescriptor, U8 *const data, const U32 size) override
Protocol specific implementation of recv. Called directly with error handling from recv.
U16 getListenPort()
get the port being listened on
void terminate(const SocketDescriptor &socketDescriptor)
close the server socket created by the startup call
static void log(const char *format,...)
log a formated string with supplied arguments
Definition: Logger.cpp:21
SocketIpStatus
Status enumeration for socket return values.
Definition: IpSocket.hpp:29
@ SOCK_INVALID_IP_ADDRESS
Bad IP address supplied.
Definition: IpSocket.hpp:33
@ SOCK_FAILED_TO_ACCEPT
Failed to accept connection.
Definition: IpSocket.hpp:41
@ SOCK_SUCCESS
Socket operation successful.
Definition: IpSocket.hpp:30
@ SOCK_FAILED_TO_BIND
Failed to bind to socket.
Definition: IpSocket.hpp:39
@ SOCK_FAILED_TO_SET_SOCKET_OPTIONS
Failed to configure socket.
Definition: IpSocket.hpp:35
@ SOCK_FAILED_TO_GET_SOCKET
Socket open failed.
Definition: IpSocket.hpp:31
@ SOCK_FAILED_TO_LISTEN
Failed to listen on socket.
Definition: IpSocket.hpp:40
@ SOCK_FAILED_TO_READ_BACK_PORT
Failed to read back port from connection.
Definition: IpSocket.hpp:44
@ SOCK_NOT_STARTED
Socket has not been started.
Definition: IpSocket.hpp:43
PlatformIntType serverFd
Used for server sockets to track the listening file descriptor.
Definition: IpSocket.hpp:23
PlatformIntType fd
Used for all sockets to track the communication file descriptor.
Definition: IpSocket.hpp:22