/* * Packet.h * * Created on: Mar 12, 2021 * Author: astrisw */ #ifndef BASE_PACKET_H_ #define BASE_PACKET_H_ #include #include #include #include #include #include /* * 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 header_field_index; std::unordered_map header_field_size; std::unordered_map header_field_values; int ssc; //source sequence counter int crc; unsigned char *buffer; int computeMaxPacketSize(){ return std::stoi((static_cast(doc.first_child().attribute("maxsize").value()))); } int computeHeaderSize(){ int headerSize = 0; for( const std::pair 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((*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 *header_field_index, std::unordered_map *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((*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; 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 * getHeaderFieldValues() {return &header_field_values;} std::unordered_map getHeaderFieldIndex() {return header_field_index;} std::unordered_map 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 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_ */