fprime/Drv/Ip/SocketReadTask.cpp
Rob Bocchino c02f35145e
Remove FPP dependencies on native int types (#2548)
* Remove FPP dependencies on native int types

* Revise FpConfig

* Fix errors in FpConfig

* Revise types

Add size type alias to Serializable
Remove type aliases for generated code
2024-03-04 19:34:23 -08:00

115 lines
4.5 KiB
C++

// ======================================================================
// \title SocketReadTask.cpp
// \author mstarch
// \brief cpp file for SocketReadTask implementation class
//
// \copyright
// Copyright 2009-2020, by the California Institute of Technology.
// ALL RIGHTS RESERVED. United States Government Sponsorship
// acknowledged.
//
// ======================================================================
#include <Drv/Ip/SocketReadTask.hpp>
#include <Fw/Logger/Logger.hpp>
#include <Fw/Types/Assert.hpp>
#include <cerrno>
#define MAXIMUM_SIZE 0x7FFFFFFF
namespace Drv {
SocketReadTask::SocketReadTask() : m_reconnect(false), m_stop(false) {}
SocketReadTask::~SocketReadTask() {}
void SocketReadTask::startSocketTask(const Fw::StringBase &name,
const bool reconnect,
const Os::Task::ParamType priority,
const Os::Task::ParamType stack,
const Os::Task::ParamType cpuAffinity) {
FW_ASSERT(not m_task.isStarted()); // It is a coding error to start this task multiple times
FW_ASSERT(not this->m_stop); // It is a coding error to stop the thread before it is started
m_reconnect = reconnect;
// Note: the first step is for the IP socket to open the port
Os::Task::TaskStatus stat = m_task.start(name, SocketReadTask::readTask, this, priority, stack, cpuAffinity);
FW_ASSERT(Os::Task::TASK_OK == stat, static_cast<NATIVE_INT_TYPE>(stat));
}
SocketIpStatus SocketReadTask::startup() {
return this->getSocketHandler().startup();
}
SocketIpStatus SocketReadTask::open() {
SocketIpStatus status = this->getSocketHandler().open();
// Call connected any time the open is successful
if (Drv::SOCK_SUCCESS == status) {
this->connected();
}
return status;
}
void SocketReadTask::shutdown() {
this->getSocketHandler().shutdown();
}
void SocketReadTask::close() {
this->getSocketHandler().close();
}
Os::Task::TaskStatus SocketReadTask::joinSocketTask(void** value_ptr) {
return m_task.join(value_ptr);
}
void SocketReadTask::stopSocketTask() {
this->m_stop = true;
this->getSocketHandler().shutdown(); // Break out of any receives and fully shutdown
}
void SocketReadTask::readTask(void* pointer) {
FW_ASSERT(pointer);
SocketIpStatus status = SOCK_SUCCESS;
SocketReadTask* self = reinterpret_cast<SocketReadTask*>(pointer);
do {
// Open a network connection if it has not already been open
if ((not self->getSocketHandler().isStarted()) and (not self->m_stop) and
((status = self->startup()) != SOCK_SUCCESS)) {
Fw::Logger::logMsg("[WARNING] Failed to open port with status %d and errno %d\n", status, errno);
(void) Os::Task::delay(SOCKET_RETRY_INTERVAL_MS);
continue;
}
// Open a network connection if it has not already been open
if ((not self->getSocketHandler().isOpened()) and (not self->m_stop) and
((status = self->open()) != SOCK_SUCCESS)) {
Fw::Logger::logMsg("[WARNING] Failed to open port with status %d and errno %d\n", status, errno);
(void) Os::Task::delay(SOCKET_RETRY_INTERVAL_MS);
continue;
}
// If the network connection is open, read from it
if (self->getSocketHandler().isStarted() and self->getSocketHandler().isOpened() and (not self->m_stop)) {
Fw::Buffer buffer = self->getBuffer();
U8* data = buffer.getData();
FW_ASSERT(data);
I32 size = static_cast<I32>(buffer.getSize());
size = (size >= 0) ? size : MAXIMUM_SIZE; // Handle max U32 edge case
status = self->getSocketHandler().recv(data, size);
if ((status != SOCK_SUCCESS) && (status != SOCK_INTERRUPTED_TRY_AGAIN)) {
Fw::Logger::logMsg("[WARNING] Failed to recv from port with status %d and errno %d\n", status, errno);
self->getSocketHandler().close();
buffer.setSize(0);
} else {
// Send out received data
buffer.setSize(size);
}
self->sendBuffer(buffer, status);
}
}
// As long as not told to stop, and we are successful interrupted or ordered to retry, keep receiving
while (not self->m_stop &&
(status == SOCK_SUCCESS || status == SOCK_INTERRUPTED_TRY_AGAIN || self->m_reconnect));
self->getSocketHandler().shutdown(); // Shutdown the port entirely
}
} // namespace Drv