Newer
Older
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
/*
* Packet.h
*
* Created on: Mar 12, 2021
* Author: astrisw
*/
#ifndef BASE_PACKET_H_
#define BASE_PACKET_H_
#include <pugixml/src/pugixml.hpp>
#include <iostream>
#include <cstring>
#include <string>
#include <math.h>
#include <unordered_map>
/*
* class Packet
* Implementation of the packet
*
* @member field name: the packet name reported in the corresponding xml file.
* @member field doc: the xml file representing the packet structure.
* @member field header_size: the size of the header (in bytes).
* @member field max_data_length: the max size of the data field (in bytes).
* @member field tail size: the size of the tail (in bytes).
* @member field max_packet_size: the maximum size of the whole packet (sum of the sizes of the header, data, tail)
* @member field header_field_index: the map representing the "order" of the fields in the header,
* es. [0 : "CRC FLAG" ] // first element in the header
* [1 : "TelescopeID"] // second element in the header and so on.
* @member field header_field_size: the map representing the sizes of the fields in the header,
* es. ["CRC FLAG", 1] // bit size of the element CRC FLAG
* ["TelescopeID", 7] // bit size of the element TelescopeID and so on.
*
* @member field header_map_values: a map where each key is the header field name and the value is
* the actual value in the received buffer.
* The lookup maps are used to access the buffer in the correct way.
*/
class BasePacket {
protected:
std::string name;
pugi::xml_document doc;
int max_packet_size;
int header_size;
int payload_size;
int tail_size;
std::unordered_map<unsigned short, std::string> header_field_index;
std::unordered_map<std::string, unsigned short> header_field_size;
std::unordered_map<std::string, unsigned short> header_field_values;
int ssc; //source sequence counter
int crc;
unsigned char *buffer;
int computeMaxPacketSize(){
return std::stoi((static_cast<std::string>(doc.first_child().attribute("maxsize").value())));
}
int computeHeaderSize(){
int headerSize = 0;
for( const std::pair<std::string, unsigned short> n : header_field_size) {
headerSize += n.second;
}
return headerSize/8; //from bitsize to bytesize
}
int computeTailSize(){
int tail_size = 0;
pugi::xml_node root = doc.first_child();
pugi::xml_node tail_node = root.child("tail");
pugi::xml_node_iterator tail_it = tail_node.begin();
while(tail_it != tail_node.end()){
unsigned short field_size = std::stoi((static_cast<std::string>((*tail_it).attribute("type").value()).substr(4)));
tail_size += field_size;
tail_it++;
}
return tail_size/8; //from bit size to byte
}
/*
* This function initializes the lookup maps of the header (see the class definition).
* @ param *header_field_index
* @ param *header_field_size
*/
void computeHeaderMaps(std::unordered_map<unsigned short, std::string> *header_field_index, std::unordered_map<std::string, unsigned short> *header_field_size){
pugi::xml_node root = doc.first_child();
pugi::xml_node header_node = root.child("header");
pugi::xml_node_iterator header_it = header_node.begin();
int i = 0;
while(header_it != header_node.end()){
std::string name = (*header_it).attribute("name").value();
unsigned short size = std::stoi((static_cast<std::string>((*header_it).attribute("type").value()).substr(4)));
(*header_field_index)[i] = name;
(*header_field_size)[name] = size;
header_it++;
i += 1;
}
}
public:
BasePacket(std::string packetPath){
if (!this->doc.load_file(packetPath.c_str())) {
std::cerr << "Invalid packet path: " << packetPath << std::endl;
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
throw "Invalid packet path";
}
computeHeaderMaps(&this->header_field_index,&this->header_field_size);
this->header_size = computeHeaderSize();
this->tail_size = computeTailSize();
this->max_packet_size = computeMaxPacketSize();
unsigned char *buffer = new unsigned char[max_packet_size];
memset(buffer, ' ', max_packet_size);
this->buffer = buffer;
this->payload_size = -1;
this->name = doc.first_child().attribute("name").value();
}
std::string getName(){return name;}
int getHeaderSize() {return header_size;}
int getPayloadSize() {return payload_size;}
int getTailSize() {return tail_size;}
int getPacketSize() {return header_size + payload_size + tail_size;}
int getSSC() {return ssc;}
int getCRC() {return crc;}
int getMaxPacketSize() {return max_packet_size;}
unsigned char * getBufferPtr(){return buffer;}
std::unordered_map<std::string,unsigned short> * getHeaderFieldValues() {return &header_field_values;}
std::unordered_map<unsigned short, std::string> getHeaderFieldIndex() {return header_field_index;}
std::unordered_map<std::string,unsigned short> getHeaderFieldSize() {return header_field_size;}
/*
* This function fills the map of "header_field_values" where
* each key is the header field name and the value is
* the actual value in the received buffer.
* It uses the lookup maps in order to access the buffer in
* the correct way.
*/
inline void computeHeaderFieldValues(){
int num_bit_read = 0; // offset from the beginning of the byte
for(unsigned short i = 0; i < header_field_index.size(); i++) {
std::string field_name = header_field_index[i];
int bit_rem = header_field_size[field_name]; //remaining bits to read
int val = 0; //final value of the field
while(bit_rem > 0){
unsigned short read = buffer[num_bit_read/8];
unsigned short mask = pow(2,8-num_bit_read%8)-1;
read = read & mask;
bit_rem = bit_rem - 8 + num_bit_read%8;
read = (bit_rem >= 0)*(read << bit_rem) +
(bit_rem < 0) *(read >> -bit_rem);
val += read;
num_bit_read = (bit_rem > 0)*(num_bit_read + 8 - num_bit_read%8)+
(bit_rem <= 0)*(num_bit_read + 8 - num_bit_read%8 + bit_rem);
}
header_field_values[field_name] = val;
}
updateFromBuffer();
updatePayloadSize();
}
virtual void updateFromBuffer()=0;
virtual void updatePayloadSize()=0;
std::string toString(){
std::string ret = "------------------\n";
for( const std::pair<std::string, unsigned short> n : header_field_values) {
ret += (n.first + " : " + std::to_string(n.second) + "\n");
}
ret+= "------------------";
return ret;
}
virtual ~BasePacket(){
std::cout << "Deleting Packet" << std::endl;
delete buffer;
}
};
#endif /* BASE_PACKET_H_ */