-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
Copy pathTcpServerComponentImpl.cpp
132 lines (113 loc) · 4.57 KB
/
TcpServerComponentImpl.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// ======================================================================
// \title TcpServerComponentImpl.cpp
// \author mstarch
// \brief cpp file for TcpServerComponentImpl component implementation class
//
// \copyright
// Copyright 2009-2020, by the California Institute of Technology.
// ALL RIGHTS RESERVED. United States Government Sponsorship
// acknowledged.
//
// ======================================================================
#include <Drv/TcpServer/TcpServerComponentImpl.hpp>
#include <FpConfig.hpp>
#include "Fw/Types/Assert.hpp"
#include "Fw/Logger/Logger.hpp"
namespace Drv {
// ----------------------------------------------------------------------
// Construction, initialization, and destruction
// ----------------------------------------------------------------------
TcpServerComponentImpl::TcpServerComponentImpl(const char* const compName)
: TcpServerComponentBase(compName) {}
SocketIpStatus TcpServerComponentImpl::configure(const char* hostname,
const U16 port,
const U32 send_timeout_seconds,
const U32 send_timeout_microseconds) {
(void)m_socket.configure(hostname, port, send_timeout_seconds, send_timeout_microseconds);
return startup();
}
TcpServerComponentImpl::~TcpServerComponentImpl() {}
// ----------------------------------------------------------------------
// Implementations for socket read task virtual methods
// ----------------------------------------------------------------------
U16 TcpServerComponentImpl::getListenPort() {
return m_socket.getListenPort();
}
IpSocket& TcpServerComponentImpl::getSocketHandler() {
return m_socket;
}
Fw::Buffer TcpServerComponentImpl::getBuffer() {
return allocate_out(0, 1024);
}
void TcpServerComponentImpl::sendBuffer(Fw::Buffer buffer, SocketIpStatus status) {
Drv::RecvStatus recvStatus = RecvStatus::RECV_ERROR;
if (status == SOCK_SUCCESS) {
recvStatus = RecvStatus::RECV_OK;
}
else if (status == SOCK_NO_DATA_AVAILABLE) {
recvStatus = RecvStatus::RECV_NO_DATA;
}
else {
recvStatus = RecvStatus::RECV_ERROR;
}
this->recv_out(0, buffer, recvStatus);
}
void TcpServerComponentImpl::connected() {
if (isConnected_ready_OutputPort(0)) {
this->ready_out(0);
}
}
bool TcpServerComponentImpl::isStarted() {
Os::ScopeLock scopedLock(this->m_lock);
return this->m_descriptor.serverFd != -1;
}
SocketIpStatus TcpServerComponentImpl::startup() {
Os::ScopeLock scopedLock(this->m_lock);
Drv::SocketIpStatus status = SOCK_SUCCESS;
// Prevent multiple startup attempts
if (this->m_descriptor.serverFd == -1) {
status = this->m_socket.startup(this->m_descriptor);
}
return status;
}
void TcpServerComponentImpl::terminate() {
Os::ScopeLock scopedLock(this->m_lock);
this->m_socket.terminate(this->m_descriptor);
this->m_descriptor.serverFd = -1;
}
void TcpServerComponentImpl::readLoop() {
Drv::SocketIpStatus status = Drv::SocketIpStatus::SOCK_NOT_STARTED;
// Keep trying to reconnect until the status is good, told to stop, or reconnection is turned off
do {
status = this->startup();
if (status != SOCK_SUCCESS) {
Fw::Logger::log("[WARNING] Failed to listen on port %hu with status %d\n", this->getListenPort(), status);
(void)Os::Task::delay(SOCKET_RETRY_INTERVAL);
continue;
}
}
while (this->running() && status != SOCK_SUCCESS && this->m_reconnect);
// If start up was successful then perform normal operations
if (this->running() && status == SOCK_SUCCESS) {
// Perform the nominal read loop
SocketComponentHelper::readLoop();
// Terminate the server
this->terminate();
}
}
// ----------------------------------------------------------------------
// Handler implementations for user-defined typed input ports
// ----------------------------------------------------------------------
Drv::SendStatus TcpServerComponentImpl::send_handler(const NATIVE_INT_TYPE portNum, Fw::Buffer& fwBuffer) {
Drv::SocketIpStatus status = this->send(fwBuffer.getData(), fwBuffer.getSize());
// Only deallocate buffer when the caller is not asked to retry
if (status == SOCK_INTERRUPTED_TRY_AGAIN) {
return SendStatus::SEND_RETRY;
} else if (status != SOCK_SUCCESS) {
deallocate_out(0, fwBuffer);
return SendStatus::SEND_ERROR;
}
deallocate_out(0, fwBuffer);
return SendStatus::SEND_OK;
}
} // end namespace Drv