Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/format-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ jobs:
- name: "Check C++ Formatting"
env:
CHECKED_DIRS: >-
Drv
Fw/Buffer
Fw/Cmd
Fw/Com
Expand Down
45 changes: 23 additions & 22 deletions Drv/Ip/IpSocket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,55 +9,56 @@
// acknowledged.
//
// ======================================================================
#include <cstring>
#include <sys/time.h>
#include <Drv/Ip/IpSocket.hpp>
#include <Fw/Types/Assert.hpp>
#include <Fw/FPrimeBasicTypes.hpp>
#include <Fw/Types/Assert.hpp>
#include <Fw/Types/StringUtils.hpp>
#include <sys/time.h>
#include <cstring>

// This implementation has primarily implemented to isolate
// the socket interface from the F' Fw::Buffer class.
// There is a macro in VxWorks (m_data) that collides with
// the m_data member in Fw::Buffer.

#ifdef TGT_OS_TYPE_VXWORKS
#include <socket.h>
#include <inetLib.h>
#include <errnoLib.h>
#include <fioLib.h>
#include <hostLib.h>
#include <inetLib.h>
#include <ioLib.h>
#include <vxWorks.h>
#include <sockLib.h>
#include <fioLib.h>
#include <taskLib.h>
#include <socket.h>
#include <sysLib.h>
#include <errnoLib.h>
#include <taskLib.h>
#include <vxWorks.h>
#include <cstring>
#elif defined TGT_OS_TYPE_LINUX || TGT_OS_TYPE_DARWIN
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cerrno>
#include <arpa/inet.h>
#else
#error OS not supported for IP Socket Communications
#endif


namespace Drv {

IpSocket::IpSocket() : m_timeoutSeconds(0), m_timeoutMicroseconds(0), m_port(0) {
::memset(m_hostname, 0, sizeof(m_hostname));
}

SocketIpStatus IpSocket::configure(const char* const hostname, const U16 port, const U32 timeout_seconds, const U32 timeout_microseconds) {
SocketIpStatus IpSocket::configure(const char* const hostname,

Check notice

Code scanning / CodeQL

Use of basic integral type Note

hostname uses the basic integral type char rather than a typedef with size and signedness.

Check notice

Code scanning / CodeQL

Long function without assertion Note

All functions of more than 10 lines should have at least one assertion.
const U16 port,
const U32 timeout_seconds,
const U32 timeout_microseconds) {
FW_ASSERT(timeout_microseconds < 1000000, static_cast<FwAssertArgType>(timeout_microseconds));
FW_ASSERT(this->isValidPort(port), static_cast<FwAssertArgType>(port));
FW_ASSERT(hostname != nullptr);
this->m_timeoutSeconds = timeout_seconds;
this->m_timeoutMicroseconds = timeout_microseconds;
this->m_port = port;
(void) Fw::StringUtils::string_copy(this->m_hostname, hostname, static_cast<FwSizeType>(SOCKET_MAX_HOSTNAME_SIZE));
(void)Fw::StringUtils::string_copy(this->m_hostname, hostname, static_cast<FwSizeType>(SOCKET_MAX_HOSTNAME_SIZE));
return SOCK_SUCCESS;
}

Expand All @@ -75,7 +76,7 @@
timeout.tv_sec = static_cast<time_t>(this->m_timeoutSeconds);
timeout.tv_usec = static_cast<suseconds_t>(this->m_timeoutMicroseconds);
// set socket write to timeout after 1 sec
if (setsockopt(socketFd, SOL_SOCKET, SO_SNDTIMEO, reinterpret_cast<char *>(&timeout), sizeof(timeout)) < 0) {
if (setsockopt(socketFd, SOL_SOCKET, SO_SNDTIMEO, reinterpret_cast<char*>(&timeout), sizeof(timeout)) < 0) {
return SOCK_FAILED_TO_SET_SOCKET_OPTIONS;
}
#endif
Expand Down Expand Up @@ -132,9 +133,9 @@
FW_ASSERT(socketDescriptor.fd != -1, static_cast<FwAssertArgType>(socketDescriptor.fd));
FW_ASSERT(data != nullptr);
FW_ASSERT(size > 0);

U32 total = 0;
I32 sent = 0;
I32 sent = 0;
// Attempt to send out data and retry as necessary
for (U32 i = 0; (i < SOCKET_MAX_ITERATIONS) && (total < size); i++) {
errno = 0;
Expand Down Expand Up @@ -165,12 +166,12 @@
}

SocketIpStatus IpSocket::recv(const SocketDescriptor& socketDescriptor, U8* data, U32& req_read) {
//TODO: Uncomment FW_ASSERT for socketDescriptor.fd once we fix TcpClientTester to not pass in uninitialized socketDescriptor
// FW_ASSERT(socketDescriptor.fd != -1, static_cast<FwAssertArgType>(socketDescriptor.fd));
// TODO: Uncomment FW_ASSERT for socketDescriptor.fd once we fix TcpClientTester to not pass in uninitialized
// socketDescriptor
// FW_ASSERT(socketDescriptor.fd != -1, static_cast<FwAssertArgType>(socketDescriptor.fd));
FW_ASSERT(data != nullptr);


I32 bytes_received_or_status; // Stores the return value from recvProtocol
I32 bytes_received_or_status; // Stores the return value from recvProtocol

// Loop primarily for EINTR. Other conditions should lead to an earlier exit.
for (U32 i = 0; i < SOCKET_MAX_ITERATIONS; i++) {
Expand All @@ -187,15 +188,15 @@
// Handle zero return based on protocol-specific behavior
req_read = 0;
return this->handleZeroReturn();
} else { // bytes_received_or_status == -1, an error occurred
} else { // bytes_received_or_status == -1, an error occurred
if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
// Non-blocking socket would block, or SO_RCVTIMEO timeout occurred.
req_read = 0;
return SOCK_NO_DATA_AVAILABLE;
} else if ((errno == ECONNRESET) || (errno == EBADF)) {
// Connection reset or bad file descriptor.
req_read = 0;
return SOCK_DISCONNECTED; // Or a more specific error like SOCK_READ_ERROR
return SOCK_DISCONNECTED; // Or a more specific error like SOCK_READ_ERROR
} else {
// Other socket read error.
req_read = 0;
Expand Down
16 changes: 9 additions & 7 deletions Drv/Ip/IpSocket.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@
#define DRV_IP_IPHELPER_HPP_

#include <Fw/FPrimeBasicTypes.hpp>
#include <config/IpCfg.hpp>
#include <Os/Mutex.hpp>
#include <config/IpCfg.hpp>

namespace Drv {

struct SocketDescriptor final {
int fd = -1; //!< Used for all sockets to track the communication file descriptor
int serverFd = -1; //!< Used for server sockets to track the listening file descriptor
int fd = -1; //!< Used for all sockets to track the communication file descriptor

Check notice

Code scanning / CodeQL

Use of basic integral type Note

fd uses the basic integral type int rather than a typedef with size and signedness.
int serverFd = -1; //!< Used for server sockets to track the listening file descriptor

Check notice

Code scanning / CodeQL

Use of basic integral type Note

serverFd uses the basic integral type int rather than a typedef with size and signedness.
};

/**
Expand Down Expand Up @@ -57,7 +57,7 @@
class IpSocket {
public:
IpSocket();
virtual ~IpSocket(){};
virtual ~IpSocket() {};

Check notice

Code scanning / CodeQL

More than one statement per line Note

This line contains 2 statements; only one is allowed.
/**
* \brief configure the ip socket with host and transmission timeouts
*
Expand All @@ -76,7 +76,9 @@
* \param send_timeout_microseconds: send timeout microseconds portion. Must be less than 1000000
* \return status of configure
*/
virtual SocketIpStatus configure(const char* hostname, const U16 port, const U32 send_timeout_seconds,
virtual SocketIpStatus configure(const char* hostname,
const U16 port,
const U32 send_timeout_seconds,
const U32 send_timeout_microseconds);

/**
Expand Down Expand Up @@ -173,7 +175,7 @@
* \brief setup the socket timeout properties of the opened outgoing socket
* \param socketDescriptor: socket descriptor to setup
* \return status of timeout setup
*/
*/
SocketIpStatus setupTimeouts(int socketFd);

/**
Expand Down Expand Up @@ -220,7 +222,7 @@

U32 m_timeoutSeconds;
U32 m_timeoutMicroseconds;
U16 m_port; //!< IP address port used
U16 m_port; //!< IP address port used
char m_hostname[SOCKET_MAX_HOSTNAME_SIZE]; //!< Hostname to supply
};
} // namespace Drv
Expand Down
19 changes: 9 additions & 10 deletions Drv/Ip/SocketComponentHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@

SocketComponentHelper::~SocketComponentHelper() {}

void SocketComponentHelper::start(const Fw::StringBase &name,
void SocketComponentHelper::start(const Fw::StringBase& name,

Check notice

Code scanning / CodeQL

Long function without assertion Note

All functions of more than 10 lines should have at least one assertion.
const FwTaskPriorityType priority,
const Os::Task::ParamType stack,
const Os::Task::ParamType cpuAffinity) {
FW_ASSERT(m_task.getState() == Os::Task::State::NOT_STARTED); // It is a coding error to start this task multiple times
FW_ASSERT(m_task.getState() ==
Os::Task::State::NOT_STARTED); // It is a coding error to start this task multiple times
this->m_stop = false;
// Note: the first step is for the IP socket to open the port
Os::Task::Arguments arguments(name, SocketComponentHelper::readTask, this, priority, stack, cpuAffinity);
Expand All @@ -45,7 +46,6 @@
} else {
local_open = OpenState::SKIP;
}

}
if (local_open == OpenState::OPENING) {
FW_ASSERT(this->m_descriptor.fd == -1); // Ensure we are not opening an opened socket
Expand Down Expand Up @@ -111,7 +111,7 @@
if (descriptor.fd == -1) {
status = this->reopen();
// if reopen wasn't successful, pass the that up to the caller
if(status != SOCK_SUCCESS) {
if (status != SOCK_SUCCESS) {
return status;
}
// Refresh local copy after reopen
Expand Down Expand Up @@ -157,7 +157,7 @@
return running;
}

SocketIpStatus SocketComponentHelper::recv(U8* data, U32 &size) {
SocketIpStatus SocketComponentHelper::recv(U8* data, U32& size) {
SocketIpStatus status = SOCK_SUCCESS;
// Check for previously disconnected socket
this->m_lock.lock();
Expand Down Expand Up @@ -199,10 +199,9 @@
U32 size = static_cast<U32>(buffer.getSize());
// recv blocks, so it may have been a while since its done an isOpened check
status = this->recv(data, size);
if ((status != SOCK_SUCCESS) && (status != SOCK_INTERRUPTED_TRY_AGAIN) && (status != SOCK_NO_DATA_AVAILABLE)) {
Fw::Logger::log("[WARNING] Failed to recv from port with status %d and errno %d\n",
status,
errno);
if ((status != SOCK_SUCCESS) && (status != SOCK_INTERRUPTED_TRY_AGAIN) &&
(status != SOCK_NO_DATA_AVAILABLE)) {
Fw::Logger::log("[WARNING] Failed to recv from port with status %d and errno %d\n", status, errno);
this->close();
buffer.setSize(0);
} else {
Expand All @@ -215,7 +214,7 @@
// This will loop until stopped. If auto-open is disabled, this will break when reopen returns disabled status
while (this->running());
// Close the socket
this->close(); // Close the port entirely
this->close(); // Close the port entirely
}

void SocketComponentHelper::readTask(void* pointer) {
Expand Down
40 changes: 18 additions & 22 deletions Drv/Ip/SocketComponentHelper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
#ifndef DRV_SocketComponentHelper_HPP
#define DRV_SocketComponentHelper_HPP

#include <Fw/Buffer/Buffer.hpp>
#include <Drv/Ip/IpSocket.hpp>
#include <Os/Task.hpp>
#include <Fw/Buffer/Buffer.hpp>
#include <Os/Mutex.hpp>
#include <Os/Task.hpp>

namespace Drv {
/**
Expand All @@ -27,12 +27,7 @@ namespace Drv {
*/
class SocketComponentHelper {
public:
enum OpenState{
NOT_OPEN,
OPENING,
OPEN,
SKIP
};
enum OpenState { NOT_OPEN, OPENING, OPEN, SKIP };
/**
* \brief constructs the socket read task
*/
Expand All @@ -52,11 +47,12 @@ class SocketComponentHelper {
* default behavior is to automatically open connections.
*
* \param name: name of the task
* \param priority: priority of the started task. See: Os::Task::start. Default: TASK_PRIORITY_DEFAULT, not prioritized
* \param priority: priority of the started task. See: Os::Task::start. Default: TASK_PRIORITY_DEFAULT, not
* prioritized
* \param stack: stack size provided to the task. See: Os::Task::start. Default: TASK_DEFAULT, posix threads default
* \param cpuAffinity: cpu affinity provided to task. See: Os::Task::start. Default: TASK_DEFAULT, don't care
*/
void start(const Fw::StringBase &name,
void start(const Fw::StringBase& name,
const FwTaskPriorityType priority = Os::Task::TASK_PRIORITY_DEFAULT,
const Os::Task::ParamType stack = Os::Task::TASK_DEFAULT,
const Os::Task::ParamType cpuAffinity = Os::Task::TASK_DEFAULT);
Expand All @@ -73,7 +69,7 @@ class SocketComponentHelper {
*/
SocketIpStatus open();

/**
/**
* \brief check if IP socket has previously been opened
*
* Check if this IpSocket has previously been opened. In the case of Udp this will check for outgoing transmissions
Expand All @@ -87,8 +83,9 @@ class SocketComponentHelper {
/**
* \brief set socket to automatically open connections when true, or not when false
*
* When passed `true`, this instructs the socket to automatically open a socket and reopen socket failed connections. When passed `false`
* the user must explicitly call the `open` method to open the socket initially and when a socket fails.
* When passed `true`, this instructs the socket to automatically open a socket and reopen socket failed
* connections. When passed `false` the user must explicitly call the `open` method to open the socket initially and
* when a socket fails.
*
* \param auto_open: true to automatically open and reopen sockets, false otherwise
*/
Expand All @@ -112,7 +109,7 @@ class SocketComponentHelper {
* \param size: maximum size of data buffer to fill
* \return status of the send, SOCK_DISCONNECTED to reopen, SOCK_SUCCESS on success, something else on error
*/
SocketIpStatus recv(U8* data, U32 &size);
SocketIpStatus recv(U8* data, U32& size);

/**
* \brief close the socket communications
Expand Down Expand Up @@ -202,7 +199,6 @@ class SocketComponentHelper {
*/
virtual void connected() = 0;


/**
* \brief a task designed to read from the socket and output incoming data
*
Expand All @@ -214,9 +210,9 @@ class SocketComponentHelper {
/**
* \brief Re-open port if it has been disconnected
*
* This function is a helper to handle the situations where this code needs to safely reopen a socket. User code should
* connect using the `open` call. This is for opening/reopening in situations where automatic open is performed
* within this socket helper.
* This function is a helper to handle the situations where this code needs to safely reopen a socket. User code
* should connect using the `open` call. This is for opening/reopening in situations where automatic open is
* performed within this socket helper.
*
* \return status of reconnect, SOCK_SUCCESS for success, something else on error
*/
Expand All @@ -226,9 +222,9 @@ class SocketComponentHelper {
Os::Task m_task;
Os::Mutex m_lock;
SocketDescriptor m_descriptor;
bool m_reopen = true; //!< Force reopen on disconnect
bool m_stop = true; //!< Stops the task when set to true
OpenState m_open = OpenState::NOT_OPEN; //!< Have we successfully opened
bool m_reopen = true; //!< Force reopen on disconnect
bool m_stop = true; //!< Stops the task when set to true
OpenState m_open = OpenState::NOT_OPEN; //!< Have we successfully opened
};
}
} // namespace Drv
#endif // DRV_SocketComponentHelper_HPP
Loading
Loading