Select Git revision
TAPFileManager.java
PacketStream.cpp 14.18 KiB
/***************************************************************************
PacketStream.cpp - description
-------------------
begin : Thu Nov 29 2001
copyright : (C) 2001, 2013 by Andrea Bulgarelli
email : bulgarelli@iasfbo.inaf.it
***************************************************************************/
/***************************************************************************
* *
* This program is free software for non commercial purpose *
* and for public research institutes; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License. *
* For commercial purpose see appropriate license terms *
* *
***************************************************************************/
#include "PacketStream.h"
#include "ConfigurationFile.h"
#include "PacketExceptionFileFormat.h"
#include "PacketExceptionIO.h"
#include "PacketNotRecognized.h"
#include "PacketLibDemo.h"
#include <sstream>
using namespace PacketLib;
PacketStream::PacketStream(string fileNameConfig)
{
filenameConfig = realpath(fileNameConfig.c_str(), NULL);
numberOfPacketType = 0;
headerReference = 0;
//TODO
packetType = new Packet* [255];
//TODO
memset(packetType, 0, sizeof(Packet*)*255);
pathFileNameConfig = 0;
dimHeader = 0;
std::cout << "Loading config file " << filenameConfig << " ..." << std::endl;
createStreamStructure();
std::cout << "Load complete." << std::endl;
}
PacketStream::PacketStream()
: filenameConfig("")
{
numberOfPacketType = 0;
headerReference = 0;
//TODO
packetType = new Packet* [255];
//TODO
memset(packetType, 0, sizeof(Packet*)*255);
pathFileNameConfig = 0;
dimHeader = 0;
}
PacketStream::~PacketStream()
{
for(int i=0; i< numberOfPacketType; i++)
delete packetType[i];
delete[] packetType;
delete headerReference;
free(pathFileNameConfig);
}
dword PacketStream::getPacketDimension(ByteStreamPtr stream) {
dword dimPre = 0;
if(prefix)
dimPre += dimPrefix;
//ByteStreamPtr prefix = new ByteStream(stream, dimPre, bigendian);
dword dim = 0;
dword dimHeader = headerReference->size();
dim += dimHeader;
ByteStreamPtr tempHeader = ByteStreamPtr(new ByteStream());
tempHeader->setStream(stream->stream+dimPre, dimHeader, bigendian);
headerReference->setByteStream(tempHeader);
dim += headerReference->getPacketLength();
return dim;
}
int PacketStream::detPacketType(ByteStreamPtr prefix, ByteStreamPtr packetHeader, ByteStreamPtr packetDataField)
{
/// Iterate through list and output each element.
/// The packetType 0 is the packet not recognized
for (int i = 1; i<numberOfPacketType; i++)
{
Packet* p = getPacketType(i);
p->decode(prefix, packetHeader, packetDataField);
if(p->verify())
return i;
}
return 0;
}
int PacketStream::detPacketType(ByteStreamPtr prefix, ByteStreamPtr packet)
{
/// Iterate through list and output each element.
/// The packetType 0 is the packet not recognized
for (dword i = 1; i<numberOfPacketType; i++)
{
Packet* p = getPacketType(i);
p->decode(prefix, packet);
if(p->verify())
return i;
}
return 0;
}
int PacketStream::detPacketType(ByteStreamPtr packet)
{
/// Iterate through list and output each element.
/// The packetType 0 is the packet not recognized
for (dword i = 1; i<numberOfPacketType; i++)
{
Packet* p = getPacketType(i);
p->decode(packet);
if(p->verify())
return i;
}
return 0;
}
Packet* PacketStream::getPacket(ByteStreamPtr stream) throw(PacketException*){
int index = detPacketType(stream);
if(index > 0) {
Packet* p = getPacketType(index);
if(!p->decode(stream)) //gli stream diventano del packet
throw new PacketExceptionIO("it is impossible to resolve the packet.");
return p;
}
else
return 0;
}
const std::string fixed32[] = { "uint32", "int32", "float" };
const std::string fixed64[] = { "uint64", "int64", "double" };
void PacketStream::cachePhysicalIndexes(pugi::xml_node node, std::map<pugi::xml_node, int>& physicalIndex)
{
int index = 0;
for(pugi::xml_node_iterator it=node.begin(); it != node.end(); ++it)
{
if(string(it->name()).compare("field") != 0)
continue;
#ifdef DEBUG
std::cout << "Physical index of " << it->attribute("name").value() << " is " << index << std::endl;
#endif
physicalIndex[*it] = index;
// if 32bits fields
string typeStr = it->attribute("type").value();
bool found = false;
for(unsigned int i=0; i<3; i++)
{
if(typeStr.compare(fixed32[i]) == 0)
{
index+=2;
found = true;
break;
}
}
if(found)
continue;
// if 64bits fields
for(unsigned int i=0; i<3; i++)
{
if(typeStr.compare(fixed64[i]) == 0)
{
index+=4;
found = true;
break;
}
}
if(found)
continue;
// else (<= 16bits fields)
index++;
}
}
void PacketStream::createStreamStructureXml()
{
std::map<pugi::xml_node, int> physicalIndex;
pugi::xml_document doc;
// open the config file
if (!doc.load_file(filenameConfig.c_str()))
{
std::stringstream ss;
ss << "Cannot open " << filenameConfig;
throw new PacketExceptionFileFormat(ss.str().c_str());
}
// cache all the field physical indexes
pugi::xpath_node_set fieldParents = doc.select_nodes("//*[field]");
for(pugi::xpath_node_set::const_iterator it = fieldParents.begin(); it != fieldParents.end(); ++it)
cachePhysicalIndexes(it->node(), physicalIndex);
// get the stream node
pugi::xml_node sNode = doc.child("stream");
if(!sNode) throw new PacketExceptionFileFormat("<stream> not found.");
if(pathFileNameConfig) free(pathFileNameConfig);
pathFileNameConfig = getcwd(NULL, 512L);
bigendian = false;
pugi::xml_attribute beAttr = sNode.attribute("bigendian");
if(beAttr && strcmp(beAttr.value(), "true") == 0)
bigendian = true;
#ifdef DEBUG
std::cout << "big endian? " << beAttr.value() << std::endl;
#endif
dimPrefix = 0;
prefix = false;
pugi::xml_attribute preAttr = sNode.attribute("prefixSize");
if(preAttr)
{
prefix = true;
dimPrefix = atoi(preAttr.value());
}
#ifdef DEBUG
std::cout << "prefix size: " << dimPrefix << std::endl;
#endif
// get the header node
pugi::xml_node hNode = sNode.child("header");
if(!hNode) throw new PacketExceptionFileFormat("<header> not found.");
// get the packet length physical index
std::string query = std::string("//field[@id=\"") + hNode.attribute("idref").value()+"\"]";
pugi::xml_node plNode = hNode.select_nodes(query.c_str())[0].node();
int plIndex = physicalIndex[plNode];
// get the packet length bit width
std::string typeStr = plNode.attribute("type").value();
std::string::size_type spos = typeStr.find_first_of("0123456789");
std::string::size_type epos = typeStr.find_last_of("0123456789");
int nbits = atoi(typeStr.substr(spos, epos+1).c_str());
// load the header
delete headerReference;
headerReference = new PacketHeader();
headerReference->loadHeader(hNode, plIndex, nbits);
dimHeader = headerReference->size();
// load the packet not recognized
PacketNotRecognized* p = new PacketNotRecognized(bigendian);
p->createPacketType(hNode, prefix, dimPrefix);
packetType[numberOfPacketType] = p;
numberOfPacketType++;
// load packet types
pugi::xml_node pNode = sNode.child("packet");
while(pNode) {
if(pNode.attribute("name") != 0)
{
Packet* p = new Packet(bigendian);
p->createPacketType(doc, hNode, plIndex, nbits, pNode, prefix, dimPrefix, physicalIndex);
packetType[numberOfPacketType] = p;
p->setPacketID(numberOfPacketType);
numberOfPacketType++;
}
pNode = pNode.next_sibling();
}
}
bool PacketStream::createStreamStructure() throw(PacketException*)
{
if(filenameConfig.find(".xml") != std::string::npos)
{
createStreamStructureXml();
return true;
}
ConfigurationFile config;
char* line;
char **argv = new char* [1];
argv[0] = (char*) filenameConfig.c_str();
//cout << "@@@@@@@@@@OPEN " << filenameConfig << endl;
try
{
if(config.open(argv))
{
//delete[] argv;
if(pathFileNameConfig) free(pathFileNameConfig);
pathFileNameConfig = getcwd(NULL, 512L);
/// prefix
config.setpos(0);
line = config.getLine();
if(strcmp(line, "[Configuration]") == 0)
{
//delete[] line;
line = config.getLine();
if(strcmp(line, "false") == 0)
prefix = false;
else
{
if(strcmp(line, "true") == 0)
prefix = true;
else
{
//delete[] line;
throw new PacketExceptionFileFormat("Prefix selector format not correct. It's possible only true or false value.");
return false;
}
}
//delete[] line;
/// bigendian
line = config.getLine();
if(strcmp(line, "false") == 0)
bigendian = false;
else
{
if(strcmp(line, "true") == 0)
bigendian = true;
else
{
throw new PacketExceptionFileFormat("Bigendian selector format not correct. It's possible only true or false value.");
return false;
}
}
/// dimensione of prefix
//delete[] line;
line = config.getLine();
if(prefix == false)
dimPrefix = 0;
else
dimPrefix = atoi(line);
}
else
throw new PacketExceptionFileFormat("No [Configuration] section found.");
/// [Header Format] section
//delete[] line;
line = config.getLine();
if(strcmp(line, "[Header Format]") == 0)
{
//delete[] line;
/// Create headerReference of PacketHeader type. The method reads the structure of header from configuration file (named in filenameConfig)
line = config.getLine();
delete headerReference;
headerReference = (PacketHeader*) new PacketHeader();
if(!headerReference->loadHeader(line))
{
//delete[] line;
throw new PacketExceptionFileFormat("No parameters in file header format");
return false;
}
dimHeader = headerReference->size();
/// It creates the PACKET NOT RECOGNIZED
PacketNotRecognized* p = new PacketNotRecognized(bigendian);
if(!p->createPacketType(line, prefix, dimPrefix))
{
//delete[] line;
throw new PacketExceptionFileFormat("Packet Not Recognized not created.");
}
else
{
packetType[numberOfPacketType] = p;
numberOfPacketType++;
}
//delete[] line;
}
else
{
throw new PacketExceptionFileFormat("No [Header format] section");
return false;
}
/// [Packet Format]
line = config.getLine();
if(strcmp(line, "[Packet Format]") == 0)
{
char* packetFileName = config.getLine();
while(strlen(packetFileName) != 0)
{
Packet* p;
p = new Packet(bigendian);
p->createPacketType(packetFileName, prefix, dimPrefix);
packetType[numberOfPacketType] = p;
p->setPacketID(numberOfPacketType);
numberOfPacketType++;
//delete[] packetFileName;
packetFileName = config.getLine();
}
}
else
{
throw new PacketExceptionFileFormat("No [Packet Format] section");
return false;
}
config.close();
}
else
throw new PacketExceptionFileFormat("Header file configuration not found.");
return true;
}
catch(PacketExceptionIO* e)
{
e->add(" - ");
e->add(filenameConfig.c_str());
e->add("Configuration file: ");
throw e;
}
catch(PacketExceptionFileFormat* e)
{
e->add(" - ");
e->add(filenameConfig.c_str());
e->add("Configuration file: ");
throw e;
}
}
word PacketStream::getPrefixDimension() const
{
if(prefix)
return dimPrefix;
else
return 0;
}
word PacketStream::getHeaderDimension() const
{
return dimHeader;
}
word PacketStream::getNumberOfPacketType()
{
return numberOfPacketType;
}
Packet* PacketStream::getPacketType(int index)
{
return packetType[index];
}
Packet* PacketStream::getPacketType(string name) {
for(int i=1; i<numberOfPacketType; i++) {
string pname = packetType[i]->getName();
if(pname.compare(name) == 0)
return packetType[i];
}
throw new PacketException("Packet type not found in the PacketStream");
}
bool PacketStream::isBigEndian()
{
return (bool) this->bigendian;
}
void PacketStream::setFileNameConfig(const char* f)
{
this->filenameConfig = (char*) f;
//this->pathFileNameConfig = Utility::extractPath(filenameConfig);
}
bool PacketStream::thereIsPrefix()
{
return prefix;
}