F´ Flight Software - C/C++ Documentation
A framework for building embedded system applications to NASA flight quality standards.
TcpServerComponentImpl.cpp
Go to the documentation of this file.
1 // ======================================================================
2 // \title TcpServerComponentImpl.cpp
3 // \author mstarch
4 // \brief cpp file for TcpServerComponentImpl component implementation class
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 
14 #include <Fw/FPrimeBasicTypes.hpp>
15 #include <limits>
16 #include "Fw/Logger/Logger.hpp"
17 #include "Fw/Types/Assert.hpp"
18 
19 namespace Drv {
20 
21 // ----------------------------------------------------------------------
22 // Construction, initialization, and destruction
23 // ----------------------------------------------------------------------
24 
26 
27 SocketIpStatus TcpServerComponentImpl::configure(const char* const ipv4_address,
28  const U16 port,
29  const U32 send_timeout_seconds,
30  const U32 send_timeout_microseconds,
31  FwSizeType buffer_size) {
32  m_allocation_size = buffer_size; // Store the buffer size
33  (void)m_socket.configure(ipv4_address, port, send_timeout_seconds, send_timeout_microseconds);
34  return startup();
35 }
36 
38 
39 // ----------------------------------------------------------------------
40 // Implementations for socket read task virtual methods
41 // ----------------------------------------------------------------------
42 
44  return m_socket.getListenPort();
45 }
46 
48  return m_socket;
49 }
50 
52  return allocate_out(0, m_allocation_size);
53 }
54 
56  // A successful receive must have produced a buffer with backing data (size may be zero)
57  FW_ASSERT((status != SOCK_SUCCESS) || (buffer.getData() != nullptr));
59  if (status == SOCK_SUCCESS) {
60  recvStatus = ByteStreamStatus::OP_OK;
61  } else if (status == SOCK_NO_DATA_AVAILABLE) {
62  recvStatus = ByteStreamStatus::RECV_NO_DATA;
63  } else {
64  recvStatus = ByteStreamStatus::OTHER_ERROR;
65  }
66  this->recv_out(0, buffer, recvStatus);
67 }
68 
71  this->ready_out(0);
72  }
73 }
74 
76  Os::ScopeLock scopedLock(this->m_lock);
77  return this->m_descriptor.serverFd != -1;
78 }
79 
81  Os::ScopeLock scopedLock(this->m_lock);
83  // Prevent multiple startup attempts
84  if (this->m_descriptor.serverFd == -1) {
85  status = this->m_socket.startup(this->m_descriptor);
86  }
87  return status;
88 }
89 
91  this->stop();
92  Os::ScopeLock scopedLock(this->m_lock);
93  this->m_socket.terminate(this->m_descriptor);
94  this->m_descriptor.serverFd = -1;
95 }
96 
99  // Keep trying to reconnect until the status is good, told to stop, or reconnection is turned off
100  // @non-terminating@: retry loop bounded by stop request
101  do {
102  status = this->startup();
103  if (status != SOCK_SUCCESS) {
104  Fw::Logger::log("[WARNING] Failed to listen on port %hu with status %d\n", this->getListenPort(), status);
106  continue;
107  }
108  } while (this->running() && status != SOCK_SUCCESS && this->getAutomaticOpen());
109  // Loop exit implies startup succeeded, a stop was requested, or reopen is disabled
110  FW_ASSERT(status == SOCK_SUCCESS || (not this->running()) || (not this->getAutomaticOpen()),
111  static_cast<FwAssertArgType>(status));
112  // If start up was successful then perform normal operations
113  if (this->running() && status == SOCK_SUCCESS) {
114  // Perform the nominal read loop
116  }
117  // Terminate the server
118  this->terminate();
119 }
120 
121 // ----------------------------------------------------------------------
122 // Handler implementations for user-defined typed input ports
123 // ----------------------------------------------------------------------
124 
125 Drv::ByteStreamStatus TcpServerComponentImpl::send_handler(const FwIndexType portNum, Fw::Buffer& fwBuffer) {
126  Drv::SocketIpStatus status = this->send(fwBuffer.getData(), fwBuffer.getSize());
127  Drv::ByteStreamStatus returnStatus;
128  switch (status) {
130  returnStatus = ByteStreamStatus::SEND_RETRY;
131  break;
132  case SOCK_SUCCESS:
133  returnStatus = ByteStreamStatus::OP_OK;
134  break;
135  default:
136  returnStatus = ByteStreamStatus::OTHER_ERROR;
137  break;
138  }
139  return returnStatus;
140 }
141 
142 void TcpServerComponentImpl::recvReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) {
143  this->deallocate_out(0, fwBuffer);
144 }
145 
146 } // end namespace Drv
void recv_out(FwIndexType portNum, Fw::Buffer &buffer, const Drv::ByteStreamStatus &status) const
Invoke output port recv.
Auto-generated base for TcpServer component.
Interrupted status for retries.
Definition: IpSocket.hpp:36
SocketIpStatus startup(SocketDescriptor &socketDescriptor)
Opens the server socket and listens, does not block.
void sendBuffer(Fw::Buffer buffer, SocketIpStatus status) override
sends a buffer to be filled with data
PlatformSizeType FwSizeType
IpSocket & getSocketHandler() override
returns a reference to the socket handler
bool isConnected_ready_OutputPort(FwIndexType portNum) const
SocketIpStatus send(const U8 *const data, const FwSizeType size)
send data to the IP socket from the given buffer
virtual SocketIpStatus configure(const char *const ipv4_address, const U16 port, const U32 send_timeout_seconds, const U32 send_timeout_microseconds)
configure the ip socket with an IPv4 address and transmission timeouts
Definition: IpSocket.cpp:51
static void log(const char *format,...)
log a formated string with supplied arguments
Definition: Logger.cpp:21
U8 * getData() const
Definition: Buffer.cpp:82
Error occurred, retrying may succeed.
SocketIpStatus configure(const char *const ipv4_address, const U16 port, const U32 send_timeout_seconds=SOCKET_SEND_TIMEOUT_SECONDS, const U32 send_timeout_microseconds=SOCKET_SEND_TIMEOUT_MICROSECONDS, FwSizeType buffer_size=1024)
Configures the TcpServer settings but does not open the connection.
Receive worked, but there was no data.
void readLoop() override
read from the socket, overridden to start and terminate the server socket
Status returned by the send call.
Socket operation successful.
Definition: IpSocket.hpp:30
bool getAutomaticOpen()
get socket automatically open connections status
U16 getListenPort()
get the port being listened on
Operation worked as expected.
void connected() override
called when the IPv4 system has been connected
TcpServerComponentImpl(const char *const compName)
construct the TcpServer component.
void terminate()
stop the read task and terminate the server socket
~TcpServerComponentImpl()
Destroy the component.
FwSizeType getSize() const
Definition: Buffer.cpp:90
U16 getListenPort()
get the port being listened on
void stop()
stop the socket read task and shut down the associated socket.
void deallocate_out(FwIndexType portNum, Fw::Buffer &fwBuffer) const
Invoke output port deallocate.
PlatformIndexType FwIndexType
locks a mutex within the current scope
Definition: Mutex.hpp:80
static const Fw::TimeInterval SOCKET_RETRY_INTERVAL
Definition: IpCfg.hpp:40
virtual void readLoop()
receive off the TCP socket
static Status delay(const Fw::TimeInterval &interval)
delay the current task
Definition: Task.cpp:204
SocketIpStatus
Status enumeration for socket return values.
Definition: IpSocket.hpp:29
void terminate(const SocketDescriptor &socketDescriptor)
shut down and 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
No data available or read operation would block.
Definition: IpSocket.hpp:45
Fw::Buffer getBuffer() override
returns a buffer to fill with data
void ready_out(FwIndexType portNum) const
Invoke output port ready.
SocketIpStatus startup()
startup the server socket for communications
#define FW_ASSERT(...)
Definition: Assert.hpp:14
int serverFd
Used for server sockets to track the listening file descriptor.
Definition: IpSocket.hpp:23
bool running()
is the read loop running
Fw::Buffer allocate_out(FwIndexType portNum, FwSizeType size) const
Invoke output port allocate.