F´ Flight Software - C/C++ Documentation
devel
A framework for building embedded system applications to NASA flight quality standards.
|
This package contains utility classes to help interact with standard IPv4 (Berkeley) sockets. These classes implement the core features of IPv4. This includes a tcp server socket (Drv::TcpServerSocket), a tcp client socket (Drv::TcpClient) and a udp socket (Drv::UdpSocket). These are not F´ components, but an F´ component wrapper of each exists: Drv::TcpClientComponent, Drv::TcpServerComponent, and Drv::UdpComponent.
In addition to each individual socket there is a Drv::IpSocket base class containing high-level functions for interacting with sockets generically. Drv::IpSocket delegates protocol specific functions to protocol functions implemented by the children concrete socket classes. i.e. Drv::IpSocket::open delegates to the functions Drv::TcpClientSocket::openProtocol to open up specifically a tcp client socket.
Drv::SocketComponentHelper is a virtual base class that comes with the functionality for setting up a generic reading thread complete with the ability to reconnect to a closed/broken connection. It exists at the component level and serves as a passthrough for requests from the F` component to the IPv4 sockets. This virtual base class is intended to be inherited by an F´ component wrapper that need to support a receive thread such that this functionality need not be redundantly implemented.
Each of these classes is explained in more detail below.
The Drv::IpSocket class represents the external interface to IPv4 socket components. This class provides a top-level interface to IPv4 sockets for connecting, disconnecting, sending, and receiving using the socket. This implements the IPv4 socket protocol as provided by the unix (Berkeley) sockets implementation.
High-level interfaces are provided for the standard functions of: open
, close
, send
, and recv
. FramingProtocol and implementation specific functionality are implemented in derived classes by implementing the pure virtual functions: openProtocol
, sendProtocol
, and recvProtocol
.
In order to use a Drv::IpSocket it must first be configured with a call to the Drv::IpSocket::configure
function. Once configured, it can be opened using Drv::IpSocket::open
. Opening the socket will verify arguments, allocate system resources and form a connection. In server implementations (Drv::TcpServerSocket) the open call will block until a client connection has been made. It is safe to assume that a successfully opened socket is ready to send or receive, however; those calls may detect an error and close the socket in response.
Drv::IpSocket::send
will attempt to send data across the socket. It will retry to transmit data a configured number of times on correctable errors before finally succeeding once all data has been transmitted or failing should the socket send fail. Interrupts and timeouts are the only recoverable errors. Other problems result in an error status and when a remote disconnect is detected Drv::IpSocket::close
is closed to ensure the socket is ready for a subsequent call to Drv::IpSocket::open
.
Drv::IpSocket::recv
will attempt to read data from across the socket. It will block until data is received and in the case that the socket is interrupted without data, it will retry a configurable number of times. Other errors will result in an error status with a specific Drv::IpSocket::close
call issued in the case of detected disconnects.
A call to Drv::IpSocket::close
will specifically shutdown and close the client connection. This has the effect of stopping any blocking reads on the socket, issuing a formal disconnect, and cleaning up the allocated resources. Once called, the Drv::IpSocket should be ready for another call to Drv::IpSocket::open
.
This section will show some example usages of the Drv::IpSocket. In this section it is assumed the initialization is done using a concrete derived class as shown in subsequent sections.
The Drv::TcpClientSocket class represents an IPv4 TCP client. It inherently provides bidirectional communication with a remote server tcp server. TCP communications acknowledge transmissions so the remote server will have received a message or this client will return an error. In other words, dropped packets will cause an error. Usage is as stipulated above and an example instantiation is shown below.
The Drv::TcpServerSocket class represents an IPv4 TCP server. It inherently provides bidirectional communication with a remote tcp client server. The TCP server must be started up such that it may listen for incoming client requests. Since this class is intended to communicate with exactly one client, no listen queue is provided and subsequent connects from clients will be ignored until the primary client has been closed. Like the TCP client packet drops will result in an error.
Note: the Drv::TcpServerSocket::open
call will block until a client connects to the server.
In order to startup the server to listen, the Drv::TcpServerSocket::startup
method should be called. It will create a socket that will listen for incoming connections. Drv::TcpServerSocket::startup
should be called before any Drv::TcpServerSocket::open
calls to ensure that the server is ready for communication. Drv::TcpServerSocket::close
will only close the client connection and does not affect the server from listening for clients, however; it does free up the server to accept a new client.
Drv::TcpServerSocket::shutdown
will close the TCP server from receiving any new clients and effectively releases all resources allocated to the server. Drv::TcpServerSocket::shutdown
implies Drv::TcpServerSocket::close
and client connections will be stopped.
The Drv::UdpSocket class represents an IPv4 UDP sender/receiver. Drv::UdpSocket will provide unidirectional or bidirectional communication using UDP. UDP is typically faster than TCP as it does not acknowledge transmissions. There is no guarantee that a sent packet is received, or even that the remote side is listening.
A UDP socket must be configured for each direction that it will communicate in. This can be done using calls to Drv::UdpSocket::configureSend
and Drv::UdpSocket::configureRecv
. If either call is omitted only a single direction of communication will function. It is erroneous to omit both configuration calls. Calling Drv::UdpSocket::configure
is equivalent to calling Drv::UdpSocket::configureSend
for compatibility with Drv::IpSocket
. Other interaction with the UDP socket is as stipulated with Drv::IpSocket
. Examples of instantiation and configuration are provided below.
The Drv::SocketComponentHelper is intended as a base class used to add in the functionality of an automatically reconnecting receive thread to another class (typically an F´ component) as well as an interface between the component using an IP socket and the IP socket library functions implemented in this folder. In order for this thread to function, the inheritor must implement several methods to provide the necessary interaction of this thread. These functions are described in the next section.
In order to start the receiving thread a call to the Drv::SocketComponentHelper::start
method is performed passing in a name, and all arguments to Os::Task::start
to start the task. An optional parameter, reconnect, will determine if this read task will reconnect to sockets should a disconnect or error occur. Once started the read task will continue until a Drv::SocketComponentHelper::stop
has been called or an error occurred when started without reconnect set to true
. Once the socket stop call has been made, the user should call Drv::SocketComponentHelper::join
in order to wait until the full task has finished. Drv::SocketComponentHelper::stop
will call Drv::SocketComponentHelper::close
on the provided Drv::IpSocket to ensure that any blocking reads exit freeing the thread to completely stop. Normal usage of a Drv::SocketComponentHelper derived class is shown below.
Drv::SocketComponentHelper::open
and Drv::SocketComponentHelper::close
convenience methods are also provided to open and close the provided Drv::IpSocket, although it should be noted that both are called automatically either by the receive thread or on send.
Drv::SocketComponentHelper is used via inheritance. A class that needs to provide receive thread functionality may inherit from this class and implement the three virtual methods to integrate with the thread. These methods are described below and each provides its prototype.
Drv::SocketComponentHelper::getSocketHandler
returns a reference to an existing Drv::IpSocket for this task to interact with for receiving, sending, opening, and closing. This should not be allocated within the function call as it will be used outside the call. The instance is expected to have been configured and started (in the case of servers). The prototype of the function is shown below.
Drv::SocketComponentHelper::getBuffer
returns an Fw::Buffer instance that wraps data for the read call to fill. This can wrap stack memory, or delegate the call to a buffer manager instance. This buffer will be returned via a call to Drv::SocketComponentHelper::sendBuffer
once the received data has filled it. The prototype of the function is shown below.
Drv::SocketComponentHelper::sendBuffer
returns the buffer obtained from Drv::SocketComponentHelper::getBuffer
after it has been filled with data read from the socket. This will come with a status associated with the read but will always be called such that the allocated buffer can be freed when needed.
Further information can be read by referencing the following components.
Drv::TcpClientComponent
: a F´ component wrapper of the tcp client Drv::TcpServerComponent
: a F´ component wrapper of the tcp server Drv::UdpComponent
: a F´ component wrapper of the udp