non crashing code - snapshot before trying QXmlStreamReader

This commit is contained in:
Srivats P. 2011-02-10 23:30:58 +05:30
parent a9dbb7bdd2
commit a70a6c5350
3 changed files with 311 additions and 62 deletions

View File

@ -21,8 +21,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "mac.pb.h" #include "mac.pb.h"
#include "eth2.pb.h" #include "eth2.pb.h"
#include "ip4.pb.h"
#include "hexdump.pb.h" #include "hexdump.pb.h"
#include "ip4.pb.h"
#include "ip6.pb.h"
#include "tcp.pb.h"
#include <google/protobuf/descriptor.h> #include <google/protobuf/descriptor.h>
@ -85,16 +87,24 @@ void PdmlDefaultProtocol::unknownFieldHandler(QString name,
// ---------------------------------------------------------- // // ---------------------------------------------------------- //
PdmlParser::PdmlParser(OstProto::StreamConfigList *streams) PdmlParser::PdmlParser(OstProto::StreamConfigList *streams)
{ {
skipUntilEndOfPacket_ = false;
skipCount_ = 0; skipCount_ = 0;
currentPdmlProtocol_ = NULL;
streams_ = streams; streams_ = streams;
protocolMap_.insert("unknown", new PdmlUnknownProtocol()); protocolMap_.insert("unknown", new PdmlUnknownProtocol());
protocolMap_.insert("geninfo", new PdmlGenInfoProtocol()); protocolMap_.insert("geninfo", new PdmlGenInfoProtocol());
protocolMap_.insert("frame", new PdmlFrameProtocol()); protocolMap_.insert("frame", new PdmlFrameProtocol());
#if 0
protocolMap_.insert("fake-field-wrapper",
new PdmlFakeFieldWrapperProtocol());
#endif
#if 0
protocolMap_.insert("eth", new PdmlEthProtocol()); protocolMap_.insert("eth", new PdmlEthProtocol());
protocolMap_.insert("ip", new PdmlIp4Protocol()); protocolMap_.insert("ip", new PdmlIp4Protocol());
protocolMap_.insert("ipv6", new PdmlIp6Protocol());
protocolMap_.insert("tcp", new PdmlTcpProtocol());
#endif
} }
PdmlParser::~PdmlParser() PdmlParser::~PdmlParser()
@ -109,12 +119,6 @@ bool PdmlParser::startElement(const QString & /* namespaceURI */,
{ {
qDebug("%s (%s)", __FUNCTION__, qName.toAscii().constData()); qDebug("%s (%s)", __FUNCTION__, qName.toAscii().constData());
if (skipUntilEndOfPacket_)
{
Q_ASSERT(skipCount_ == 0);
goto _exit;
}
if (skipCount_) if (skipCount_)
{ {
skipCount_++; skipCount_++;
@ -127,8 +131,6 @@ bool PdmlParser::startElement(const QString & /* namespaceURI */,
} }
else if (qName == "packet") else if (qName == "packet")
{ {
Q_ASSERT(skipUntilEndOfPacket_ == false);
// XXX: For now, each packet is converted to a stream // XXX: For now, each packet is converted to a stream
currentStream_ = streams_->add_stream(); currentStream_ = streams_->add_stream();
currentStream_->mutable_stream_id()->set_id(packetCount_); currentStream_->mutable_stream_id()->set_id(packetCount_);
@ -146,11 +148,11 @@ bool PdmlParser::startElement(const QString & /* namespaceURI */,
goto _exit; goto _exit;
} }
if (protoName == "fake-field-wrapper") // HACK HACK HACK
{ if (currentPdmlProtocol_ && (currentPdmlProtocol_->ostProtoId()
skipUntilEndOfPacket_ = true; == OstProto::Protocol::kHexDumpFieldNumber))
goto _exit; currentPdmlProtocol_->postProtocolHandler(currentStream_);
}
if (!protocolMap_.contains(protoName)) if (!protocolMap_.contains(protoName))
protoName = "unknown"; // FIXME: change to Ost:Hexdump protoName = "unknown"; // FIXME: change to Ost:Hexdump
@ -161,25 +163,26 @@ bool PdmlParser::startElement(const QString & /* namespaceURI */,
int protoId = currentPdmlProtocol_->ostProtoId(); int protoId = currentPdmlProtocol_->ostProtoId();
// PdmlDefaultProtocol =>
if (protoId <= 0)
goto _exit;
OstProto::Protocol *proto = currentStream_->add_protocol();
proto->mutable_protocol_id()->set_id(protoId);
const google::protobuf::Reflection *msgRefl =
proto->GetReflection();
const google::protobuf::FieldDescriptor *fDesc =
msgRefl->FindKnownExtensionByNumber(protoId);
// TODO: if !fDesc
// init default values of all fields in protocol
currentProtocolMsg_ = msgRefl->MutableMessage(proto, fDesc);
currentPdmlProtocol_->preProtocolHandler(protoName, attributes, currentPdmlProtocol_->preProtocolHandler(protoName, attributes,
currentStream_); currentStream_);
if (protoId > 0)
{
OstProto::Protocol *proto = currentStream_->add_protocol();
proto->mutable_protocol_id()->set_id(protoId);
const google::protobuf::Reflection *msgRefl =
proto->GetReflection();
const google::protobuf::FieldDescriptor *fDesc =
msgRefl->FindKnownExtensionByNumber(protoId);
// TODO: if !fDesc
// init default values of all fields in protocol
currentProtocolMsg_ = msgRefl->MutableMessage(proto, fDesc);
}
} }
else if (qName == "field") else if (qName == "field")
{ {
@ -191,16 +194,14 @@ bool PdmlParser::startElement(const QString & /* namespaceURI */,
} }
QString name = attributes.value("name"); QString name = attributes.value("name");
int pos = attributes.value("pos").toInt();
int size = attributes.value("size").toInt();
QString valueStr = attributes.value("value"); QString valueStr = attributes.value("value");
int pos = -1;
int size = -1;
// fields with no name are analysis and should be skipped if (!attributes.value("pos").isEmpty())
if (name.isEmpty()) pos = attributes.value("pos").toInt();
{ if (!attributes.value("size").isEmpty())
skipCount_++; size = attributes.value("size").toInt();
goto _exit;
}
qDebug("\tname:%s, pos:%d, size:%d value:%s", qDebug("\tname:%s, pos:%d, size:%d value:%s",
name.toAscii().constData(), name.toAscii().constData(),
@ -236,6 +237,14 @@ bool PdmlParser::startElement(const QString & /* namespaceURI */,
case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
msgRefl->SetUInt64(currentProtocolMsg_, fDesc, msgRefl->SetUInt64(currentProtocolMsg_, fDesc,
valueStr.toULongLong(&isOk, kBaseHex)); valueStr.toULongLong(&isOk, kBaseHex));
break;
case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
{
QByteArray hexVal = QByteArray::fromHex(valueStr.toUtf8());
std::string str(hexVal.constData(), hexVal.size());
msgRefl->SetString(currentProtocolMsg_, fDesc, str);
break;
}
default: default:
qDebug("%s: unhandled cpptype = %d", __FUNCTION__, qDebug("%s: unhandled cpptype = %d", __FUNCTION__,
fDesc->cpp_type()); fDesc->cpp_type());
@ -262,16 +271,21 @@ bool PdmlParser::endElement(const QString & /* namespaceURI */,
if (qName == "packet") if (qName == "packet")
{ {
if (currentStream_->core().name().size())
{
OstProto::Protocol *proto = currentStream_->add_protocol();
proto->mutable_protocol_id()->set_id(
OstProto::Protocol::kHexDumpFieldNumber);
OstProto::HexDump *hexDump = proto->MutableExtension(OstProto::hexDump);
hexDump->set_content(currentStream_->core().name());
hexDump->set_pad_until_end(false);
currentStream_->mutable_core()->set_name("");
}
packetCount_++; packetCount_++;
if (skipUntilEndOfPacket_) currentPdmlProtocol_ = NULL;
skipUntilEndOfPacket_ = false;
goto _exit;
}
if (skipUntilEndOfPacket_)
{
Q_ASSERT(skipCount_ == 0);
goto _exit; goto _exit;
} }
@ -284,6 +298,7 @@ bool PdmlParser::endElement(const QString & /* namespaceURI */,
if (qName == "proto") if (qName == "proto")
{ {
currentPdmlProtocol_->postProtocolHandler(currentStream_); currentPdmlProtocol_->postProtocolHandler(currentStream_);
//currentPdmlProtocol_ = NULL;
} }
else if (qName == "field") else if (qName == "field")
{ {
@ -331,14 +346,22 @@ void PdmlUnknownProtocol::preProtocolHandler(QString name,
const QXmlAttributes &attributes, OstProto::Stream *stream) const QXmlAttributes &attributes, OstProto::Stream *stream)
{ {
bool isOk; bool isOk;
int size;
int pos = attributes.value("pos").toUInt(&isOk); int pos = attributes.value("pos").toUInt(&isOk);
Q_ASSERT(isOk); if (!isOk)
goto _skip_pos_size_proc;
int size = attributes.value("size").toUInt(&isOk); size = attributes.value("size").toUInt(&isOk);
Q_ASSERT(isOk); if (!isOk)
goto _skip_pos_size_proc;
expPos_ = pos; expPos_ = pos;
endPos_ = expPos_ + size; endPos_ = expPos_ + size;
_skip_pos_size_proc:
OstProto::HexDump *hexDump = stream->mutable_protocol(
stream->protocol_size()-1)->MutableExtension(OstProto::hexDump);
hexDump->set_pad_until_end(false);
} }
void PdmlUnknownProtocol::postProtocolHandler(OstProto::Stream *stream) void PdmlUnknownProtocol::postProtocolHandler(OstProto::Stream *stream)
@ -346,7 +369,7 @@ void PdmlUnknownProtocol::postProtocolHandler(OstProto::Stream *stream)
OstProto::HexDump *hexDump = stream->mutable_protocol( OstProto::HexDump *hexDump = stream->mutable_protocol(
stream->protocol_size()-1)->MutableExtension(OstProto::hexDump); stream->protocol_size()-1)->MutableExtension(OstProto::hexDump);
// Skipped field? Pad with zero! // Skipped field(s) at end? Pad with zero!
if (endPos_ > expPos_) if (endPos_ > expPos_)
{ {
QByteArray hexVal(endPos_ - expPos_, char(0)); QByteArray hexVal(endPos_ - expPos_, char(0));
@ -355,10 +378,11 @@ void PdmlUnknownProtocol::postProtocolHandler(OstProto::Stream *stream)
expPos_ += hexVal.size(); expPos_ += hexVal.size();
} }
Q_ASSERT(expPos_ == endPos_); qDebug("%s: expPos_ = %d, endPos_ = %d\n", __FUNCTION__, expPos_, endPos_);
//Q_ASSERT(expPos_ == endPos_);
hexDump->set_pad_until_end(false); hexDump->set_pad_until_end(false);
expPos_ = -1; endPos_ = expPos_ = -1;
} }
void PdmlUnknownProtocol::unknownFieldHandler(QString name, int pos, int size, void PdmlUnknownProtocol::unknownFieldHandler(QString name, int pos, int size,
@ -367,11 +391,12 @@ void PdmlUnknownProtocol::unknownFieldHandler(QString name, int pos, int size,
OstProto::HexDump *hexDump = stream->mutable_protocol( OstProto::HexDump *hexDump = stream->mutable_protocol(
stream->protocol_size()-1)->MutableExtension(OstProto::hexDump); stream->protocol_size()-1)->MutableExtension(OstProto::hexDump);
qDebug("%s: %s, pos = %d, expPos_ = %d\n", __FUNCTION__, qDebug("%s: %s, pos = %d, expPos_ = %d, endPos_ = %d\n",
name.toAscii().constData(), pos, expPos_); __PRETTY_FUNCTION__, name.toAscii().constData(),
pos, expPos_, endPos_);
// Skipped field? Pad with zero! // Skipped field? Pad with zero!
if (pos > expPos_) if ((pos > expPos_) && (expPos_ < endPos_))
{ {
QByteArray hexVal(pos - expPos_, char(0)); QByteArray hexVal(pos - expPos_, char(0));
@ -379,10 +404,11 @@ void PdmlUnknownProtocol::unknownFieldHandler(QString name, int pos, int size,
expPos_ += hexVal.size(); expPos_ += hexVal.size();
} }
if (pos == expPos_) if ((pos == expPos_) /*&& (pos < endPos_)*/)
{ {
QByteArray hexVal = QByteArray hexVal = attributes.value("unmaskedvalue").isEmpty() ?
QByteArray::fromHex(attributes.value("value").toUtf8()); QByteArray::fromHex(attributes.value("value").toUtf8()) :
QByteArray::fromHex(attributes.value("unmaskedvalue").toUtf8());
hexDump->mutable_content()->append(hexVal.constData(), hexVal.size()); hexDump->mutable_content()->append(hexVal.constData(), hexVal.size());
expPos_ += hexVal.size(); expPos_ += hexVal.size();
@ -414,7 +440,59 @@ PdmlFrameProtocol::PdmlFrameProtocol()
pdmlProtoName_ = "frame"; pdmlProtoName_ = "frame";
} }
#if 1
// ---------------------------------------------------------- //
// PdmlFakeFieldWrapperProtocol //
// ---------------------------------------------------------- //
PdmlFakeFieldWrapperProtocol::PdmlFakeFieldWrapperProtocol()
{
pdmlProtoName_ = "OST:HexDump";
ostProtoId_ = OstProto::Protocol::kHexDumpFieldNumber;
expPos_ = -1;
}
void PdmlFakeFieldWrapperProtocol::preProtocolHandler(QString name,
const QXmlAttributes &attributes, OstProto::Stream *stream)
{
expPos_ = 0;
OstProto::HexDump *hexDump = stream->mutable_protocol(
stream->protocol_size()-1)->MutableExtension(OstProto::hexDump);
hexDump->set_pad_until_end(false);
}
void PdmlFakeFieldWrapperProtocol::postProtocolHandler(OstProto::Stream *stream)
{
OstProto::HexDump *hexDump = stream->mutable_protocol(
stream->protocol_size()-1)->MutableExtension(OstProto::hexDump);
qDebug("%s: expPos_ = %d\n", __FUNCTION__, expPos_);
hexDump->set_pad_until_end(false);
expPos_ = -1;
}
void PdmlFakeFieldWrapperProtocol::unknownFieldHandler(QString name, int pos,
int size, const QXmlAttributes &attributes, OstProto::Stream *stream)
{
OstProto::HexDump *hexDump = stream->mutable_protocol(
stream->protocol_size()-1)->MutableExtension(OstProto::hexDump);
if ((pos == expPos_) && (size >= 0) &&
(!attributes.value("unmaskedvalue").isEmpty() ||
!attributes.value("value").isEmpty()))
{
QByteArray hexVal = attributes.value("unmaskedvalue").isEmpty() ?
QByteArray::fromHex(attributes.value("value").toUtf8()) :
QByteArray::fromHex(attributes.value("unmaskedvalue").toUtf8());
hexDump->mutable_content()->append(hexVal.constData(), hexVal.size());
expPos_ += hexVal.size();
}
}
#endif
// ---------------------------------------------------------- // // ---------------------------------------------------------- //
// PdmlEthProtocol // // PdmlEthProtocol //
// ---------------------------------------------------------- // // ---------------------------------------------------------- //
@ -495,3 +573,134 @@ void PdmlIp4Protocol::postProtocolHandler(OstProto::Stream *stream)
ip4->set_is_override_cksum(true); // FIXME ip4->set_is_override_cksum(true); // FIXME
} }
// ---------------------------------------------------------- //
// PdmlIp6Protocol //
// ---------------------------------------------------------- //
PdmlIp6Protocol::PdmlIp6Protocol()
{
pdmlProtoName_ = "ipv6";
ostProtoId_ = OstProto::Protocol::kIp6FieldNumber;
fieldMap_.insert("ipv6.version", OstProto::Ip6::kVersionFieldNumber);
fieldMap_.insert("ipv6.class", OstProto::Ip6::kTrafficClassFieldNumber);
fieldMap_.insert("ipv6.flow", OstProto::Ip6::kFlowLabelFieldNumber);
fieldMap_.insert("ipv6.plen", OstProto::Ip6::kPayloadLengthFieldNumber);
fieldMap_.insert("ipv6.nxt", OstProto::Ip6::kNextHeaderFieldNumber);
fieldMap_.insert("ipv6.hlim", OstProto::Ip6::kHopLimitFieldNumber);
// ipv6.src and ipv6.dst handled as unknown fields
}
void PdmlIp6Protocol::unknownFieldHandler(QString name, int pos, int size,
const QXmlAttributes &attributes, OstProto::Stream *stream)
{
bool isOk;
if (name == "ipv6.src")
{
OstProto::Ip6 *ip6 = stream->mutable_protocol(
stream->protocol_size()-1)->MutableExtension(OstProto::ip6);
QString addrHexStr = attributes.value("value");
ip6->set_src_addr_hi(addrHexStr.left(16).toULongLong(&isOk, kBaseHex));
ip6->set_src_addr_lo(addrHexStr.right(16).toULongLong(&isOk, kBaseHex));
}
else if (name == "ipv6.dst")
{
OstProto::Ip6 *ip6 = stream->mutable_protocol(
stream->protocol_size()-1)->MutableExtension(OstProto::ip6);
QString addrHexStr = attributes.value("value");
ip6->set_dst_addr_hi(addrHexStr.left(16).toULongLong(&isOk, kBaseHex));
ip6->set_dst_addr_lo(addrHexStr.right(16).toULongLong(&isOk, kBaseHex));
}
}
void PdmlIp6Protocol::postProtocolHandler(OstProto::Stream *stream)
{
OstProto::Ip6 *ip6 = stream->mutable_protocol(
stream->protocol_size()-1)->MutableExtension(OstProto::ip6);
ip6->set_is_override_version(true); // FIXME
ip6->set_is_override_payload_length(true); // FIXME
ip6->set_is_override_next_header(true); // FIXME
}
// ---------------------------------------------------------- //
// PdmlTcpProtocol //
// ---------------------------------------------------------- //
PdmlTcpProtocol::PdmlTcpProtocol()
{
pdmlProtoName_ = "tcp";
ostProtoId_ = OstProto::Protocol::kTcpFieldNumber;
fieldMap_.insert("tcp.srcport", OstProto::Tcp::kSrcPortFieldNumber);
fieldMap_.insert("tcp.dstport", OstProto::Tcp::kDstPortFieldNumber);
fieldMap_.insert("tcp.seq", OstProto::Tcp::kSeqNumFieldNumber);
fieldMap_.insert("tcp.ack", OstProto::Tcp::kAckNumFieldNumber);
fieldMap_.insert("tcp.hdr_len", OstProto::Tcp::kHdrlenRsvdFieldNumber);
fieldMap_.insert("tcp.flags", OstProto::Tcp::kFlagsFieldNumber);
fieldMap_.insert("tcp.window_size", OstProto::Tcp::kWindowFieldNumber);
fieldMap_.insert("tcp.checksum", OstProto::Tcp::kCksumFieldNumber);
fieldMap_.insert("tcp.urgent_pointer", OstProto::Tcp::kUrgPtrFieldNumber);
}
void PdmlTcpProtocol::unknownFieldHandler(QString name, int pos, int size,
const QXmlAttributes &attributes, OstProto::Stream *stream)
{
if (name == "tcp.options")
options_ = QByteArray::fromHex(attributes.value("value").toUtf8());
else if (name == ""
&& attributes.value("show").startsWith("TCP segment data"))
{
segmentData_ = QByteArray::fromHex(attributes.value("value").toUtf8());
stream->mutable_core()->mutable_name()->append(segmentData_.constData(),
segmentData_.size());
}
}
void PdmlTcpProtocol::postProtocolHandler(OstProto::Stream *stream)
{
OstProto::Tcp *tcp = stream->mutable_protocol(
stream->protocol_size()-1)->MutableExtension(OstProto::tcp);
tcp->set_is_override_src_port(true); // FIXME
tcp->set_is_override_dst_port(true); // FIXME
tcp->set_is_override_hdrlen(true); // FIXME
tcp->set_is_override_cksum(true); // FIXME
if (options_.size())
{
OstProto::Protocol *proto = stream->add_protocol();
proto->mutable_protocol_id()->set_id(
OstProto::Protocol::kHexDumpFieldNumber);
OstProto::HexDump *hexDump = proto->MutableExtension(OstProto::hexDump);
hexDump->mutable_content()->append(options_.constData(),
options_.size());
hexDump->set_pad_until_end(false);
options_.resize(0);
}
#if 0
if (segmentData_.size())
{
OstProto::Protocol *proto = stream->add_protocol();
proto->mutable_protocol_id()->set_id(
OstProto::Protocol::kHexDumpFieldNumber);
OstProto::HexDump *hexDump = proto->MutableExtension(OstProto::hexDump);
hexDump->mutable_content()->append(segmentData_.constData(),
segmentData_.size());
hexDump->set_pad_until_end(false);
segmentData_.resize(0);
}
#endif
}

View File

@ -21,11 +21,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "protocol.pb.h" #include "protocol.pb.h"
#include <QByteArray>
#include <QMap> #include <QMap>
#include <QObject> #include <QObject>
#include <QString> #include <QString>
#include <QXmlDefaultHandler> #include <QXmlDefaultHandler>
// TODO: add const where possible
class QXmlSimpleReader; class QXmlSimpleReader;
class QXmlInputSource; class QXmlInputSource;
@ -73,7 +76,6 @@ private:
QMap<QString, PdmlDefaultProtocol*> protocolMap_; QMap<QString, PdmlDefaultProtocol*> protocolMap_;
PdmlDefaultProtocol *currentPdmlProtocol_; PdmlDefaultProtocol *currentPdmlProtocol_;
bool skipUntilEndOfPacket_;
int skipCount_; int skipCount_;
int packetCount_; int packetCount_;
OstProto::StreamConfigList *streams_; OstProto::StreamConfigList *streams_;
@ -112,6 +114,22 @@ public:
PdmlFrameProtocol(); PdmlFrameProtocol();
}; };
#if 1
class PdmlFakeFieldWrapperProtocol : public PdmlDefaultProtocol
{
public:
PdmlFakeFieldWrapperProtocol();
virtual void preProtocolHandler(QString name,
const QXmlAttributes &attributes, OstProto::Stream *stream);
virtual void postProtocolHandler(OstProto::Stream *stream);
virtual void unknownFieldHandler(QString name, int pos, int size,
const QXmlAttributes &attributes, OstProto::Stream *stream);
private:
int expPos_;
};
#endif
class PdmlEthProtocol : public PdmlDefaultProtocol class PdmlEthProtocol : public PdmlDefaultProtocol
{ {
public: public:
@ -129,4 +147,26 @@ public:
const QXmlAttributes &attributes, OstProto::Stream *stream); const QXmlAttributes &attributes, OstProto::Stream *stream);
virtual void postProtocolHandler(OstProto::Stream *stream); virtual void postProtocolHandler(OstProto::Stream *stream);
}; };
class PdmlIp6Protocol : public PdmlDefaultProtocol
{
public:
PdmlIp6Protocol();
virtual void unknownFieldHandler(QString name, int pos, int size,
const QXmlAttributes &attributes, OstProto::Stream *stream);
virtual void postProtocolHandler(OstProto::Stream *stream);
};
class PdmlTcpProtocol : public PdmlDefaultProtocol
{
public:
PdmlTcpProtocol();
virtual void unknownFieldHandler(QString name, int pos, int size,
const QXmlAttributes &attributes, OstProto::Stream *stream);
virtual void postProtocolHandler(OstProto::Stream *stream);
private:
QByteArray options_;
QByteArray segmentData_;
};
#endif #endif

View File

@ -311,7 +311,7 @@ void PcapPort::PortTransmitter::run()
// 'stats callback' function so that both Rx and Tx stats are updated // 'stats callback' function so that both Rx and Tx stats are updated
// together // together
const int kSyncTransmit = 1; const int kSyncTransmit = 0; // temp mask, shd be 1;
int i; int i;
qDebug("sendQueueList_.size = %d", sendQueueList_.size()); qDebug("sendQueueList_.size = %d", sendQueueList_.size());