- added PortStatsFilter

- added PacketDump (test code)
- added PacketTree (not complete)
- Protocol stuff (not complete)
This commit is contained in:
Srivats P. 2008-05-25 11:30:30 +00:00
parent 7e8d8308e3
commit 8251383351
22 changed files with 1832 additions and 440 deletions

175
client/dumpview.cpp Normal file
View File

@ -0,0 +1,175 @@
#include "dumpview.h"
DumpView::DumpView(QWidget *parent)
{
int w, h;
data.resize(73);
// NOTE: Monospaced fonts only !!!!!!!!!!!
setFont(QFont("Courier"));
w = fontMetrics().width('X');
h = fontMetrics().height();
mLineHeight = h;
mCharWidth = w;
mSelectedRow = mSelectedCol = -1;
// calculate width for offset column and the whitespace that follows it
mOffsetPaneTopRect = QRect(0, 0, w*4, h);
mDumpPaneTopRect = QRect(mOffsetPaneTopRect.right()+w*3, 0,
w*((8*3-1)+2+(8*3-1)), h);
mAsciiPaneTopRect = QRect(mDumpPaneTopRect.right()+w*3, 0,
w*(8+1+8), h);
qDebug("DumpView::DumpView");
}
#if 0
QSize DumpView::sizeHint() const
{
}
#endif
void DumpView::mousePressEvent(QMouseEvent *event)
{
int x = event->x();
int row, col;
if (x > mAsciiPaneTopRect.left())
{
col = (x - mAsciiPaneTopRect.left()) / mCharWidth;
if (col == 8) // don't select whitespace
goto _exit;
else if (col > 8) // adjust for whitespace
col--;
}
else if (x > mDumpPaneTopRect.left())
{
col = (x - mDumpPaneTopRect.left()) / (mCharWidth*3);
}
row = event->y()/mLineHeight;
if ((col < 16) && (row < ((data.size()+16)/16)))
{
mSelectedRow = row;
mSelectedCol = col;
}
else
goto _exit;
// last row check col
if ((row == (((data.size()+16)/16) - 1)) && (col >= (data.size() % 16)))
goto _exit;
qDebug("dumpview::selection(%d, %d)", mSelectedRow, mSelectedCol);
update();
return;
_exit:
// Clear existing selection
mSelectedRow = -1;
update();
}
void DumpView::paintEvent(QPaintEvent* event)
{
QStylePainter painter(this);
QRect offsetRect = mOffsetPaneTopRect;
QRect dumpRect = mDumpPaneTopRect;
QRect asciiRect = mAsciiPaneTopRect;
QPalette pal = palette();
QByteArray ba;
//qDebug("dumpview::paintEvent");
// FIXME(LOW): unable to set the self widget's font in constructor
painter.setFont(QFont("Courier"));
// set a white background
painter.fillRect(rect(), QBrush(QColor(Qt::white)));
// display the offset, dump and ascii panes 8 + 8 bytes on a line
for (int i = 0; i < data.size(); i+=16)
{
QString dumpStr, asciiStr;
ba = data.mid(i, 16);
// display offset
painter.drawItemText(offsetRect, Qt::AlignLeft | Qt::AlignTop, pal,
true, QString("%1").arg(i, 4, 16, QChar('0')), QPalette::WindowText);
// construct the dumpStr and asciiStr
for (int j = i; (j < (i+16)) && (j < data.size()); j++)
{
unsigned char c = data.at(j);
// extra space after 8 bytes
if (((j+8) % 16) == 0)
{
dumpStr.append(" ");
asciiStr.append(" ");
}
dumpStr.append(QString("%1").arg((uint)c, 2, 16, QChar('0')).
toUpper()).append(" ");
if (isPrintable(c))
asciiStr.append(QChar(c));
else
asciiStr.append(QChar('.'));
}
// display dump
painter.drawItemText(dumpRect, Qt::AlignLeft | Qt::AlignTop, pal,
true, dumpStr, QPalette::WindowText);
// display ascii
painter.drawItemText(asciiRect, Qt::AlignLeft | Qt::AlignTop, pal,
true, asciiStr, QPalette::WindowText);
// overpaint selection (if any)
if ((i/16) == mSelectedRow)
{
QRect r;
unsigned char c = data.at(mSelectedRow*16+mSelectedCol);
QString selectedAsciiStr, selectedDumpStr;
qDebug("dumpview::paintEvent - Highlighted");
selectedDumpStr.append(QString("%1").arg((uint) c, 2, 16, QChar('0')).toUpper());
if (isPrintable(c))
selectedAsciiStr.append(QChar(c));
else
selectedAsciiStr.append(QChar('.'));
// display dump
r = dumpRect;
if (mSelectedCol < 8)
r.translate(mCharWidth*(mSelectedCol*3), 0);
else
r.translate(mCharWidth*(mSelectedCol*3+1), 0);
r.setWidth(mCharWidth*2);
painter.fillRect(r, pal.highlight());
painter.drawItemText(r, Qt::AlignLeft | Qt::AlignTop, pal,
true, selectedDumpStr, QPalette::HighlightedText);
// display ascii
r = asciiRect;
if (mSelectedCol < 8)
r.translate(mCharWidth*(mSelectedCol), 0);
else
r.translate(mCharWidth*(mSelectedCol+1), 0);
r.setWidth(mCharWidth);
painter.fillRect(r, pal.highlight());
painter.drawItemText(r, Qt::AlignLeft | Qt::AlignTop, pal,
true, selectedAsciiStr, QPalette::HighlightedText);
}
// move the rects down
offsetRect.translate(0, mLineHeight);
dumpRect.translate(0, mLineHeight);
asciiRect.translate(0, mLineHeight);
}
}

34
client/dumpview.h Normal file
View File

@ -0,0 +1,34 @@
#include <QtGui> // FIXME: High
class DumpView: public QWidget // QAbstractItemView // FIXME
{
public:
DumpView(QWidget *parent=0);
// bool setBase(uint base); // valid values: 16, 8, 10, 2 etc.
// void hideAsciiPane(void);
// void showAsciiPane(void);
// void hideOffsetPane(void);
// void showOffsetPane(void);
//QSize sizeHint() const;
protected:
void mousePressEvent(QMouseEvent *event);
//void mouseMoveEvent(QMouseEvent *event);
void paintEvent(QPaintEvent *event);
private:
QString toAscii(QByteArray ba);
bool inline isPrintable(char c)
{if ((c > 48) && (c < 126)) return true; else return false; }
private:
QRect mOffsetPaneTopRect;
QRect mDumpPaneTopRect;
QRect mAsciiPaneTopRect;
QByteArray data;
int mSelectedRow, mSelectedCol;
int mLineHeight;
int mCharWidth;
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 432 B

View File

@ -3,14 +3,17 @@ CONFIG += qt debug
QT += network
RESOURCES += ostinato.qrc
HEADERS += \
dumpview.h \
hexlineedit.h \
mainwindow.h \
mythread.h \
packetmodel.h \
port.h \
portgroup.h \
portgrouplist.h \
portmodel.h \
portstatsmodel.h \
portstatsfilterdialog.h \
portstatswindow.h \
portswindow.h \
streamconfigdialog.h \
@ -18,21 +21,25 @@ HEADERS += \
FORMS += \
mainwindow.ui \
portstatsfilter.ui \
portstatswindow.ui \
portswindow.ui \
streamconfigdialog.ui
SOURCES += \
dumpview.cpp \
stream.cpp \
hexlineedit.cpp \
main.cpp \
mainwindow.cpp \
mythread.cpp \
packetmodel.cpp \
port.cpp \
portgroup.cpp \
portgrouplist.cpp \
portmodel.cpp \
portstatsmodel.cpp \
portstatsfilterdialog.cpp \
portstatswindow.cpp \
portswindow.cpp \
streamconfigdialog.cpp \

View File

@ -12,6 +12,7 @@
<file>icons/portgroup_connect.png</file>
<file>icons/portgroup_delete.png</file>
<file>icons/portgroup_disconnect.png</file>
<file>icons/portstats_filter.png</file>
<file>icons/sound_mute.png</file>
<file>icons/sound_none.png</file>
<file>icons/stream_add.png</file>

440
client/packetmodel.cpp Normal file
View File

@ -0,0 +1,440 @@
#include "packetmodel.h"
PacketModel::PacketModel(Stream *pStream, QObject *parent)
{
mpStream = pStream;
}
int PacketModel::rowCount(const QModelIndex &parent) const
{
// Parent - Invisible Root.
// Children - Top Level Items
if (!parent.isValid())
{
int v = 0;
if (mpStream->l2.eth.vlanMask & VM_SVLAN_TAGGED)
v++;
if (mpStream->l2.eth.vlanMask & VM_CVLAN_TAGGED)
v++;
if (mpStream->proto.protoMask & PM_L3_PROTO_NONE)
return v+2; // L2, Data
if (mpStream->proto.protoMask & PM_L4_PROTO_NONE)
return v+3; // L2, L3, Data
else
return v+4; // L2, L3, L4, Data
}
// Parent - Top Level Item (L2)
// Children(count) - Second Level Items (L2 fields)
if (isIndexL2Container(parent))
{
switch(mpStream->proto.ft)
{
case Stream::e_ft_none:
return 2; // DstMac, SrcMac
break;
case Stream::e_ft_eth_2:
case Stream::e_ft_802_3_raw:
return 3; // DstMac, SrcMac, Type/Len
break;
case Stream::e_ft_802_3_llc:
case Stream::e_ft_snap:
return 5; // DstMac, SrcMac, Type, DSAP, SSAP, CTL, OUI, Type
break;
default:
qDebug("%s: Unsupported frametype", __FUNCTION__);
return -1;
}
}
// Parent - Top Level Item (SVLAN)
// Children(count) - Second Level Items (SVLAN fields)
if (isIndexSvlanContainer(parent))
{
return 4; // TPID, PCP, DE, VlanId
}
// Parent - Top Level Item (CVLAN)
// Children(count) - Second Level Items (CVLAN fields)
if (isIndexCvlanContainer(parent))
{
return 4; // TPID, Prio, CFI, VlanId
}
// Parent - Top Level Item (L3)
// Children(count) - Second Level Items (L3 fields)
if (isIndexL3Container(parent))
{
// L3 cannot be "None"
Q_ASSERT(mpStream->proto.protoMask & PM_L3_PROTO_NONE);
switch(mpStream->proto.etherType)
{
case ETH_TYP_IP:
return 12; // Ver, HdrLen, TOS, TotLen, Id, Flags,
// FragOfs, TTL, Proto, Cksum, SrcIp, DstIp
break;
case ETH_TYP_ARP:
return 0; // TODO(LOW)
break;
default:
qDebug("%s: Unsupported ethtype", __FUNCTION__);
return -1;
}
}
// Parent - Top Level Item (L4)
// Children(count) - Second Level Items (L4 fields)
if (isIndexL4Container(parent))
{
// L4 cannot be "None"
Q_ASSERT(mpStream->proto.protoMask & PM_L4_PROTO_NONE);
switch(mpStream->proto.ipProto)
{
case IP_PROTO_TCP:
return 10; // SrcPort, DstPort, SeqNum, AckNum, HdrLen,
// Rsvd, Flags, Window, Cksum, UrgPtr,
break;
case IP_PROTO_UDP:
return 4; // SrcPort, DstPort, TotLen, Cksum
break;
case IP_PROTO_ICMP:
case IP_PROTO_IGMP:
return 0; // TODO(LOW)
break;
default:
qDebug("%s: Unsupported ethtype", __FUNCTION__);
return -1;
}
}
// Parent - Second Level Item (L2 field)
// Children(count) - Third Level Items (L2 subfield)
if (isIndexL2Field(parent))
{
return 0; // No subfields for any L2 field
}
// Parent - Second Level Item (L3 field)
// Children(count) - Third Level Items (L3 subfield)
if (isIndexL3Field(parent))
{
if (isIndexIpField(parent))
return 0; // TODO (MED)
if (isIndexArpField(parent))
return 0; // TODO (LOW)
qDebug("%s: Unknown L3 Field", __FUNCTION__);
return 0; // catch all
}
// Parent - Second Level Item (L4 field)
// Children(count) - Third Level Items (L4 subfield)
if (isIndexL4Field(parent))
{
if (isIndexTcpField(parent))
return 0; // TODO (MED)
if (isIndexUdpField(parent))
return 0; // No subfields for any UDP fields
if (isIndexIcmpField(parent))
return 0; // TODO (LOW)
if (isIndexIgmpField(parent))
return 0; // TODO (LOW)
qDebug("%s: Unknown L4 Field", __FUNCTION__);
return 0; // catch all
}
//qDebug("%s: Catch all - need to investigate", __FUNCTION__);
return 0; // catch all
}
int PacketModel::columnCount(const QModelIndex &parent) const
{
return 1;
}
QModelIndex PacketModel::index(int row, int col, const QModelIndex &parent) const
{
QModelIndex index;
IndexId id, parentId;
uint vlanMask = mpStream->l2.eth.vlanMask;
if (!hasIndex(row, col, parent))
goto _exit;
parentId.w = parent.internalId();
// Parent - Invisible Root
// Requested child - First/Top Level Item
if (parentId.ws.b2 == 0xFF)
{
Q_ASSERT(!parent.isValid());
if (mpStream->l2.eth.vlanMask & VM_UNTAGGED)
id.ws.b1 = row+2; // Only L2, L3, L4
else if (VM_SINGLE_TAGGED(vlanMask))
{
switch (row)
{
case 0: id.ws.b1 = 2; break; // L2
case 1: id.ws.b1 = (vlanMask & VM_SVLAN_TAGGED)?0x88:0x81; break;
case 2: id.ws.b1 = 3; break; // L3
case 3: id.ws.b1 = 4; break; // L4
case 4: id.ws.b1 = 0; break; // Data
default: qWarning("%s: Unexpected row (%d)", __FUNCTION__, row);
}
}
else if (VM_DOUBLE_TAGGED(vlanMask))
{
switch (row)
{
case 0: id.ws.b1 = 2; break; // L2
case 1: id.ws.b1 = 0x88; break; // SVLAN
case 2: id.ws.b1 = 0x81; break; // CVLAN
case 3: id.ws.b1 = 3; break; // L3
case 4: id.ws.b1 = 4; break; // L4
case 5: id.ws.b1 = 0; break; // Data
default: qWarning("%s: Unexpected row (%d)", __FUNCTION__, row);
}
}
id.ws.b2 = 0xFF;
index = createIndex(row, col, id.w);
goto _exit;
}
// Parent - First Level Item
// Requested child - Second Level Item
if (parentId.ws.b3 == 0xFF)
{
Q_ASSERT(parentId.ws.b1 != 0xFF);
Q_ASSERT(parentId.ws.b2 != 0xFF);
id.ws.b1 = parentId.ws.b1;
id.ws.b2 = 0; // TODO(MED): Set Field Id for subfields
index = createIndex(row, col, id.w);
goto _exit;
}
// Parent - Second Level Item (Field)
// Requested child - Third Level Item (Subfield)
// TODO(MED): Support subfields
// Till then we return an invalid index
_exit:
return index;
}
QModelIndex PacketModel::parent(const QModelIndex &index) const
{
IndexId id, parentId;
id.w = index.internalId();
parentId = id;
// 1st/Top Level Item - Protocol
// Requested Parent => Invisible Root
if (id.ws.b2 == 0xFF)
return QModelIndex();
// Second Level Item - Field
// Requested Parent => 1st Level Item (Protocol)
if (id.ws.b3 == 0xFF)
{
uint vlanMask = mpStream->l2.eth.vlanMask;
int row = -1;
parentId.ws.b2 = 0xFF;
if (vlanMask & VM_UNTAGGED)
{
row = parentId.ws.b1 - 2;
}
else if (VM_SINGLE_TAGGED(vlanMask))
{
switch (parentId.ws.b1)
{
case 2: row = 0; break; // L2
case 0x88:
case 0x81: row = 1; break; // SVlan/CVlan
case 3: row = 2; break; // L3
case 4: row = 3; break; // L4
case 0: row = 4; break; // Data
default: qWarning("%s: Unexpected b1 (%d)", __FUNCTION__, parentId.ws.b1);
}
}
else if (VM_DOUBLE_TAGGED(vlanMask))
{
switch (parentId.ws.b1)
{
case 2: row = 0; break; // L2
case 0x88: row = 1; break; // Svlan
case 0x81: row = 2; break; // CVlan
case 3: row = 3; break; // L3
case 4: row = 4; break; // L4
case 0: row = 5; break; // Data
default: qWarning("%s: Unexpected b1 (%d)", __FUNCTION__, parentId.ws.b1);
}
}
else
qWarning("%s: Unhandled leg", __FUNCTION__);
return createIndex(row, 0, parentId.w);
}
// Third Level Item - Subfield
// Requested Parent => 2nd Level Item (Field)
// TODO(Med)
qWarning("%s: Unexpected leg", __FUNCTION__);
return QModelIndex();
}
QVariant PacketModel::data(const QModelIndex &index, int role) const
{
IndexId id;
id.w = index.internalId();
if (id.ws.b2 == 0xFF)
return QString("Protocol Header");
else
return QString("Field: Value");
}
/*
** --------------- Private Stuff -----------------
*/
typedef union
{
quint32 w;
struct
{
quint8 b1;
quint8 b2;
quint8 b3;
quint8 b4;
} ws;
} IndexId;
bool PacketModel::isIndexContainer(const QModelIndex& index, int level) const
{
IndexId id;
id.w = index.internalId();
if ((id.ws.b1 == level) && (id.ws.b2 == 0xFF))
return true;
else
return false;
}
bool PacketModel::isIndexL2Container(const QModelIndex& index) const
{
return isIndexContainer(index, 2);
}
bool PacketModel::isIndexSvlanContainer(const QModelIndex& index) const
{
return isIndexContainer(index, 0x88);
}
bool PacketModel::isIndexCvlanContainer(const QModelIndex& index) const
{
return isIndexContainer(index, 0x81);
}
bool PacketModel::isIndexL3Container(const QModelIndex& index) const
{
return isIndexContainer(index, 3);
}
bool PacketModel::isIndexL4Container(const QModelIndex& index) const
{
return isIndexContainer(index, 4);
}
bool PacketModel::isIndexField(const QModelIndex& index, int level) const
{
IndexId id;
id.w = index.internalId();
if ((id.ws.b1 == level) && (id.ws.b2 != 0xFF) && (id.ws.b3 == 0xFF))
return true;
else
return false;
}
bool PacketModel::isIndexL2Field(const QModelIndex& index) const
{
return isIndexField(index, 2);
}
bool PacketModel::isIndexL3Field(const QModelIndex& index) const
{
return isIndexField(index, 3);
}
bool PacketModel::isIndexL4Field(const QModelIndex& index) const
{
return isIndexField(index, 4);
}
bool PacketModel::isIndexIpField(const QModelIndex& index) const
{
IndexId id;
id.w = index.internalId();
if ((id.ws.b1 == 3) && (id.ws.b2 == 1) && (id.ws.b3 == 0xFF))
return true;
else
return false;
}
bool PacketModel::isIndexArpField(const QModelIndex& index) const
{
IndexId id;
id.w = index.internalId();
if ((id.ws.b1 == 3) && (id.ws.b2 == 2) && (id.ws.b3 == 0xFF))
return true;
else
return false;
}
bool PacketModel::isIndexL4ProtoField(const QModelIndex& index, int proto) const
{
IndexId id;
id.w = index.internalId();
if ((id.ws.b1 == 4) && (id.ws.b2 == proto) && (id.ws.b3 == 0xFF))
return true;
else
return false;
}
bool PacketModel::isIndexTcpField(const QModelIndex& index) const
{
return isIndexL4ProtoField(index, IP_PROTO_TCP);
}
bool PacketModel::isIndexUdpField(const QModelIndex& index) const
{
return isIndexL4ProtoField(index, IP_PROTO_UDP);
}
bool PacketModel::isIndexIcmpField(const QModelIndex& index) const
{
return isIndexL4ProtoField(index, IP_PROTO_ICMP);
}
bool PacketModel::isIndexIgmpField(const QModelIndex& index) const
{
return isIndexL4ProtoField(index, IP_PROTO_IGMP);
}

52
client/packetmodel.h Normal file
View File

@ -0,0 +1,52 @@
#ifndef _PACKET_MODEL_H
#define _PACKET_MODEL_H
#include <QAbstractItemModel>
#include "stream.h"
class PacketModel: public QAbstractItemModel
{
public:
PacketModel(Stream *pStream, QObject *parent = 0);
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role) const;
QModelIndex index (int row, int col, const QModelIndex & parent = QModelIndex() ) const;
QModelIndex parent(const QModelIndex &index) const;
private:
Stream *mpStream;
typedef union _IndexId
{
quint32 w;
struct
{
quint8 b1; // 1st Level
quint8 b2; // 2nd Level
quint8 b3; // 3rd Level
quint8 b4; // Reserved
} ws;
} IndexId;
bool PacketModel::isIndexContainer(const QModelIndex& index, int level) const;
bool PacketModel::isIndexL2Container(const QModelIndex& index) const;
bool PacketModel::isIndexSvlanContainer(const QModelIndex& index) const;
bool PacketModel::isIndexCvlanContainer(const QModelIndex& index) const;
bool PacketModel::isIndexL3Container(const QModelIndex& index) const;
bool PacketModel::isIndexL4Container(const QModelIndex& index) const;
bool PacketModel::isIndexField(const QModelIndex& index, int level) const;
bool PacketModel::isIndexL2Field(const QModelIndex& index) const;
bool PacketModel::isIndexL3Field(const QModelIndex& index) const;
bool PacketModel::isIndexL4Field(const QModelIndex& index) const;
bool PacketModel::isIndexIpField(const QModelIndex& index) const;
bool PacketModel::isIndexArpField(const QModelIndex& index) const;
bool PacketModel::isIndexL4ProtoField(const QModelIndex& index, int proto) const;
bool PacketModel::isIndexTcpField(const QModelIndex& index) const;
bool PacketModel::isIndexUdpField(const QModelIndex& index) const;
bool PacketModel::isIndexIcmpField(const QModelIndex& index) const;
bool PacketModel::isIndexIgmpField(const QModelIndex& index) const;
};
#endif

View File

@ -18,7 +18,9 @@ void Port::insertDummyStreams()
{
mStreams.append(*(new Stream));
mStreams[0].setName(QString("%1:%2:0").arg(portGroupId()).arg(id()));
#if 1
mStreams.append(*(new Stream));
mStreams[1].setName(QString("%1:%2:1").arg(portGroupId()).arg(id()));
#endif
}

View File

@ -100,9 +100,9 @@ void PortGroup::ProcessCapabilityInfo(const char *msg, qint32 size)
goto _next;
}
p = new Port(NTOHL(cap->port), mPortGroupId);
p->setName(cap->name);
p->setDescription(cap->desc);
p = new Port(NTOHL(cap->portId), mPortGroupId);
p->setName(cap->portName);
p->setDescription(cap->portDesc);
p->insertDummyStreams(); // FIXME: only for testing
qDebug("before port append\n");
mPorts.append(*p);
@ -137,7 +137,7 @@ void PortGroup::when_connected()
pkt.ver = 1;
pkt.resv1 = 0;
pkt.resv2 = 0;
pkt.msgType = HTONS(e_MT_CapabilityReq);
pkt.msgType = HTONS(e_MT_GetCapability);
pkt.msgLen = HTONS(8);
mpSocket->write((char*) &pkt, sizeof(pkt));

View File

@ -1,6 +1,6 @@
<ui version="4.0" >
<class>Dialog</class>
<widget class="QDialog" name="Dialog" >
<class>PortStatsFilterDialog</class>
<widget class="QDialog" name="PortStatsFilterDialog" >
<property name="geometry" >
<rect>
<x>0</x>
@ -16,7 +16,11 @@
<item>
<layout class="QHBoxLayout" >
<item>
<widget class="QListView" name="lvAllPorts" />
<widget class="QListView" name="lvUnselected" >
<property name="selectionMode" >
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" >
@ -34,14 +38,14 @@
</spacer>
</item>
<item>
<widget class="QToolButton" name="tbFilterIn" >
<widget class="QToolButton" name="tbSelectIn" >
<property name="text" >
<string>></string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="tbFilterOut" >
<widget class="QToolButton" name="tbSelectOut" >
<property name="text" >
<string>&lt;</string>
</property>
@ -63,7 +67,11 @@
</layout>
</item>
<item>
<widget class="QListView" name="lvFilteredPorts" />
<widget class="QListView" name="lvSelected" >
<property name="selectionMode" >
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
</widget>
</item>
</layout>
</item>
@ -80,10 +88,10 @@
</layout>
</widget>
<tabstops>
<tabstop>lvAllPorts</tabstop>
<tabstop>tbFilterIn</tabstop>
<tabstop>tbFilterOut</tabstop>
<tabstop>lvFilteredPorts</tabstop>
<tabstop>lvUnselected</tabstop>
<tabstop>tbSelectIn</tabstop>
<tabstop>tbSelectOut</tabstop>
<tabstop>lvSelected</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>
@ -91,7 +99,7 @@
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<receiver>PortStatsFilterDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel" >
@ -107,7 +115,7 @@
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Dialog</receiver>
<receiver>PortStatsFilterDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel" >

View File

@ -1,9 +1,84 @@
#include "portstatsfilterdialog.h"
PortStatsFilterDialog::PortStatsFilterDialog(AbstractItemModel *allPortsModel,
QWidget *parent)
PortStatsFilterDialog::PortStatsFilterDialog(QWidget *parent)
{
setupUi(this);
lvAllPorts->setModel(allPortsModel);
// TODO(MED): Use ExtendedSelection and use "selected" instead of
// "current" for selecting in/out
// TODO(MED): Ensure items are READ-ONLY not editable
// TODO(MED): Enable "double-click" on items
lvUnselected->setSelectionMode(QAbstractItemView::SingleSelection);
lvSelected->setSelectionMode(QAbstractItemView::SingleSelection);
mUnselected.setSortRole(PositionRole);
lvUnselected->setModel(&mUnselected);
lvSelected->setModel(&mSelected);
}
QList<uint> PortStatsFilterDialog::getItemList(bool* ok,
QAbstractItemModel *model, Qt::Orientation orientation,
QList<uint> initial)
{
QList<uint> ret;
uint count = (orientation == Qt::Vertical) ?
model->rowCount() : model->columnCount();
*ok = false;
mUnselected.clear();
mSelected.clear();
for (uint i = 0; i < count; i++)
{
QStandardItem *item;
item = new QStandardItem(model->headerData(i, orientation).toString());
item->setData(i, PositionRole);
if (initial.contains(i))
mSelected.appendRow(item);
else
mUnselected.appendRow(item);
}
// No need to sort right now 'coz we have inserted items in order
if (exec() == QDialog::Accepted)
{
uint count = mSelected.rowCount();
for (uint i = 0; i < count; i++)
{
QModelIndex index = mSelected.index(i, 0, QModelIndex());
QStandardItem *item = mSelected.itemFromIndex(index);
ret.append(item->data(PositionRole).toInt());
}
*ok = true;
}
return ret;
}
void PortStatsFilterDialog::on_tbSelectIn_clicked()
{
QStandardItem *item;
item = mUnselected.takeItem(lvUnselected->currentIndex().row());
if (mUnselected.removeRow(lvUnselected->currentIndex().row()))
mSelected.appendRow(item);
}
void PortStatsFilterDialog::on_tbSelectOut_clicked()
{
QStandardItem *item;
item = mSelected.takeItem(lvSelected->currentIndex().row());
if (mSelected.removeRow(lvSelected->currentIndex().row()))
{
mUnselected.appendRow(item);
mUnselected.sort(0);
}
}

View File

@ -3,7 +3,8 @@
#include <QDialog>
#include <QAbstractItemModel>
#include "ui_portstatsfilterdialog.h"
#include <QStandardItemModel>
#include "ui_portstatsfilter.h"
#include "portgrouplist.h"
class PortStatsFilterDialog : public QDialog, public Ui::PortStatsFilterDialog
@ -11,8 +12,21 @@ class PortStatsFilterDialog : public QDialog, public Ui::PortStatsFilterDialog
Q_OBJECT
public:
PortStatsFilterDialog(AbstractItemModel *allPortsModel,
QWidget *parent = 0);
PortStatsFilterDialog(QWidget *parent = 0);
QList<uint> getItemList(bool* ok, QAbstractItemModel *model,
Qt::Orientation orientation = Qt::Vertical,
QList<uint> initial = QList<uint>());
private:
enum ItemRole {
PositionRole = Qt::UserRole + 1
};
QStandardItemModel mUnselected;
QStandardItemModel mSelected;
private slots:
void on_tbSelectIn_clicked();
void on_tbSelectOut_clicked();
};
#endif

View File

@ -1,15 +1,37 @@
#include "portstatswindow.h"
#include "portstatsmodel.h"
#include "portstatsfilterdialog.h"
#include "QHeaderView"
//PortStatsWindow::PortStatsWindow(QWidget *parent) : QDialog (parent)
PortStatsWindow::PortStatsWindow(PortGroupList *pgl, QWidget *parent)
{
setupUi(this);
tvPortStats->setModel(pgl->getPortStatsModel());
model = pgl->getPortStatsModel();
tvPortStats->setModel(model);
tvPortStats->horizontalHeader()->setMovable(true);
}
PortStatsWindow::~PortStatsWindow()
{
}
void PortStatsWindow::on_tbFilter_clicked()
{
bool ok;
QList<uint> currentColumns, newColumns;
PortStatsFilterDialog dialog;
for(int i = 0; i < model->columnCount(); i++)
if (!tvPortStats->isColumnHidden(i))
currentColumns.append(i);
newColumns = dialog.getItemList(&ok, model, Qt::Horizontal, currentColumns);
if(ok)
for(int i = 0; i < model->columnCount(); i++)
tvPortStats->setColumnHidden(i, !newColumns.contains(i));
}

View File

@ -15,6 +15,9 @@ public:
~PortStatsWindow();
private:
QAbstractItemModel *model;
private slots:
void on_tbFilter_clicked();
};
#endif

View File

@ -1,133 +1,192 @@
<ui version="4.0" >
<class>PortStatsWindow</class>
<widget class="QWidget" name="PortStatsWindow" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>502</width>
<height>415</height>
</rect>
</property>
<property name="windowTitle" >
<string>Form</string>
</property>
<layout class="QVBoxLayout" >
<item>
<widget class="QFrame" name="frame" >
<property name="frameShape" >
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow" >
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" >
<item>
<widget class="QToolButton" name="tbStartTransmit" >
<property name="toolTip" >
<string>Start Transmit</string>
</property>
<property name="statusTip" >
<string>Stop Transmit</string>
</property>
<property name="text" >
<string>Start Transmit</string>
</property>
<property name="icon" >
<iconset resource="ostinato.qrc" >:/icons/control_play.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="tbStopTransmit" >
<property name="toolTip" >
<string>Stop Transmit</string>
</property>
<property name="statusTip" >
<string>Stop Transmit</string>
</property>
<property name="text" >
<string>Stop Trasmit</string>
</property>
<property name="icon" >
<iconset resource="ostinato.qrc" >:/icons/control_stop.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="tbClear" >
<property name="text" >
<string>Clear</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="tbClearAll" >
<property name="text" >
<string>Clear All</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="tbStartCapture" >
<property name="text" >
<string>Start Capture</string>
</property>
<property name="icon" >
<iconset resource="ostinato.qrc" >:/icons/sound_none.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="tbStopCapture" >
<property name="text" >
<string>Stop Capture</string>
</property>
<property name="icon" >
<iconset resource="ostinato.qrc" >:/icons/sound_mute.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="tbViewCapture" >
<property name="text" >
<string>View Capture</string>
</property>
<property name="icon" >
<iconset resource="ostinato.qrc" >:/icons/magnifier.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line" >
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QTableView" name="tvPortStats" />
</item>
</layout>
</widget>
<resources>
<include location="ostinato.qrc" />
</resources>
<connections/>
</ui>
<ui version="4.0" >
<class>PortStatsWindow</class>
<widget class="QWidget" name="PortStatsWindow" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>502</width>
<height>415</height>
</rect>
</property>
<property name="windowTitle" >
<string>Form</string>
</property>
<layout class="QVBoxLayout" >
<item>
<widget class="QFrame" name="frame" >
<property name="toolTip" >
<string>Clear All</string>
</property>
<property name="frameShape" >
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow" >
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" >
<item>
<widget class="QToolButton" name="tbStartTransmit" >
<property name="toolTip" >
<string>Clear All</string>
</property>
<property name="statusTip" >
<string>Starts transmit on selected port(s)</string>
</property>
<property name="text" >
<string>Start Transmit</string>
</property>
<property name="icon" >
<iconset resource="ostinato.qrc" >:/icons/control_play.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="tbStopTransmit" >
<property name="toolTip" >
<string>Clear All</string>
</property>
<property name="statusTip" >
<string>Stops transmit on selected port(s)</string>
</property>
<property name="text" >
<string>Stop Trasmit</string>
</property>
<property name="icon" >
<iconset resource="ostinato.qrc" >:/icons/control_stop.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="tbClear" >
<property name="toolTip" >
<string>Clear All</string>
</property>
<property name="statusTip" >
<string>Clears statistics of the selected port(s)</string>
</property>
<property name="text" >
<string>Clear</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="tbClearAll" >
<property name="toolTip" >
<string>Clear All</string>
</property>
<property name="statusTip" >
<string>Clears statistics of all ports</string>
</property>
<property name="text" >
<string>Clear All</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="tbStartCapture" >
<property name="toolTip" >
<string>Clear All</string>
</property>
<property name="statusTip" >
<string>Captures packets on the selected port(s)</string>
</property>
<property name="text" >
<string>Start Capture</string>
</property>
<property name="icon" >
<iconset resource="ostinato.qrc" >:/icons/sound_none.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="tbStopCapture" >
<property name="toolTip" >
<string>Clear All</string>
</property>
<property name="statusTip" >
<string>End capture on selecteed port(s)</string>
</property>
<property name="text" >
<string>Stop Capture</string>
</property>
<property name="icon" >
<iconset resource="ostinato.qrc" >:/icons/sound_mute.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="tbViewCapture" >
<property name="toolTip" >
<string>Clear All</string>
</property>
<property name="statusTip" >
<string>View captured packets on selected port(s)</string>
</property>
<property name="text" >
<string>View Capture</string>
</property>
<property name="icon" >
<iconset resource="ostinato.qrc" >:/icons/magnifier.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line" >
<property name="toolTip" >
<string>Clear All</string>
</property>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<spacer>
<property name="toolTip" >
<string>Clear All</string>
</property>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="tbFilter" >
<property name="toolTip" >
<string>Clear All</string>
</property>
<property name="statusTip" >
<string>Select which ports to view</string>
</property>
<property name="text" >
<string>Filter</string>
</property>
<property name="icon" >
<iconset resource="ostinato.qrc" >:/icons/portstats_filter.png</iconset>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QTableView" name="tvPortStats" >
<property name="toolTip" >
<string>Clear All</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="ostinato.qrc" />
</resources>
<connections/>
</ui>

View File

@ -6,11 +6,13 @@
class StreamConfigDialog;
class StreamModel;
class PacketModel;
class Stream {
friend class StreamConfigDialog;
friend class StreamModel;
friend class PacketModel;
enum FrameType {
e_ft_none,
@ -114,6 +116,13 @@ class Stream {
#define VM_SVLAN_TAGGED 0x0100
#define VM_SVLAN_TPID_OVERRIDE 0x0200
#define VM_SINGLE_TAGGED(mask) \
((mask & VM_CVLAN_TAGGED ) | (mask & VM_SVLAN_TAGGED))
#define VM_DOUBLE_TAGGED(mask) \
(mask & (VM_CVLAN_TAGGED | VM_SVLAN_TAGGED))
quint16 ctpid;
quint16 cvlanPrio : 3;
quint16 cvlanCfi : 1;

View File

@ -2,6 +2,9 @@
#include "streamconfigdialog.h"
#include "stream.h"
// TODO(LOW): Remove
#include "modeltest.h"
StreamConfigDialog::StreamConfigDialog(QList<Stream> *streamList,
uint streamIndex, QWidget *parent) : QDialog (parent)
{
@ -13,6 +16,12 @@ StreamConfigDialog::StreamConfigDialog(QList<Stream> *streamList,
mCurrentStreamIndex = streamIndex;
LoadCurrentStream();
mpPacketModel = new PacketModel(&((*mpStreamList)[mCurrentStreamIndex]),
this);
tvPacketTree->setModel(mpPacketModel);
mpPacketModelTester = new ModelTest(mpPacketModel);
tvPacketTree->header()->hide();
qDebug("stream %p %d/%d loaded",
mpStreamList, mCurrentStreamIndex, mpStreamList->size());
@ -66,6 +75,8 @@ void StreamConfigDialog::setupUiExtra()
StreamConfigDialog::~StreamConfigDialog()
{
delete mpPacketModelTester;
delete mpPacketModel;
}
void StreamConfigDialog::on_cmbDstMacMode_currentIndexChanged(QString mode)

View File

@ -3,7 +3,9 @@
#include <QDialog>
#include "ui_streamconfigdialog.h"
#include <stream.h>
#include "stream.h"
#include "packetmodel.h"
#include "modeltest.h"
#define MAX_MAC_ITER_COUNT 256
#define MIN_PKT_LEN 64
@ -26,6 +28,8 @@ public:
private:
QList<Stream> *mpStreamList;
uint mCurrentStreamIndex;
PacketModel *mpPacketModel;
ModelTest *mpPacketModelTester;
void setupUiExtra();
void LoadCurrentStream();

View File

@ -33,9 +33,9 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
<string/>
</property>
<property name="currentIndex" >
<number>0</number>
<number>2</number>
</property>
<widget class="QWidget" name="" >
<widget class="QWidget" name="widget" >
<attribute name="title" >
<string>Packet Config</string>
</attribute>
@ -2023,66 +2023,18 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff
<attribute name="title" >
<string>Packet View</string>
</attribute>
<layout class="QVBoxLayout" >
<layout class="QHBoxLayout" >
<item>
<widget class="QSplitter" name="splitter" >
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<widget class="QTreeWidget" name="treeWidget" >
<property name="uniformRowHeights" >
<bool>true</bool>
</property>
<column>
<property name="text" >
<string>New Column</string>
</property>
</column>
<item>
<property name="text" >
<string>Ethernet</string>
</property>
<item>
<property name="text" >
<string>DstMac: 00:00:00:00:00:00</string>
</property>
</item>
<item>
<property name="text" >
<string>SrcMac: 00:00:00:00:00:00</string>
</property>
</item>
<item>
<property name="text" >
<string>EtherType: IP (0800)</string>
</property>
</item>
</item>
<item>
<property name="text" >
<string>IP</string>
</property>
<item>
<property name="text" >
<string>Version: 4</string>
</property>
</item>
<item>
<property name="text" >
<string>Header Length: 20</string>
</property>
</item>
</item>
</widget>
<widget class="QTextEdit" name="textEdit" >
<property name="html" >
<string>&lt;html>&lt;head>&lt;meta name="qrichtext" content="1" />&lt;style type="text/css">
p, li { white-space: pre-wrap; }
&lt;/style>&lt;/head>&lt;body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
&lt;p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;">0004 00 00 00 00 00 00&lt;/p>
&lt;p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;">&lt;/p>&lt;/body>&lt;/html></string>
<widget class="QTreeView" name="tvPacketTree" >
<property name="selectionBehavior" >
<enum>QAbstractItemView::SelectItems</enum>
</property>
</widget>
<widget class="DumpView" native="1" name="vwPacketDump" />
</widget>
</item>
</layout>
@ -2145,6 +2097,12 @@ p, li { white-space: pre-wrap; }
<extends>QLineEdit</extends>
<header location="global" >hexlineedit.h</header>
</customwidget>
<customwidget>
<class>DumpView</class>
<extends>QWidget</extends>
<header>dumpview.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>twTopLevel</tabstop>
@ -2347,12 +2305,12 @@ p, li { white-space: pre-wrap; }
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>79</x>
<y>247</y>
<x>101</x>
<y>276</y>
</hint>
<hint type="destinationlabel" >
<x>99</x>
<y>247</y>
<x>101</x>
<y>276</y>
</hint>
</hints>
</connection>
@ -2363,12 +2321,12 @@ p, li { white-space: pre-wrap; }
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>79</x>
<y>247</y>
<x>101</x>
<y>276</y>
</hint>
<hint type="destinationlabel" >
<x>99</x>
<y>247</y>
<x>101</x>
<y>276</y>
</hint>
</hints>
</connection>
@ -2443,12 +2401,12 @@ p, li { white-space: pre-wrap; }
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>79</x>
<y>247</y>
<x>101</x>
<y>276</y>
</hint>
<hint type="destinationlabel" >
<x>99</x>
<y>247</y>
<x>101</x>
<y>276</y>
</hint>
</hints>
</connection>
@ -2459,44 +2417,44 @@ p, li { white-space: pre-wrap; }
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>79</x>
<y>247</y>
<x>101</x>
<y>276</y>
</hint>
<hint type="destinationlabel" >
<x>101</x>
<y>276</y>
</hint>
</hints>
</connection>
<connection>
<sender>rbFtNone</sender>
<signal>toggled(bool)</signal>
<receiver>lblDsap</receiver>
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>58</x>
<y>218</y>
</hint>
</hints>
</connection>
<connection>
<sender>rbFtNone</sender>
<signal>toggled(bool)</signal>
<receiver>leDsap</receiver>
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>99</x>
<y>247</y>
</hint>
</hints>
</connection>
<connection>
<sender>rbFtNone</sender>
<signal>toggled(bool)</signal>
<receiver>lblDsap</receiver>
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>186</y>
</hint>
<hint type="destinationlabel" >
<x>137</x>
<y>185</y>
</hint>
</hints>
</connection>
<connection>
<sender>rbFtNone</sender>
<signal>toggled(bool)</signal>
<receiver>leDsap</receiver>
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>186</y>
</hint>
<hint type="destinationlabel" >
<x>178</x>
<y>185</y>
<y>218</y>
</hint>
</hints>
</connection>
@ -2507,12 +2465,12 @@ p, li { white-space: pre-wrap; }
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>186</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>137</x>
<y>211</y>
<x>58</x>
<y>218</y>
</hint>
</hints>
</connection>
@ -2523,12 +2481,12 @@ p, li { white-space: pre-wrap; }
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>186</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>178</x>
<y>211</y>
<x>99</x>
<y>218</y>
</hint>
</hints>
</connection>
@ -2539,8 +2497,8 @@ p, li { white-space: pre-wrap; }
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>186</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>137</x>
@ -2555,12 +2513,12 @@ p, li { white-space: pre-wrap; }
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>186</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>178</x>
<y>237</y>
<x>99</x>
<y>218</y>
</hint>
</hints>
</connection>
@ -2571,12 +2529,12 @@ p, li { white-space: pre-wrap; }
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>186</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>137</x>
<y>263</y>
<x>58</x>
<y>218</y>
</hint>
</hints>
</connection>
@ -2587,12 +2545,12 @@ p, li { white-space: pre-wrap; }
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>186</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>178</x>
<y>263</y>
<x>99</x>
<y>218</y>
</hint>
</hints>
</connection>
@ -2603,12 +2561,12 @@ p, li { white-space: pre-wrap; }
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>186</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>137</x>
<y>289</y>
<x>58</x>
<y>218</y>
</hint>
</hints>
</connection>
@ -2619,12 +2577,12 @@ p, li { white-space: pre-wrap; }
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>186</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>178</x>
<y>289</y>
<x>99</x>
<y>218</y>
</hint>
</hints>
</connection>
@ -2635,12 +2593,12 @@ p, li { white-space: pre-wrap; }
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>211</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>137</x>
<y>185</y>
<x>58</x>
<y>218</y>
</hint>
</hints>
</connection>
@ -2651,12 +2609,12 @@ p, li { white-space: pre-wrap; }
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>211</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>178</x>
<y>185</y>
<x>99</x>
<y>218</y>
</hint>
</hints>
</connection>
@ -2667,12 +2625,12 @@ p, li { white-space: pre-wrap; }
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>211</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>137</x>
<y>211</y>
<x>58</x>
<y>218</y>
</hint>
</hints>
</connection>
@ -2683,12 +2641,12 @@ p, li { white-space: pre-wrap; }
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>211</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>178</x>
<y>211</y>
<x>99</x>
<y>218</y>
</hint>
</hints>
</connection>
@ -2699,8 +2657,8 @@ p, li { white-space: pre-wrap; }
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>236</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>137</x>
@ -2715,12 +2673,12 @@ p, li { white-space: pre-wrap; }
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>236</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>178</x>
<y>237</y>
<x>99</x>
<y>218</y>
</hint>
</hints>
</connection>
@ -2731,8 +2689,8 @@ p, li { white-space: pre-wrap; }
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>211</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>137</x>
@ -2747,12 +2705,12 @@ p, li { white-space: pre-wrap; }
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>211</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>178</x>
<y>237</y>
<x>99</x>
<y>218</y>
</hint>
</hints>
</connection>
@ -2763,12 +2721,12 @@ p, li { white-space: pre-wrap; }
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>211</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>137</x>
<y>263</y>
<x>58</x>
<y>218</y>
</hint>
</hints>
</connection>
@ -2779,12 +2737,12 @@ p, li { white-space: pre-wrap; }
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>211</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>178</x>
<y>263</y>
<x>99</x>
<y>218</y>
</hint>
</hints>
</connection>
@ -2795,12 +2753,12 @@ p, li { white-space: pre-wrap; }
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>236</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>137</x>
<y>185</y>
<x>58</x>
<y>218</y>
</hint>
</hints>
</connection>
@ -2811,12 +2769,12 @@ p, li { white-space: pre-wrap; }
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>236</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>178</x>
<y>185</y>
<x>99</x>
<y>218</y>
</hint>
</hints>
</connection>
@ -2827,12 +2785,12 @@ p, li { white-space: pre-wrap; }
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>236</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>137</x>
<y>211</y>
<x>58</x>
<y>218</y>
</hint>
</hints>
</connection>
@ -2843,12 +2801,12 @@ p, li { white-space: pre-wrap; }
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>236</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>178</x>
<y>211</y>
<x>99</x>
<y>218</y>
</hint>
</hints>
</connection>
@ -2859,8 +2817,8 @@ p, li { white-space: pre-wrap; }
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>236</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>137</x>
@ -2875,12 +2833,12 @@ p, li { white-space: pre-wrap; }
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>236</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>178</x>
<y>237</y>
<x>99</x>
<y>218</y>
</hint>
</hints>
</connection>
@ -2891,12 +2849,12 @@ p, li { white-space: pre-wrap; }
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>236</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>137</x>
<y>263</y>
<x>58</x>
<y>218</y>
</hint>
</hints>
</connection>
@ -2907,12 +2865,12 @@ p, li { white-space: pre-wrap; }
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>236</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>178</x>
<y>263</y>
<x>99</x>
<y>218</y>
</hint>
</hints>
</connection>
@ -2923,12 +2881,12 @@ p, li { white-space: pre-wrap; }
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>236</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>137</x>
<y>289</y>
<x>58</x>
<y>218</y>
</hint>
</hints>
</connection>
@ -2939,12 +2897,12 @@ p, li { white-space: pre-wrap; }
<slot>setHidden(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>236</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>178</x>
<y>289</y>
<x>99</x>
<y>218</y>
</hint>
</hints>
</connection>
@ -2987,12 +2945,12 @@ p, li { white-space: pre-wrap; }
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>286</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>178</x>
<y>185</y>
<x>99</x>
<y>218</y>
</hint>
</hints>
</connection>
@ -3003,12 +2961,12 @@ p, li { white-space: pre-wrap; }
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>286</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>178</x>
<y>211</y>
<x>99</x>
<y>218</y>
</hint>
</hints>
</connection>
@ -3019,12 +2977,12 @@ p, li { white-space: pre-wrap; }
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>43</x>
<y>286</y>
<x>57</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>178</x>
<y>237</y>
<x>99</x>
<y>218</y>
</hint>
</hints>
</connection>
@ -3035,12 +2993,12 @@ p, li { white-space: pre-wrap; }
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>355</x>
<y>196</y>
<x>570</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>300</x>
<y>291</y>
<x>570</x>
<y>302</y>
</hint>
</hints>
</connection>
@ -3051,12 +3009,12 @@ p, li { white-space: pre-wrap; }
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>355</x>
<y>196</y>
<x>570</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>372</x>
<y>291</y>
<x>570</x>
<y>302</y>
</hint>
</hints>
</connection>
@ -3067,12 +3025,12 @@ p, li { white-space: pre-wrap; }
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>355</x>
<y>196</y>
<x>570</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>443</x>
<y>291</y>
<x>570</x>
<y>302</y>
</hint>
</hints>
</connection>
@ -3083,12 +3041,12 @@ p, li { white-space: pre-wrap; }
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>355</x>
<y>196</y>
<x>570</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>372</x>
<y>267</y>
<x>570</x>
<y>302</y>
</hint>
</hints>
</connection>
@ -3099,12 +3057,12 @@ p, li { white-space: pre-wrap; }
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>355</x>
<y>196</y>
<x>570</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>443</x>
<y>267</y>
<x>570</x>
<y>302</y>
</hint>
</hints>
</connection>
@ -3115,12 +3073,12 @@ p, li { white-space: pre-wrap; }
<slot>click()</slot>
<hints>
<hint type="sourcelabel" >
<x>300</x>
<y>196</y>
<x>570</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>300</x>
<y>267</y>
<x>570</x>
<y>302</y>
</hint>
</hints>
</connection>
@ -3131,12 +3089,12 @@ p, li { white-space: pre-wrap; }
<slot>click()</slot>
<hints>
<hint type="sourcelabel" >
<x>407</x>
<y>196</y>
<x>570</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>300</x>
<y>267</y>
<x>570</x>
<y>302</y>
</hint>
</hints>
</connection>
@ -3147,12 +3105,12 @@ p, li { white-space: pre-wrap; }
<slot>click()</slot>
<hints>
<hint type="sourcelabel" >
<x>457</x>
<y>196</y>
<x>570</x>
<y>218</y>
</hint>
<hint type="destinationlabel" >
<x>300</x>
<y>267</y>
<x>570</x>
<y>302</y>
</hint>
</hints>
</connection>
@ -3163,12 +3121,12 @@ p, li { white-space: pre-wrap; }
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>334</x>
<y>147</y>
<x>224</x>
<y>207</y>
</hint>
<hint type="destinationlabel" >
<x>411</x>
<y>177</y>
<x>224</x>
<y>209</y>
</hint>
</hints>
</connection>
@ -3179,12 +3137,12 @@ p, li { white-space: pre-wrap; }
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>38</x>
<y>73</y>
<x>125</x>
<y>207</y>
</hint>
<hint type="destinationlabel" >
<x>180</x>
<y>284</y>
<x>191</x>
<y>236</y>
</hint>
</hints>
</connection>
@ -3195,12 +3153,12 @@ p, li { white-space: pre-wrap; }
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>46</x>
<y>98</y>
<x>125</x>
<y>207</y>
</hint>
<hint type="destinationlabel" >
<x>162</x>
<y>313</y>
<x>173</x>
<y>236</y>
</hint>
</hints>
</connection>
@ -3211,12 +3169,12 @@ p, li { white-space: pre-wrap; }
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel" >
<x>73</x>
<y>108</y>
<x>125</x>
<y>207</y>
</hint>
<hint type="destinationlabel" >
<x>225</x>
<y>184</y>
<x>224</x>
<y>216</y>
</hint>
</hints>
</connection>

View File

@ -31,23 +31,139 @@ typedef struct {
} tCommHdr;
typedef enum {
e_MT_CapabilityReq=1,
e_MT_CapabilityInfo
e_MT_GetCapability=1, // C-->S
e_MT_CapabilityInfo, // C<--S
e_MT_ChangePortConfig, // C-->S
e_MT_GetPortConfig, // C-->S
e_MT_PortInfo, // C<--S
e_MT_StartTx, // C-->S
e_MT_StopTx, // C-->S
e_MT_StartCapture, // C-->S
e_MT_StopCapture, // C-->S
e_MT_GetCaptureBuffer, // C-->S
e_MT_CaptureBufferInfo, // C-->S
e_MT_GetStats, // C-->S
e_MT_StatsInfo, // C<--S
e_MT_ClearStats, // C-->S
} eMsgType;
typedef enum {
e_TT_PortCapability
e_TT_PortCapability=0x0000,
e_TT_StreamOper = 0x0100,
e_TT_StreamName,
e_TT_StreamStatus,
e_TT_StreamFrameLength,
e_TT_StreamDataPattern,
e_TT_StreamHeaderData,
} eTlvType;
typedef struct {
UINT16 tlvType;
UINT16 tlvLen;
UINT32 port;
UINT32 speed;
} tTlv;
typedef struct {
UINT16 tlvType;
UINT16 tlvLen;
UINT32 portId;
UINT32 portSpeed;
#define TLV_MAX_PORT_NAME 64
#define TLV_MAX_PORT_DESC 64
char name[TLV_MAX_PORT_NAME];
char desc[TLV_MAX_PORT_DESC];
char portName[TLV_MAX_PORT_NAME];
char portDesc[TLV_MAX_PORT_DESC];
} tTlvPortCapability;
typedef struct {
UINT16 tlvType;
UINT16 tlvLen;
UINT32 portId;
UINT32 streamId;
} tTlvStream;
typedef struct {
UINT16 tlvType;
UINT16 tlvLen;
UINT32 portId;
UINT32 streamId;
UINT16 rsvd;
UINT16 streamOper;
#define TLV_STREAM_OPER_INSERT_HEAD 0x0001
#define TLV_STREAM_OPER_INSERT_TAIL 0x0002
#define TLV_STREAM_OPER_INSERT_BEFORE 0x0003
#define TLV_STREAM_OPER_DELETE 0x0010
UINT32 StreamId;
} tTlvStreamOper;
typedef struct {
UINT16 tlvType;
UINT16 tlvLen;
UINT32 portId;
UINT32 streamId;
char streamName[0];
} tTlvStreamName;
typedef struct {
UINT16 tlvType;
UINT16 tlvLen;
UINT32 portId;
UINT32 streamId;
UINT32 streamStatus;
#define TLV_STREAM_STATUS_DISABLED 0
#define TLV_STREAM_STATUS_ENABLED 1
} tTlvStreamStatus;
typedef struct {
UINT16 tlvType;
UINT16 tlvLen;
UINT32 portId;
UINT32 streamId;
UINT16 frameLenMode;
#define TLV_STREAM_FRAME_LEN_MODE_FIXED 0x0000
#define TLV_STREAM_FRAME_LEN_MODE_RANDOM 0x0001
#define TLV_STREAM_FRAME_LEN_MODE_INCREMENT 0x0002
#define TLV_STREAM_FRAME_LEN_MODE_DECREMENT 0x0003
UINT16 frameLen;
UINT16 frameLenMin;
UINT16 frameLenMax;
} tTlvStreamFrameLength;
typedef struct {
UINT16 tlvType;
UINT16 tlvLen;
UINT32 portId;
UINT32 streamId;
UINT16 dataPatternMode;
#define TLV_STREAM_DATA_PATTERN_MODE_FIXED 0x0000
#define TLV_STREAM_DATA_PATTERN_MODE_RANDOM 0x0001
#define TLV_STREAM_DATA_PATTERN_MODE_INCREMENT 0x0002
#define TLV_STREAM_DATA_PATTERN_MODE_DECREMENT 0x0003
UINT16 rsvd;
UINT32 dataPattern;
} tTlvStreamDataPattern;
typedef struct {
UINT16 tlvType;
UINT16 tlvLen;
UINT32 portId;
UINT32 streamId;
UINT16 rsvd;
UINT16 headerLen;
UINT8 header[0];
} tTlvStreamHeaderData;
typedef union {
tTlvStream tlv;
tTlvStreamOper oper;
tTlvStreamName name;
tTlvStreamStatus status;
tTlvStreamFrameLength frameLen;
tTlvStreamDataPattern dataPattern;
tTlvStreamHeaderData headerData;
} uTlvStream;
#endif

View File

@ -1,6 +1,8 @@
#include "qtglobal" // FIXME: needed only for qdebug
#include "rxtx.h"
#include "../common/protocol.h"
#include "qtglobal" // FIXME: needed only for qdebug
//#define LOG(...) drone->ui.teLOG->append(QString().sprintf( __VA_ARGS__))
//#define LOG(...) drone->LOG(QString().sprintf( __VA_ARGS__))
@ -36,6 +38,8 @@ RxTx::RxTx(AbstractHost *host)
{
portInfo[i].portId = i;
portInfo[i].dev = d;
portInfo[i].streamHead = NULL;
portInfo[i].streamTail = NULL;
#if 1
LOG("%d. %s", i, d->name);
if (d->description)
@ -67,13 +71,17 @@ RxTx::LOG(char* fmt, ...)
RxTx::~RxTx()
{
unsigned int i;
for (i = 0; i < numPorts; i++)
DeleteAllStreams(i);
pcap_freealldevs(alldevs);
}
void RxTx::ProcessMsg(const char* msg, int len)
{
tCommHdr *hdr;
// TODO: For now, assuming we'll get a complete msg
// TODO: For now assuming we'll get a complete msg
// but need to fix this as this is a TCP stream
hdr = (tCommHdr*) msg;
@ -87,9 +95,15 @@ void RxTx::ProcessMsg(const char* msg, int len)
qDebug("msgType - %x: %x\n", hdr->msgType, NTOHS(hdr->msgType));
switch (NTOHS(hdr->msgType))
{
case e_MT_CapabilityReq:
case e_MT_GetCapability:
SendCapabilityInfo();
break;
case e_MT_ChangePortConfig:
ProcessPortConfig(msg+sizeof(tCommHdr), len - sizeof(tCommHdr));
break;
case e_MT_GetPortConfig:
SendPortInfo();
break;
default:
LOG("Rcvd msg with unrecognized msgType %d\n", NTOHS(hdr->msgType));
@ -114,20 +128,20 @@ void RxTx::SendCapabilityInfo(void)
// TLV: Port Capability
((tTlvPortCapability*)(p))->tlvType = HTONS(e_TT_PortCapability);
((tTlvPortCapability*)(p))->tlvLen = HTONS(sizeof(tTlvPortCapability));
((tTlvPortCapability*)(p))->port = HTONL(portInfo[i].portId);
((tTlvPortCapability*)(p))->speed = 0; // TODO
((tTlvPortCapability*)(p))->portId = HTONL(portInfo[i].portId);
((tTlvPortCapability*)(p))->portSpeed = 0; // TODO
#if 0
strncpy(((tTlvPortCapability*)(p))->name,
portInfo[i].dev->name, TLV_MAX_PORT_NAME);
((tTlvPortCapability*)(p))->name[TLV_MAX_PORT_NAME-1] = 0;
#else
strcpy(((tTlvPortCapability*)(p))->name, "eth");
strcpy(((tTlvPortCapability*)(p))->portName, "eth");
//strcat(((tTlvPortCapability*)(p))->name, itoa(portInfo[i].portId, NULL, 10));
itoa(portInfo[i].portId, &(((tTlvPortCapability*)(p))->name[3]), 10);
itoa(portInfo[i].portId, &(((tTlvPortCapability*)(p))->portName[3]), 10);
#endif
strncpy(((tTlvPortCapability*)(p))->desc,
strncpy(((tTlvPortCapability*)(p))->portDesc,
portInfo[i].dev->description, TLV_MAX_PORT_DESC);
((tTlvPortCapability*)(p))->desc[TLV_MAX_PORT_DESC -1] = 0;
((tTlvPortCapability*)(p))->portDesc[TLV_MAX_PORT_DESC -1] = 0;
p += sizeof(tTlvPortCapability);
}
msgLen = (p - msg);
@ -145,3 +159,350 @@ void RxTx::SendCapabilityInfo(void)
host->Log(logStr);
host->SendMsg(pktBuff, msgLen);
}
void RxTx::ProcessPortConfig(const char* msg, int len)
{
// ASSUMPTION: msg points to start of first TLV
UINT8 *p = (UINT8*) msg;
uTlvStream u;
Stream *s;
// Extract and process each TLV
while (len)
{
if (len < 12)
{
LOG("Length (%d) Error - not enough to fit a TLV", len);
goto _exit;
}
u.tlv.tlvType = NTOHS(GET16(p));
u.tlv.tlvLen = NTOHS(GET16(p+2));
u.tlv.portId = NTOHL(GET32(p+4));
u.tlv.streamId = NTOHL(GET32(p+8));
p += 12;
len -= 12;
// Locate the correct node for processing
if (u.tlv.portId >= numPorts)
goto _next_tlv;
s = GetStream(u.tlv.portId, u.tlv.streamId);
if ((s == NULL) && (u.tlv.tlvType!= e_TT_StreamOper))
{
LOG("Unrecognized stream Id %d\n", u.tlv.streamId);
goto _next_tlv;
}
switch(u.tlv.tlvType)
{
case e_TT_StreamOper:
u.oper.streamOper = NTOHS(GET16(p+2));
switch (u.oper.streamOper)
{
case TLV_STREAM_OPER_DELETE:
if (!DeleteStream(u.tlv.portId, u.tlv.streamId))
{
LOG("No Stream with id %d currently in list\n",
u.tlv.streamId);
goto _next_tlv;
}
break;
case TLV_STREAM_OPER_INSERT_HEAD:
s = new Stream;
s->id = u.tlv.streamId;
InsertStreamAtHead(u.tlv.portId, s);
break;
case TLV_STREAM_OPER_INSERT_TAIL:
s = new Stream;
s->id = u.tlv.streamId;
InsertStreamAtTail(u.tlv.portId, s);
break;
case TLV_STREAM_OPER_INSERT_BEFORE:
{
UINT32 nextStreamId;
s = new Stream;
s->id = u.tlv.streamId;
nextStreamId = NTOHS(GET32(p+4));
if (!InsertStreamBefore(u.tlv.portId, s, nextStreamId))
{
LOG("List Empty or No stream with id %d "
"currently in list\n", nextStreamId);
goto _next_tlv;
}
break;
}
default:
LOG("Unrecognized Stream Oper %d\n",
u.oper.streamOper);
goto _next_tlv;
}
break;
case e_TT_StreamName:
strncpy(s->name, (char*) p, MAX_STREAM_NAME_SIZE);
break;
case e_TT_StreamStatus:
u.status.streamStatus = NTOHL(GET32(p));
if (u.status.streamStatus == TLV_STREAM_STATUS_DISABLED)
s->flags |= STREAM_FLAG_VALUE_STATUS_DISABLED; // FIXME
else if (u.status.streamStatus == TLV_STREAM_STATUS_ENABLED)
s->flags |= STREAM_FLAG_VALUE_STATUS_ENABLED; // FIXME
else
goto _next_tlv;
break;
case e_TT_StreamFrameLength:
u.frameLen.frameLenMode = NTOHS(GET16(p));
u.frameLen.frameLen = NTOHS(GET16(p+2));
u.frameLen.frameLenMin = NTOHS(GET16(p+4));
u.frameLen.frameLenMax = NTOHS(GET16(p+6));
s->pktLen = u.frameLen.frameLen;
// FIXME: other frameLen params
break;
case e_TT_StreamDataPattern:
u.dataPattern.dataPatternMode = NTOHS(GET16(p));
u.dataPattern.dataPattern = NTOHS(GET32(p+4));
s->dataPattern = u.dataPattern.dataPattern;
// FIXME: other dataPattern params
break;
case e_TT_StreamHeaderData:
u.headerData.headerLen = NTOHS(GET16(p+2));
s->hdrLen = u.headerData.headerLen;
memcpy(s->pktHdr, p+4, u.headerData.headerLen);
break;
default:
LOG("Unrecognizeed/Unexpected TLV %d\n", u.tlv.tlvType);
}
_next_tlv:
p += u.tlv.tlvLen;
len -= u.tlv.tlvLen;
}
_exit:
return;
}
void RxTx::SendPortInfo(unsigned int port)
{
// Assumption: port is valid
assert(port < numPorts);
}
/*
** --------------------- STREAM LIST OPERATIONS -------------------------
*/
void RxTx::InsertStreamAtHead(unsigned int port, Stream *s)
{
if (portInfo[port].streamHead == NULL)
{
// list empty - first entry being added
s->next = NULL;
portInfo[port].streamHead = portInfo[port].streamTail = s;
}
else
{
// at least one entry in list, so tail does not change
s->next = portInfo[port].streamHead;
portInfo[port].streamHead = s;
}
}
void RxTx::InsertStreamAtTail(unsigned int port, Stream *s)
{
s->next = NULL;
if (portInfo[port].streamHead == NULL)
{
// list empty - first entry being added
portInfo[port].streamHead = portInfo[port].streamTail = s;
}
else
{
// at least one entry in list, so head does not change
portInfo[port].streamTail->next = s;
portInfo[port].streamTail = s;
}
}
bool RxTx::InsertStreamBefore(unsigned int port, Stream *s,
unsigned int nextStreamId)
{
Stream *q, *r;
// For an "Insert Before", list cannot be empty
if (portInfo[port].streamHead == NULL)
{
LOG("Cannot 'insert before' in an empty list");
return false;
}
// Traverse with 'r' and keep track of previous with 'q'
q = NULL;
r = portInfo[port].streamHead;
while (r != NULL)
{
if (r->id == nextStreamId)
{
if (r == portInfo[port].streamHead)
{
// Insert at Head
s->next = portInfo[port].streamHead;
portInfo[port].streamHead = s;
}
else if (r == portInfo[port].streamTail)
{
// Insert one before Tail
s->next = portInfo[port].streamTail;
q->next = s;
}
else
{
s->next = r;
q->next = s;
}
break;
}
q = r;
r = r->next;
}
if (r == NULL)
return false;
else
return true;
}
bool RxTx::DeleteStream(unsigned int port, Stream *s)
{
Stream *q, *r;
// Traverse with 'r' and keep track of prev with 'q'
q = NULL;
r = portInfo[port].streamHead;
while (r != NULL)
{
if (r == s)
{
if (r == portInfo[port].streamHead)
{
if (portInfo[port].streamHead == portInfo[port].streamTail)
{
portInfo[port].streamHead = NULL;
portInfo[port].streamTail = NULL;
}
else
portInfo[port].streamHead = portInfo[port].streamHead->next;
}
else if (r == portInfo[port].streamTail)
{
q->next = NULL;
portInfo[port].streamTail = q;
}
else
{
q->next = r->next;
}
delete r;
break;
}
q = r;
r = r->next;
}
if (r == NULL)
return false;
else
return true;
}
bool RxTx::DeleteStream(unsigned int port, unsigned int streamId)
{
Stream *q, *r;
// Traverse with 'r' and keep track of prev with 'q'
q = NULL;
r = portInfo[port].streamHead;
while (r != NULL)
{
if (r->id == streamId)
{
if (r == portInfo[port].streamHead)
{
if (portInfo[port].streamHead == portInfo[port].streamTail)
{
portInfo[port].streamHead = NULL;
portInfo[port].streamTail = NULL;
}
else
portInfo[port].streamHead = portInfo[port].streamHead->next;
}
else if (r == portInfo[port].streamTail)
{
q->next = NULL;
portInfo[port].streamTail = q;
}
else
{
q->next = r->next;
}
delete r;
break;
}
q = r;
r = r->next;
}
if (r == NULL)
return false;
else
return true;
}
void RxTx::DeleteAllStreams(unsigned int port)
{
Stream *r, *q;
r = portInfo[port].streamHead;
while (r != NULL)
{
q = r;
r = r->next;
delete q;
}
}
Stream* RxTx::GetStream(unsigned int port, unsigned int streamId)
{
Stream *r;
r = portInfo[port].streamHead;
while (r != NULL)
{
if (r->id == streamId)
return r;
r = r->next;
}
return NULL;
}

View File

@ -4,11 +4,41 @@
#include "pcap.h"
#include "abstracthost.h"
#define GET16(x) (UINT16)( \
(*((UINT8*)x+0) << 16 ) \
| (*((UINT8*)x+1)))
#define GET32(x) (UINT32)( \
(*((UINT8*)x+0) << 24) \
| (*((UINT8*)x+1) << 16) \
| (*((UINT8*)x+2) << 8 ) \
| (*((UINT8*)x+3)))
#define MAX_PKT_HDR_SIZE 1536
#define MAX_STREAM_NAME_SIZE 64
typedef struct _Stream
{
unsigned int id;
char name[MAX_STREAM_NAME_SIZE];
unsigned char pktHdr[MAX_PKT_HDR_SIZE];
unsigned short hdrLen;
unsigned short pktLen;
unsigned int dataPattern;
unsigned int flags;
#define STREAM_FLAG_MASK_STATUS 0x00000001
#define STREAM_FLAG_VALUE_STATUS_DISABLED 0x00000000
#define STREAM_FLAG_VALUE_STATUS_ENABLED 0x00000001
struct _Stream *next;
} Stream;
typedef struct
{
unsigned int portId;
pcap_if_t *dev;
Stream *streamHead;
Stream *streamTail;
} PortInfo;
class RxTx
@ -28,8 +58,19 @@ class RxTx
PortInfo *portInfo;
pcap_if_t *alldevs;
void InsertStreamAtHead(unsigned int port, Stream *s);
void InsertStreamAtTail(unsigned int port, Stream *s);
bool InsertStreamBefore(unsigned int port, Stream *s,
unsigned int nextStreamId);
bool DeleteStream(unsigned int port, Stream *s);
bool DeleteStream(unsigned int port, unsigned int streamId);
void DeleteAllStreams(unsigned int port);
Stream* GetStream(unsigned int port, unsigned int streamId);
//void Log(char *fmt, ...);
void SendCapabilityInfo(void);
void SendPortInfo(unsigned int port);
void ProcessPortConfig(const char* msg, int len);
};
#endif