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 
13 #include <limits>
15 #include <Fw/FPrimeBasicTypes.hpp>
16 #include "Fw/Types/Assert.hpp"
17 #include "Fw/Logger/Logger.hpp"
18 
19 namespace Drv {
20 
21 // ----------------------------------------------------------------------
22 // Construction, initialization, and destruction
23 // ----------------------------------------------------------------------
24 
26  : TcpServerComponentBase(compName) {}
27 
29  const U16 port,
30  const U32 send_timeout_seconds,
31  const U32 send_timeout_microseconds,
32  FwSizeType buffer_size) {
33 
34  // Check that ensures the configured buffer size fits within the limits fixed-width type, U32
35 
36  FW_ASSERT(buffer_size <= std::numeric_limits<U32>::max(), static_cast<FwAssertArgType>(buffer_size));
37  m_allocation_size = buffer_size; // Store the buffer size
38  //
39  (void)m_socket.configure(hostname, port, send_timeout_seconds, send_timeout_microseconds);
40  return startup();
41 }
42 
44 
45 // ----------------------------------------------------------------------
46 // Implementations for socket read task virtual methods
47 // ----------------------------------------------------------------------
48 
50  return m_socket.getListenPort();
51 }
52 
54  return m_socket;
55 }
56 
58  return allocate_out(0, static_cast<U32>(m_allocation_size));
59 }
60 
63  if (status == SOCK_SUCCESS) {
64  recvStatus = ByteStreamStatus::OP_OK;
65  }
66  else if (status == SOCK_NO_DATA_AVAILABLE) {
67  recvStatus = ByteStreamStatus::RECV_NO_DATA;
68  }
69  else {
70  recvStatus = ByteStreamStatus::OTHER_ERROR;
71  }
72  this->recv_out(0, buffer, recvStatus);
73 }
74 
77  this->ready_out(0);
78  }
79 }
80 
82  Os::ScopeLock scopedLock(this->m_lock);
83  return this->m_descriptor.serverFd != -1;
84 }
85 
87  Os::ScopeLock scopedLock(this->m_lock);
89  // Prevent multiple startup attempts
90  if (this->m_descriptor.serverFd == -1) {
91  status = this->m_socket.startup(this->m_descriptor);
92  }
93  return status;
94 }
95 
97  Os::ScopeLock scopedLock(this->m_lock);
98  this->m_socket.terminate(this->m_descriptor);
99  this->m_descriptor.serverFd = -1;
100 }
101 
104  // Keep trying to reconnect until the status is good, told to stop, or reconnection is turned off
105  do {
106  status = this->startup();
107  if (status != SOCK_SUCCESS) {
108  Fw::Logger::log("[WARNING] Failed to listen on port %hu with status %d\n", this->getListenPort(), status);
110  continue;
111  }
112  }
113  while (this->running() && status != SOCK_SUCCESS && this->m_reopen);
114  // If start up was successful then perform normal operations
115  if (this->running() && status == SOCK_SUCCESS) {
116  // Perform the nominal read loop
118  }
119  // Terminate the server
120  this->terminate();
121 }
122 
123 // ----------------------------------------------------------------------
124 // Handler implementations for user-defined typed input ports
125 // ----------------------------------------------------------------------
126 
127 void TcpServerComponentImpl::send_handler(const FwIndexType portNum, Fw::Buffer& fwBuffer) {
128  FW_ASSERT_NO_OVERFLOW(fwBuffer.getSize(), U32);
129  Drv::SocketIpStatus status = this->send(fwBuffer.getData(), static_cast<U32>(fwBuffer.getSize()));
130  Drv::ByteStreamStatus returnStatus;
131  switch (status) {
133  returnStatus = ByteStreamStatus::SEND_RETRY;
134  break;
135  case SOCK_SUCCESS:
136  returnStatus = ByteStreamStatus::OP_OK;
137  break;
138  default:
139  returnStatus = ByteStreamStatus::OTHER_ERROR;
140  break;
141  }
142  // Return the buffer and status to the caller
143  this->sendReturnOut_out(0, fwBuffer, returnStatus);
144 }
145 
146 void TcpServerComponentImpl::recvReturnIn_handler(FwIndexType portNum, Fw::Buffer& fwBuffer) {
147  this->deallocate_out(0, fwBuffer);
148 }
149 
150 } // end namespace Drv
static Status delay(Fw::TimeInterval interval)
delay the current task
Definition: Task.cpp:191
bool m_reopen
Force reopen on disconnect.
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
SocketIpStatus send(const U8 *const data, const U32 size)
send data to the IP socket from the given buffer
IpSocket & getSocketHandler() override
returns a reference to the socket handler
bool isConnected_ready_OutputPort(FwIndexType portNum)
static void log(const char *format,...)
log a formated string with supplied arguments
Definition: Logger.cpp:21
U8 * getData() const
Definition: Buffer.cpp:56
Error occurred, retrying may succeed.
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
SocketIpStatus configure(const char *hostname, 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.
U16 getListenPort()
get the port being listened on
Operation worked as expected.
void connected() override
called when the IPv4 system has been connected
void recv_out(FwIndexType portNum, Fw::Buffer &buffer, const Drv::ByteStreamStatus &status)
Invoke output port recv.
TcpServerComponentImpl(const char *const compName)
construct the TcpServer component.
void sendReturnOut_out(FwIndexType portNum, Fw::Buffer &buffer, const Drv::ByteStreamStatus &status)
Invoke output port sendReturnOut.
Fw::Buffer allocate_out(FwIndexType portNum, FwSizeType size)
Invoke output port allocate.
void terminate()
terminate the server socket
~TcpServerComponentImpl()
Destroy the component.
virtual SocketIpStatus configure(const char *hostname, const U16 port, const U32 send_timeout_seconds, const U32 send_timeout_microseconds)
configure the ip socket with host and transmission timeouts
Definition: IpSocket.cpp:53
FwSizeType getSize() const
Definition: Buffer.cpp:60
U16 getListenPort()
get the port being listened on
PlatformIndexType FwIndexType
locks a mutex within the current scope
Definition: Mutex.hpp:80
#define FW_ASSERT_NO_OVERFLOW(value, T)
Definition: Assert.hpp:49
static const Fw::TimeInterval SOCKET_RETRY_INTERVAL
Definition: IpCfg.hpp:24
virtual void readLoop()
receive off the TCP socket
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
No data available or read operation would block.
Definition: IpSocket.hpp:45
Fw::Buffer getBuffer() override
returns a buffer to fill with data
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
void deallocate_out(FwIndexType portNum, Fw::Buffer &fwBuffer)
Invoke output port deallocate.
void ready_out(FwIndexType portNum)
Invoke output port ready.