F´ Flight Software - C/C++ Documentation NASA-v1.6.0
A framework for building embedded system applications to NASA flight quality standards.
Loading...
Searching...
No Matches
UdpReceiverComponentImpl.cpp
Go to the documentation of this file.
1// ======================================================================
2// \title UdpReceiverImpl.cpp
3// \author tcanham
4// \brief cpp file for UdpReceiver component implementation class
5//
6// \copyright
7// Copyright 2009-2015, by the California Institute of Technology.
8// ALL RIGHTS RESERVED. United States Government Sponsorship
9// acknowledged.
10//
11// ======================================================================
12
13
15#include <FpConfig.hpp>
16#include <sys/types.h>
17#include <cstring>
18#include <cerrno>
19#include <cstdlib>
20#include <unistd.h>
21#include <sys/socket.h>
22#include <arpa/inet.h>
23#include <Os/TaskString.hpp>
24
25//#define DEBUG_PRINT(x,...) printf(x,##__VA_ARGS__)
26#define DEBUG_PRINT(x,...)
27
28namespace Svc {
29
30 // ----------------------------------------------------------------------
31 // Construction, initialization, and destruction
32 // ----------------------------------------------------------------------
33
34 UdpReceiverComponentImpl ::
35 UdpReceiverComponentImpl(
36 const char *const compName
37 ) : UdpReceiverComponentBase(compName),
38 m_fd(-1),
39 m_packetsReceived(0),
40 m_bytesReceived(0),
41 m_packetsDropped(0),
42 m_decodeErrors(0),
43 m_firstSeq(true),
44 m_currSeq(0)
45 {
46
47 }
48
49 void UdpReceiverComponentImpl ::
50 init(
51 const NATIVE_INT_TYPE instance
52 )
53 {
54 UdpReceiverComponentBase::init(instance);
55 }
56
57 UdpReceiverComponentImpl ::
58 ~UdpReceiverComponentImpl()
59 {
60 if (this->m_fd != -1) {
61 close(this->m_fd);
62 }
63 }
64
66 const char* port
67 ) {
68
69 //create a UDP socket
70 this->m_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
71 if (-1 == this->m_fd) {
72 Fw::LogStringArg arg(strerror(errno));
73 this->log_WARNING_HI_UR_SocketError(arg);
74 }
75
76 sockaddr_in saddr;
77 // zero out the structure
78 memset(&saddr, 0, sizeof(saddr));
79
80 saddr.sin_family = AF_INET;
81 saddr.sin_port = htons(atoi(port));
82 saddr.sin_addr.s_addr = htonl(INADDR_ANY);
83
84 //bind socket to port
85 NATIVE_INT_TYPE status = bind(this->m_fd , (struct sockaddr*)&saddr, sizeof(saddr));
86 if (-1 == status) {
87 Fw::LogStringArg arg(strerror(errno));
88 this->log_WARNING_HI_UR_BindError(arg);
89 close(this->m_fd);
90 this->m_fd = -1;
91 } else {
92 this->log_ACTIVITY_HI_UR_PortOpened(atoi(port));
93 }
94 }
95
97 NATIVE_UINT_TYPE priority,
98 NATIVE_UINT_TYPE stackSize,
99 NATIVE_UINT_TYPE affinity
100 ) {
101 Os::TaskString name(this->getObjName());
102 Os::Task::TaskStatus stat = this->m_socketTask.start(
103 name,
104 0,
105 priority,
106 stackSize,
107 UdpReceiverComponentImpl::workerTask,
108 this,
109 affinity);
110 FW_ASSERT(Os::Task::TASK_OK == stat,stat);
111 }
112
113
114 // ----------------------------------------------------------------------
115 // Handler implementations for user-defined typed input ports
116 // ----------------------------------------------------------------------
117
118 void UdpReceiverComponentImpl ::
119 Sched_handler(
120 const NATIVE_INT_TYPE portNum,
121 NATIVE_UINT_TYPE context
122 )
123 {
124 this->tlmWrite_UR_BytesReceived(this->m_bytesReceived);
125 this->tlmWrite_UR_PacketsReceived(this->m_packetsReceived);
126 this->tlmWrite_UR_PacketsDropped(this->m_packetsDropped);
127 }
128
129 void UdpReceiverComponentImpl::workerTask(void* ptr) {
130 UdpReceiverComponentImpl *compPtr = static_cast<UdpReceiverComponentImpl*>(ptr);
131 while (true) {
132 compPtr->doRecv();
133 }
134 }
135
136 void UdpReceiverComponentImpl::doRecv() {
137
138 // wait for data from the socket
139 NATIVE_INT_TYPE psize = recvfrom(
140 this->m_fd,
141 this->m_recvBuff.getBuffAddr(),
142 this->m_recvBuff.getBuffCapacity(),
143 MSG_WAITALL,
144 0,
145 0);
146 if (-1 == psize) {
147 if (errno != EINTR) {
148 Fw::LogStringArg arg(strerror(errno));
149 this->log_WARNING_HI_UR_RecvError(arg);
150 }
151 return;
152 }
153 // reset buffer for deserialization
154 Fw::SerializeStatus stat = this->m_recvBuff.setBuffLen(psize);
155 FW_ASSERT(Fw::FW_SERIALIZE_OK == stat, stat);
156
157 // get sequence number
158 U8 seqNum;
159 stat = this->m_recvBuff.deserialize(seqNum);
160 // check for deserialization error or port number too high
161 if (stat != Fw::FW_SERIALIZE_OK) {
162 this->log_WARNING_HI_UR_DecodeError(DECODE_SEQ,stat);
163 this->m_decodeErrors++;
164 return;
165 }
166
167 // track sequence number
168 if (this->m_firstSeq) {
169 // first time, set tracked sequence number equal to the one received
170 this->m_currSeq = seqNum;
171 this->m_firstSeq = false;
172 } else {
173 // make sure sequence number has gone up by one
174 if (seqNum != ++this->m_currSeq) {
175 // will only be right if it rolls over only once, but better than nothing
176 U8 diff = seqNum - this->m_currSeq;
177 this->m_packetsDropped += diff;
178 // send EVR
179 this->log_WARNING_HI_UR_DroppedPacket(diff);
180 // reset to current sequence
181 this->m_currSeq = seqNum;
182 }
183 }
184
185 // get port number
186 U8 portNum;
187 stat = this->m_recvBuff.deserialize(portNum);
188 // check for deserialization error or port number too high
189 if (stat != Fw::FW_SERIALIZE_OK or portNum > this->getNum_PortsOut_OutputPorts()) {
190 this->log_WARNING_HI_UR_DecodeError(DECODE_PORT,stat);
191 this->m_decodeErrors++;
192 return;
193 }
194 // get buffer for port
195
196 stat = this->m_recvBuff.deserialize(this->m_portBuff);
197 if (stat != Fw::FW_SERIALIZE_OK) {
198 this->log_WARNING_HI_UR_DecodeError(DECODE_BUFFER,stat);
199 this->m_decodeErrors++;
200 return;
201 }
202
203 // call output port
204 DEBUG_PRINT("Calling port %d with %d bytes.\n",portNum,this->m_portBuff.getBuffLength());
205 if (this->isConnected_PortsOut_OutputPort(portNum)) {
206
207 Fw::SerializeStatus stat = this->PortsOut_out(portNum,this->m_portBuff);
208
209 // If had issues deserializing the data, then report it:
210 if (stat != Fw::FW_SERIALIZE_OK) {
211
212 this->log_WARNING_HI_UR_DecodeError(PORT_SEND,stat);
213 this->m_decodeErrors++;
214 }
215
216 this->m_packetsReceived++;
217 this->m_bytesReceived += psize;
218
219 }
220 }
221
222#ifdef BUILD_UT
223 UdpReceiverComponentImpl::UdpSerialBuffer& UdpReceiverComponentImpl::UdpSerialBuffer::operator=(const UdpReceiverComponentImpl::UdpSerialBuffer& other) {
224 this->resetSer();
225 this->serialize(other.getBuffAddr(),other.getBuffLength(),true);
226 return *this;
227 }
228
229 UdpReceiverComponentImpl::UdpSerialBuffer::UdpSerialBuffer(
230 const Fw::SerializeBufferBase& other) : Fw::SerializeBufferBase() {
231 FW_ASSERT(sizeof(this->m_buff)>= other.getBuffLength(),sizeof(this->m_buff),other.getBuffLength());
232 memcpy(this->m_buff,other.getBuffAddr(),other.getBuffLength());
233 this->setBuffLen(other.getBuffLength());
234 }
235
236 UdpReceiverComponentImpl::UdpSerialBuffer::UdpSerialBuffer(
237 const UdpReceiverComponentImpl::UdpSerialBuffer& other) : Fw::SerializeBufferBase() {
238 FW_ASSERT(sizeof(this->m_buff)>= other.getBuffLength(),sizeof(this->m_buff),other.getBuffLength());
239 memcpy(this->m_buff,other.m_buff,other.getBuffLength());
240 this->setBuffLen(other.getBuffLength());
241 }
242
243 UdpReceiverComponentImpl::UdpSerialBuffer::UdpSerialBuffer(): Fw::SerializeBufferBase() {
244
245 }
246
247#endif
248
249
250
251} // end namespace Svc
#define FW_ASSERT(...)
Definition Assert.hpp:7
PlatformIntType NATIVE_INT_TYPE
Definition BasicTypes.h:51
uint8_t U8
8-bit unsigned integer
Definition BasicTypes.h:26
PlatformUIntType NATIVE_UINT_TYPE
Definition BasicTypes.h:52
C++-compatible configuration header for fprime configuration.
#define DEBUG_PRINT(x,...)
SerializeBufferBase & operator=(const SerializeBufferBase &src)
equal operator
virtual U8 * getBuffAddr()=0
gets buffer address for data filling
NATIVE_UINT_TYPE getBuffLength() const
returns current buffer size
TaskStatus
Definition Task.hpp:18
@ TASK_OK
message sent/received okay
Definition Task.hpp:19
TaskStatus start(const Fw::StringBase &name, taskRoutine routine, void *arg, NATIVE_UINT_TYPE priority=TASK_DEFAULT, NATIVE_UINT_TYPE stackSize=TASK_DEFAULT, NATIVE_UINT_TYPE cpuAffinity=TASK_DEFAULT, NATIVE_UINT_TYPE identifier=TASK_DEFAULT)
start the task
Definition Task.cpp:18
void open(const char *port)
Open the connection.
void startThread(NATIVE_UINT_TYPE priority, NATIVE_UINT_TYPE stackSize, NATIVE_UINT_TYPE affinity)
start worker thread
Definition Buffer.cpp:21
SerializeStatus
forward declaration for string
@ FW_SERIALIZE_OK
Serialization/Deserialization operation was successful.