From 9e7b3239730c221231952b2699cc675fb1bc7340 Mon Sep 17 00:00:00 2001 From: "Srivats P." Date: Sat, 30 Aug 2008 08:49:08 +0000 Subject: [PATCH] Rewrote DumpView as a subclass of QAbstractItemView (as it should be). Correspondingly reworked PacketModel to work with DumpView. Added Dot3Protocol and PayloadProtocol to Stream class --- client/dumpview.cpp | 265 +++++++++-- client/dumpview.h | 34 +- client/packetmodel.cpp | 816 +--------------------------------- client/stream.cpp | 356 ++++++++++++++- client/stream.h | 83 +++- client/streamconfigdialog.cpp | 12 +- client/streamconfigdialog.ui | 5 +- common/protocol.proto | 4 +- 8 files changed, 718 insertions(+), 857 deletions(-) diff --git a/client/dumpview.cpp b/client/dumpview.cpp index a238e95..79edab9 100644 --- a/client/dumpview.cpp +++ b/client/dumpview.cpp @@ -1,11 +1,10 @@ #include "dumpview.h" +//public: DumpView::DumpView(QWidget *parent) { int w, h; - data.resize(73); - // NOTE: Monospaced fonts only !!!!!!!!!!! setFont(QFont("Courier")); w = fontMetrics().width('X'); @@ -17,6 +16,7 @@ DumpView::DumpView(QWidget *parent) mSelectedRow = mSelectedCol = -1; // calculate width for offset column and the whitespace that follows it + // 0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........ mOffsetPaneTopRect = QRect(0, 0, w*4, h); mDumpPaneTopRect = QRect(mOffsetPaneTopRect.right()+w*3, 0, w*((8*3-1)+2+(8*3-1)), h); @@ -25,15 +25,10 @@ DumpView::DumpView(QWidget *parent) qDebug("DumpView::DumpView"); } +QModelIndex DumpView::indexAt( const QPoint &point ) const +{ #if 0 -QSize DumpView::sizeHint() const -{ -} -#endif - -void DumpView::mousePressEvent(QMouseEvent *event) -{ - int x = event->x(); + int x = point.x(); int row, col; if (x > mAsciiPaneTopRect.left()) @@ -48,12 +43,12 @@ void DumpView::mousePressEvent(QMouseEvent *event) { col = (x - mDumpPaneTopRect.left()) / (mCharWidth*3); } - row = event->y()/mLineHeight; + row = point.y()/mLineHeight; if ((col < 16) && (row < ((data.size()+16)/16))) { - mSelectedRow = row; - mSelectedCol = col; + selrow = row; + selcol = col; } else goto _exit; @@ -62,26 +57,163 @@ void DumpView::mousePressEvent(QMouseEvent *event) if ((row == (((data.size()+16)/16) - 1)) && (col >= (data.size() % 16))) goto _exit; - qDebug("dumpview::selection(%d, %d)", mSelectedRow, mSelectedCol); - update(); - return; + qDebug("dumpview::selection(%d, %d)", selrow, selcol); + + offset = selrow * 16 + selcol; +#if 0 + for(int i = 0; i < model()->rowCount(parent); i++) + { + QModelIndex index = model()->index(i, 0, parent); + + if (model()->hasChildren(index)) + indexAtOffset(offset, index); // Non Leaf + else + if ( + dump.append(model()->data(index, Qt::UserRole).toByteArray()); // Leaf + // FIXME: Use RawValueRole instead of UserRole + } +#endif +} _exit: // Clear existing selection - mSelectedRow = -1; + selrow = -1; +#endif + + return QModelIndex(); +} + +void DumpView::scrollTo( const QModelIndex &index, ScrollHint hint ) +{ + // FIXME: implement scrolling +} + +QRect DumpView::visualRect( const QModelIndex &index ) const +{ + // FIXME: calculate actual rect + return rect(); +} + +//protected: +int DumpView::horizontalOffset() const +{ + return horizontalScrollBar()->value(); +} + +bool DumpView::isIndexHidden( const QModelIndex &index ) const +{ + return false; +} + +QModelIndex DumpView::moveCursor( CursorAction cursorAction, + Qt::KeyboardModifiers modifiers ) +{ + // FIXME(MED): need to implement movement using cursor + return currentIndex(); +} + +void DumpView::setSelection( const QRect &rect, + QItemSelectionModel::SelectionFlags flags ) +{ + // FIXME(HI): calculate indexes using rect + selectionModel()->select(QModelIndex(), flags); +} + +int DumpView::verticalOffset() const +{ + return verticalScrollBar()->value(); +} + +QRegion DumpView::visualRegionForSelection( const QItemSelection &selection ) const +{ + // FIXME(HI) + return QRegion(rect()); +} + +//protected slots: +void DumpView::dataChanged( const QModelIndex &topLeft, + const QModelIndex &bottomRight ) +{ + // FIXME(HI) update(); } +void DumpView::selectionChanged( const QItemSelection &selected, + const QItemSelection &deselected ) +{ + // FIXME(HI) + update(); +} + +void DumpView::populateDump(QByteArray &dump, int &selOfs, int &selSize, + QModelIndex parent) +{ + // TODO(LOW): Assumption - only single selection - enforce/ensure this + + for(int i = 0; i < model()->rowCount(parent); i++) + { + QModelIndex index = model()->index(i, 0, parent); + + if (model()->hasChildren(index)) + { + // Non Leaf + + // A non-leaf has no dump data of its own but is rather a + // container for its children. So we calculate ofs/size based + // on this fact + if (selectionModel()->isSelected(index)) + { + selOfs = dump.size(); + populateDump(dump, selOfs, selSize, index); + selSize = dump.size() - selOfs; + } + else + { + populateDump(dump, selOfs, selSize, index); + } + } + else + { + // Leaf + if (selectionModel()->isSelected(index)) + { + int size, j; + + selOfs = dump.size(); + size = model()->data(index, Qt::UserRole).toByteArray().size(); + + // Take care of multiple indexes (2 or more) mapping onto + // same dump byte(s) + j = i-1; + while ((size == 0) && (j >= 0)) + { + size = model()->data(index.sibling(j,0), Qt::UserRole). + toByteArray().size(); + selOfs -= size; + j++; + } + selSize = size; + } + dump.append(model()->data(index, Qt::UserRole).toByteArray()); + } + // FIXME: Use RawValueRole instead of UserRole + } +} + +// TODO(LOW): rewrite this function - it's a mess! void DumpView::paintEvent(QPaintEvent* event) { - QStylePainter painter(this); + QStylePainter painter(viewport()); QRect offsetRect = mOffsetPaneTopRect; QRect dumpRect = mDumpPaneTopRect; QRect asciiRect = mAsciiPaneTopRect; QPalette pal = palette(); - QByteArray ba; + QByteArray data; + //QByteArray ba; + int selOfs = -1, selSize; + int curSelOfs, curSelSize; - //qDebug("dumpview::paintEvent"); + qDebug("dumpview::paintEvent"); // FIXME(LOW): unable to set the self widget's font in constructor painter.setFont(QFont("Courier")); @@ -89,12 +221,15 @@ void DumpView::paintEvent(QPaintEvent* event) // set a white background painter.fillRect(rect(), QBrush(QColor(Qt::white))); + if (model()) + populateDump(data, selOfs, selSize); + // 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); + //ba = data.mid(i, 16); // display offset painter.drawItemText(offsetRect, Qt::AlignLeft | Qt::AlignTop, pal, @@ -128,48 +263,102 @@ void DumpView::paintEvent(QPaintEvent* event) painter.drawItemText(asciiRect, Qt::AlignLeft | Qt::AlignTop, pal, true, asciiStr, QPalette::WindowText); - // overpaint selection (if any) - if ((i/16) == mSelectedRow) + // if no selection, skip selection painting + if (selOfs < 0) + goto _next; + + // Check overlap between current row and selection + { + QRect r1(i, 0, qMin(16, data.size()-i), 8); + QRect s1(selOfs, 0, selSize, 8); + if (r1.intersects(s1)) + { + QRect t = r1.intersected(s1); + + curSelOfs = t.x(); + curSelSize = t.width(); + } + else + curSelSize = 0; + + } + + // overpaint selection on current row (if any) + if (curSelSize > 0) { 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()); + // construct the dumpStr and asciiStr + for (int k = curSelOfs; (k < (curSelOfs + curSelSize)); k++) + { + unsigned char c = data.at(k); - if (isPrintable(c)) - selectedAsciiStr.append(QChar(c)); - else - selectedAsciiStr.append(QChar('.')); + // extra space after 8 bytes + if (((k+8) % 16) == 0) + { + // Avoid adding space at the start for fields starting + // at second column 8 byte boundary + if (k!=curSelOfs) + { + selectedDumpStr.append(" "); + selectedAsciiStr.append(" "); + } + } + + selectedDumpStr.append(QString("%1").arg((uint)c, 2, 16, + QChar('0')).toUpper()).append(" "); + + if (isPrintable(c)) + selectedAsciiStr.append(QChar(c)); + else + selectedAsciiStr.append(QChar('.')); + } // display dump r = dumpRect; - if (mSelectedCol < 8) - r.translate(mCharWidth*(mSelectedCol*3), 0); + if ((curSelOfs - i) < 8) + r.translate(mCharWidth*(curSelOfs-i)*3, 0); else - r.translate(mCharWidth*(mSelectedCol*3+1), 0); - r.setWidth(mCharWidth*2); + r.translate(mCharWidth*((curSelOfs-i)*3+1), 0); + + // adjust width taking care of selection stretching between + // the two 8byte columns + if (( (curSelOfs-i) < 8 ) && ( (curSelOfs-i+curSelSize) > 8 )) + r.setWidth((curSelSize * 3 + 1) * mCharWidth); + else + r.setWidth((curSelSize * 3) * mCharWidth); + 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); + if ((curSelOfs - i) < 8) + r.translate(mCharWidth*(curSelOfs-i)*1, 0); else - r.translate(mCharWidth*(mSelectedCol+1), 0); - r.setWidth(mCharWidth); + r.translate(mCharWidth*((curSelOfs-i)*1+1), 0); + + // adjust width taking care of selection stretching between + // the two 8byte columns + if (( (curSelOfs-i) < 8 ) && ( (curSelOfs-i+curSelSize) > 8 )) + r.setWidth((curSelSize * 1 + 1) * mCharWidth); + else + r.setWidth((curSelSize * 1) * mCharWidth); + painter.fillRect(r, pal.highlight()); painter.drawItemText(r, Qt::AlignLeft | Qt::AlignTop, pal, true, selectedAsciiStr, QPalette::HighlightedText); } +_next: // move the rects down offsetRect.translate(0, mLineHeight); dumpRect.translate(0, mLineHeight); asciiRect.translate(0, mLineHeight); } } + diff --git a/client/dumpview.h b/client/dumpview.h index 4578a91..cdbcde7 100644 --- a/client/dumpview.h +++ b/client/dumpview.h @@ -1,25 +1,33 @@ #include // FIXME: High -class DumpView: public QWidget // QAbstractItemView // FIXME + +class DumpView: public QAbstractItemView { -public: +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; + QModelIndex indexAt( const QPoint &point ) const; + void scrollTo( const QModelIndex &index, ScrollHint hint = EnsureVisible ); + QRect visualRect( const QModelIndex &index ) const; protected: - void mousePressEvent(QMouseEvent *event); - //void mouseMoveEvent(QMouseEvent *event); + int horizontalOffset() const; + bool isIndexHidden( const QModelIndex &index ) const; + QModelIndex moveCursor( CursorAction cursorAction, + Qt::KeyboardModifiers modifiers ); + void setSelection( const QRect &rect, QItemSelectionModel::SelectionFlags flags ); + int verticalOffset() const; + QRegion visualRegionForSelection( const QItemSelection &selection ) const; +protected slots: + void dataChanged( const QModelIndex &topLeft, + const QModelIndex &bottomRight ); + void selectionChanged( const QItemSelection &selected, + const QItemSelection &deselected ); void paintEvent(QPaintEvent *event); private: - QString toAscii(QByteArray ba); + void DumpView::populateDump(QByteArray &dump, int &selOfs, int &selSize, + QModelIndex parent = QModelIndex()); bool inline isPrintable(char c) {if ((c > 48) && (c < 126)) return true; else return false; } @@ -27,8 +35,8 @@ private: QRect mOffsetPaneTopRect; QRect mDumpPaneTopRect; QRect mAsciiPaneTopRect; - QByteArray data; int mSelectedRow, mSelectedCol; int mLineHeight; int mCharWidth; }; + diff --git a/client/packetmodel.cpp b/client/packetmodel.cpp index 5800413..a1d4b7f 100644 --- a/client/packetmodel.cpp +++ b/client/packetmodel.cpp @@ -4,22 +4,6 @@ PacketModel::PacketModel(Stream *pStream, QObject *parent) { mpStream = pStream; -#ifdef NEW_IMPL -// Nothing else -#else - populatePacketProtocols(); - - registerFrameTypeProto(); - registerVlanProto(); - registerIpProto(); - registerArpProto(); - registerTcpProto(); - registerUdpProto(); - registerIcmpProto(); - registerIgmpProto(); - registerData(); - registerInvalidProto(); -#endif } int PacketModel::rowCount(const QModelIndex &parent) const @@ -29,22 +13,14 @@ int PacketModel::rowCount(const QModelIndex &parent) const // Parent == Invalid i.e. Invisible Root. // ==> Children are Protocol (Top Level) Items if (!parent.isValid()) -#ifdef NEW_IMPL return mpStream->numProtocols(); -#else - return protoCount(); -#endif // Parent - Valid Item parentId.w = parent.internalId(); switch(parentId.ws.type) { case ITYP_PROTOCOL: -#ifdef NEW_IMPL return mpStream->protocol(parentId.ws.protocol)->numFields(); -#else - return fieldCount(parentId.ws.protocol); -#endif case ITYP_FIELD: return 0; default: @@ -137,40 +113,44 @@ _exit: QVariant PacketModel::data(const QModelIndex &index, int role) const { IndexId id; -#ifdef NEW_IMPL -// Nothing -#else - ProtocolInfo proto; -#endif if (!index.isValid()) return QVariant(); + id.w = index.internalId(); + + // FIXME(HI): Relook at this completely + if (role == Qt::UserRole) + { + switch(id.ws.type) + { + case ITYP_PROTOCOL: + return QByteArray(); + + case ITYP_FIELD: + return mpStream->protocol(id.ws.protocol)->fieldRawValue( + index.row()); + + default: + qWarning("%s: Unhandled ItemType", __FUNCTION__); + } + return QByteArray(); + } + if (role != Qt::DisplayRole) return QVariant(); - id.w = index.internalId(); switch(id.ws.type) { case ITYP_PROTOCOL: -#ifdef NEW_IMPL return QString("%1 (%2)") .arg(mpStream->protocol(id.ws.protocol)->protocolShortName()) .arg(mpStream->protocol(id.ws.protocol)->protocolName()); -#else - return protoName(id.ws.protocol); -#endif case ITYP_FIELD: -#ifdef NEW_IMPL return mpStream->protocol(id.ws.protocol)->fieldName(index.row()) + QString(" : ") + mpStream->protocol(id.ws.protocol)->fieldTextValue(index.row()); -#else - return fieldName(id.ws.protocol, index.row()) + - QString(" : ") + - fieldTextValue(id.ws.protocol, index.row()).toString(); -#endif default: qWarning("%s: Unhandled ItemType", __FUNCTION__); @@ -180,759 +160,3 @@ QVariant PacketModel::data(const QModelIndex &index, int role) const return QVariant(); } - -#ifdef NEW_IMPL -// required methods all part of the Stream class -#else -/* -** --------------- Private Stuff ----------------- -** FIXME(MED): Move these to the Stream Class -** -*/ - -/*! - Looking at the stream's protocols and populate an ordered list of - protocols accordingly. The order of protocols will be in the order of - protocol headers viz. - - - None/Eth2/802.3 (Mac Addr) - - LLC - - SNAP - - SVLAN - - CVLAN - - L3 (IP/ARP) - - L4 (TCP/UDP/ICMP/IGMP) - -*/ -void PacketModel::populatePacketProtocols() -{ - int proto; - - // Clear the protocols list - mPacketProtocols.clear(); - - // Check and populate L2 Protocol - switch(mpStream->frameType()) - { - case Stream::e_ft_none: - proto = PTYP_L2_NONE; - break; - - case Stream::e_ft_eth_2: - proto = PTYP_L2_ETH_2; - break; - - case Stream::e_ft_802_3_raw: - proto = PTYP_L2_802_3_RAW; - break; - - case Stream::e_ft_802_3_llc: - mPacketProtocols.append(PTYP_L2_NONE); - proto = PTYP_L2_802_3_LLC; - break; - - case Stream::e_ft_snap: - mPacketProtocols.append(PTYP_L2_NONE); - mPacketProtocols.append(PTYP_L2_802_3_LLC); - proto = PTYP_L2_SNAP; - break; - - default: - qDebug("%s: Unsupported frametype %d", __FUNCTION__, - mpStream->frameType()); - proto = PTYP_INVALID; - } - mPacketProtocols.append(proto); - - // Check and populate VLANs, if present - if (mpStream->vlan()->vlanFlags().testFlag(VlanProtocol::VlanSvlanTagged)) - mPacketProtocols.append(PTYP_SVLAN); - - if (mpStream->vlan()->vlanFlags().testFlag(VlanProtocol::VlanCvlanTagged)) - mPacketProtocols.append(PTYP_CVLAN); - - // Check and populate L3 protocols - switch (mpStream->l3Proto()) - { - case Stream::e_l3_none : - goto _data; - break; - - case Stream::e_l3_ip : - proto = PTYP_L3_IP; - break; - - case Stream::e_l3_arp: - proto = PTYP_L3_ARP; - break; - - default: - qDebug("%s: Unsupported L3 Proto %d", __FUNCTION__, - mpStream->l3Proto()); - proto = PTYP_INVALID; - } - mPacketProtocols.append(proto); - - // Check and populate L4 protocol - switch(mpStream->l4Proto()) - { - case Stream::e_l4_none: - goto _data; - break; - case Stream::e_l4_tcp: - proto = PTYP_L4_TCP; - break; - case Stream::e_l4_udp: - proto = PTYP_L4_UDP; - break; - case Stream::e_l4_icmp: - proto = PTYP_L4_ICMP; - break; - case Stream::e_l4_igmp: - proto = PTYP_L4_IGMP; - break; - default: - qDebug("%s: Unsupported L4 Proto %d", __FUNCTION__, - mpStream->l4Proto()); - proto = PTYP_INVALID; - }; - mPacketProtocols.append(proto); - -_data: - mPacketProtocols.append(PTYP_DATA); -} -/*! - Returns the count of protocols in the current stream -*/ -int PacketModel::protoCount() const -{ - return mPacketProtocols.count(); -} - -/*! - Returns the count of fields in the given protocol -*/ -int PacketModel::fieldCount(int protocol) const -{ - ProtocolInfo proto; - - if (protocol >= mPacketProtocols.count()) - return 0; - - foreach(proto, mProtocols) - { - if (proto.handle == mPacketProtocols.at(protocol)) - { - qDebug("proto=%d, name=%s",protocol,proto.name.toAscii().data()); - qDebug("fieldcount = %d", proto.fieldList.size()); - return proto.fieldList.count(); - } - } - - return 0; -} - -QString PacketModel::protoName(int protocol) const -{ - ProtocolInfo proto; - - if (protocol >= mPacketProtocols.count()) - return 0; - - foreach(proto, mProtocols) - { - if (proto.handle == mPacketProtocols.at(protocol)) - { - qDebug("proto=%d, name=%s",protocol,proto.name.toAscii().data()); - qDebug("fieldcount = %d", proto.fieldList.size()); - return proto.name; - } - } - - return QString(); -} - -QString PacketModel::fieldName(int protocol, int field) const -{ - ProtocolInfo proto; - - if (protocol >= mPacketProtocols.count()) - return 0; - - foreach(proto, mProtocols) - { - if (proto.handle == mPacketProtocols.at(protocol)) - { - qDebug("proto=%d, name=%s",protocol,proto.name.toAscii().data()); - qDebug("fieldcount = %d", proto.fieldList.size()); - if (field >= proto.fieldList.count()) - return QString(); - - return proto.fieldList.at(field).name; - } - } - - return QString(); -} - -QVariant PacketModel::fieldTextValue(int protocol, int field) const -{ - if (protocol >= mPacketProtocols.count()) - return QVariant(); - - switch(mPacketProtocols.at(protocol)) - { - case PTYP_L2_NONE: - case PTYP_L2_ETH_2: - return ethField(field, FROL_TEXT_VALUE); - case PTYP_L2_802_3_RAW: - //return dot3Field(field, FROL_TEXT_VALUE); // FIXME(HIGH) - return ethField(field, FROL_TEXT_VALUE); - case PTYP_L2_802_3_LLC: - return llcField(field, FROL_TEXT_VALUE); - case PTYP_L2_SNAP: - return snapField(field, FROL_TEXT_VALUE); - - case PTYP_SVLAN: - return svlanField(field, FROL_TEXT_VALUE); - case PTYP_CVLAN: - // return cvlanField(field, FROL_TEXT_VALUE); // FIXME(HIGH) - return svlanField(field, FROL_TEXT_VALUE); - - case PTYP_L3_IP: - return ipField(field, FROL_TEXT_VALUE); - case PTYP_L3_ARP: - return QString(); // FIXME(HIGH) - - case PTYP_L4_TCP: - return tcpField(field, FROL_TEXT_VALUE); - case PTYP_L4_UDP: - return udpField(field, FROL_TEXT_VALUE); - case PTYP_L4_ICMP: - return QString(); // FIXME(HIGH) - case PTYP_L4_IGMP: - return QString(); // FIXME(HIGH) - - case PTYP_INVALID: - return QString(); // FIXME(HIGH) - case PTYP_DATA: - return QString(); // FIXME(HIGH) - } - - return QString(); -} - -QVariant PacketModel::ethField(int field, int role) const -{ - FieldInfo info; - - // FIXME(MED): Mac Addr formatting - switch(field) - { - case 0: - info.name = QString("Destination Mac Address"); - info.textValue = QString("%1"). - arg(mpStream->mac()->dstMac(), 12, BASE_HEX, QChar('0')); - break; - case 1: - info.name = QString("Source Mac Address"); - info.textValue = QString("%1"). - arg(mpStream->mac()->srcMac(), 12, BASE_HEX, QChar('0')); - break; - case 2: - info.name = QString("Type"); - info.textValue = QString("0x%1"). - arg(mpStream->eth2()->type(), 4, BASE_HEX, QChar('0')); - break; - default: - info.name = QString(); - info.textValue = QString(); - } - - switch(role) - { - case FROL_NAME: - return info.name; - case FROL_TEXT_VALUE: - return info.textValue; - default: - ; - } - - Q_ASSERT(1 == 1); // Unreachable code - return QVariant(); -} - -QVariant PacketModel::llcField(int field, int role) const -{ - FieldInfo info; - - switch(field) - { - case 0: - info.name = QString("DSAP"); - info.textValue = QString("0x%1"). - arg(mpStream->llc()->dsap(), 2, BASE_HEX, QChar('0')); - break; - case 1: - info.name = QString("SSAP"); - info.textValue = QString("0x%1"). - arg(mpStream->llc()->ssap(), 2, BASE_HEX, QChar('0')); - break; - case 2: - info.name = QString("Control"); - info.textValue = QString("0x%1"). - arg(mpStream->llc()->ctl(), 2, BASE_HEX, QChar('0')); - break; - default: - info.name = QString(); - info.textValue = QString(); - } - - switch(role) - { - case FROL_NAME: - return info.name; - case FROL_TEXT_VALUE: - return info.textValue; - default: - ; - } - - Q_ASSERT(1 == 1); // Unreachable code - return QVariant(); -} - -QVariant PacketModel::snapField(int field, int role) const -{ - FieldInfo info; - - switch(field) - { - case 0: - info.name = QString("OUI"); - info.textValue = QString("0x%1"). - arg(mpStream->snap()->oui(), 6, BASE_HEX, QChar('0')); - break; - case 1: - info.name = QString("Type"); - info.textValue = QString("0x%1"). - arg(mpStream->eth2()->type(), 4, BASE_HEX, QChar('0')); - break; - default: - info.name = QString(); - info.textValue = QString(); - } - - switch(role) - { - case FROL_NAME: - return info.name; - case FROL_TEXT_VALUE: - return info.textValue; - default: - ; - } - - Q_ASSERT(1 == 1); // Unreachable code - return QVariant(); -} - -QVariant PacketModel::svlanField(int field, int role) const -{ - FieldInfo info; - - switch(field) - { - case 0: - info.name = QString("TPID"); - info.textValue = QString("0x%1"). - arg(mpStream->vlan()->stpid(), 4, BASE_HEX, QChar('0')); - break; - case 1: - info.name = QString("PCP"); - info.textValue = QString("%1"). - arg(mpStream->vlan()->svlanPrio()); - break; - case 2: - info.name = QString("DE"); - info.textValue = QString("%1"). - arg(mpStream->vlan()->svlanCfi()); - break; - case 3: - info.name = QString("VlanId"); - info.textValue = QString("%1"). - arg(mpStream->vlan()->svlanId()); - break; - default: - info.name = QString(); - info.textValue = QString(); - } - - switch(role) - { - case FROL_NAME: - return info.name; - case FROL_TEXT_VALUE: - return info.textValue; - default: - ; - } - - Q_ASSERT(1 == 1); // Unreachable code - return QVariant(); -} - - -QVariant PacketModel::ipField(int field, int role) const -{ - FieldInfo info; - - switch(field) - { - case 0: - info.name = QString("Version"); - info.textValue = QString("%1"). - arg(mpStream->ip()->ver()); - break; - case 1: - info.name = QString("Header Length"); - info.textValue = QString("%1"). - arg(mpStream->ip()->hdrLen()); - break; - case 2: - info.name = QString("TOS/DSCP"); - info.textValue = QString("0x%1"). - arg(mpStream->ip()->tos(), 2, BASE_HEX, QChar('0')); - break; - case 3: - info.name = QString("Total Length"); - info.textValue = QString("%1"). - arg(mpStream->ip()->totLen()); - break; - case 4: - info.name = QString("ID"); - info.textValue = QString("0x%1"). - arg(mpStream->ip()->id(), 2, BASE_HEX, QChar('0')); - break; - case 5: - info.name = QString("Flags"); - info.textValue = QString("0x%1"). - arg(mpStream->ip()->flags(), 2, BASE_HEX, QChar('0')); // FIXME(HIGH) - break; - case 6: - info.name = QString("Fragment Offset"); - info.textValue = QString("%1"). - arg(mpStream->ip()->fragOfs()); - break; - case 7: - info.name = QString("TTL"); - info.textValue = QString("%1"). - arg(mpStream->ip()->ttl()); - break; - case 8: - info.name = QString("Protocol Type"); - info.textValue = QString("0x%1"). - arg(mpStream->ip()->proto(), 2, BASE_HEX, QChar('0')); - break; - case 9: - info.name = QString("Checksum"); - info.textValue = QString("0x%1"). - arg(mpStream->ip()->cksum(), 4, BASE_HEX, QChar('0')); - break; - case 10: - info.name = QString("Source IP"); - info.textValue = QHostAddress(mpStream->ip()->srcIp()).toString(); - break; - case 11: - info.name = QString("Destination IP"); - info.textValue = QHostAddress(mpStream->ip()->dstIp()).toString(); - break; - default: - info.name = QString(); - info.textValue = QString(); - } - - switch(role) - { - case FROL_NAME: - return info.name; - case FROL_TEXT_VALUE: - return info.textValue; - default: - ; - } - - Q_ASSERT(1 == 1); // Unreachable code - return QVariant(); -} - - -QVariant PacketModel::tcpField(int field, int role) const -{ - FieldInfo info; - - switch(field) - { - case 0: - info.name = QString("Source Port"); - info.textValue = QString("%1"). - arg(mpStream->tcp()->srcPort()); - break; - case 1: - info.name = QString("Destination Port"); - info.textValue = QString("%1"). - arg(mpStream->tcp()->dstPort()); - break; - case 2: - info.name = QString("Seq Number"); - info.textValue = QString("%1"). - arg(mpStream->tcp()->seqNum()); - break; - case 3: - info.name = QString("Ack Number"); - info.textValue = QString("%1"). - arg(mpStream->tcp()->ackNum()); - break; - case 4: - info.name = QString("Header Length"); - info.textValue = QString("%1"). - arg(mpStream->tcp()->hdrLen()); - break; - case 5: - info.name = QString("Reserved"); - info.textValue = QString("%1"). - arg(mpStream->tcp()->rsvd()); - break; - case 6: - info.name = QString("Flags"); - info.textValue = QString("0x%1"). - arg(mpStream->tcp()->flags(), 2, BASE_HEX, QChar('0')); - break; - case 7: - info.name = QString("Window"); - info.textValue = QString("%1"). - arg(mpStream->tcp()->flags()); - break; - case 8: - info.name = QString("Checksum"); - info.textValue = QString("0x%1"). - arg(mpStream->tcp()->cksum(), 4, BASE_HEX, QChar('0')); - break; - case 9: - info.name = QString("Urgent Pointer"); - info.textValue = QString("%1"). - arg(mpStream->tcp()->urgPtr()); - break; - default: - info.name = QString(); - info.textValue = QString(); - } - - switch(role) - { - case FROL_NAME: - return info.name; - case FROL_TEXT_VALUE: - return info.textValue; - default: - ; - } - - Q_ASSERT(1 == 1); // Unreachable code - return QVariant(); -} - - -QVariant PacketModel::udpField(int field, int role) const -{ - FieldInfo info; - - switch(field) - { - case 0: - info.name = QString("Source Port"); - info.textValue = QString("%1"). - arg(mpStream->udp()->srcPort()); - break; - case 1: - info.name = QString("Destination Port"); - info.textValue = QString("%1"). - arg(mpStream->udp()->dstPort()); - break; - case 2: - info.name = QString("Total Length"); - info.textValue = QString("%1"). - arg(mpStream->udp()->totLen()); - break; - case 3: - info.name = QString("Checksum"); - info.textValue = QString("0x%1"). - arg(mpStream->udp()->cksum(), 4, BASE_HEX, QChar('0')); - break; - default: - info.name = QString(); - info.textValue = QString(); - } - - switch(role) - { - case FROL_NAME: - return info.name; - case FROL_TEXT_VALUE: - return info.textValue; - default: - ; - } - - Q_ASSERT(1 == 1); // Unreachable code - return QVariant(); -} - - - -/* -** ------------- Registration Functions --------------- -*/ - -void PacketModel::registerProto(uint handle, char *name, char *abbr) -{ - ProtocolInfo proto; - - proto.handle = handle; - proto.name = QString(name); - proto.abbr = QString(abbr); - mProtocols.append(proto); -} - -void PacketModel::registerField(uint protoHandle, char *name, char *abbr) -{ - for (int i = 0; i < mProtocols.size(); i++) - { - if (mProtocols.at(i).handle == protoHandle) - { - FieldInfo field; - - field.name = QString(name); - field.abbr = QString(abbr); - mProtocols[i].fieldList.append(field); - qDebug("proto = %d, name = %s", protoHandle, name); - break; - } - } -} - -void PacketModel::registerFrameTypeProto() -{ - registerProto(PTYP_L2_NONE, "None", ""); - registerField(PTYP_L2_NONE, "Destination Mac", "dstMac"); - registerField(PTYP_L2_NONE, "Source Mac", "srcMac"); - - registerProto(PTYP_L2_ETH_2, "Ethernet II", "eth"); - registerField(PTYP_L2_ETH_2, "Destination Mac", "dstMac"); - registerField(PTYP_L2_ETH_2, "Source Mac", "srcMac"); - registerField(PTYP_L2_ETH_2, "Ethernet Type", "type"); - - registerProto(PTYP_L2_802_3_RAW, "IEEE 802.3 Raw", "dot3raw"); - registerField(PTYP_L2_802_3_RAW, "Destination Mac", "dstMac"); - registerField(PTYP_L2_802_3_RAW, "Source Mac", "srcMac"); - registerField(PTYP_L2_802_3_RAW, "Length", "len"); - - registerProto(PTYP_L2_802_3_LLC, "802.3 LLC", "dot3llc"); - registerField(PTYP_L2_802_3_LLC, "Destination Service Acces Point", "dsap"); - registerField(PTYP_L2_802_3_LLC, "Source Service Acces Point", "ssap"); - registerField(PTYP_L2_802_3_LLC, "Control", "ctl"); - - registerProto(PTYP_L2_SNAP, "SNAP", "dot3snap"); - registerField(PTYP_L2_SNAP, "Organisationally Unique Identifier", "oui"); - registerField(PTYP_L2_SNAP, "Type", "type"); - -} - -void PacketModel::registerVlanProto() -{ - registerProto(PTYP_SVLAN, "IEEE 802.1ad Service VLAN", "SVLAN"); - - registerField(PTYP_SVLAN, "Tag Protocol Identifier", "tpid"); - registerField(PTYP_SVLAN, "Priority Code Point", "pcp"); - registerField(PTYP_SVLAN, "Drop Eligible", "de"); - registerField(PTYP_SVLAN, "VLAN Identifier", "vlan"); - - registerProto(PTYP_CVLAN, "IEEE 802.1Q VLAN/CVLAN", "VLAN"); - - registerField(PTYP_CVLAN, "Tag Protocol Identifier", "tpid"); - registerField(PTYP_CVLAN, "Priority", "prio"); - registerField(PTYP_CVLAN, "Canonical Format Indicator", "cfi"); - registerField(PTYP_CVLAN, "VLAN Identifier", "vlan"); -} - -void PacketModel::registerIpProto() -{ - registerProto(PTYP_L3_IP, "Internet Protocol version 4", "IPv4"); - - registerField(PTYP_L3_IP, "Version", "ver"); - registerField(PTYP_L3_IP, "Header Length", "hdrlen"); - registerField(PTYP_L3_IP, "Type of Service/DiffServ Code Point", "tos"); - registerField(PTYP_L3_IP, "Total Length", "len"); - registerField(PTYP_L3_IP, "Identification", "id"); - registerField(PTYP_L3_IP, "Flags", "flags"); - registerField(PTYP_L3_IP, "Fragment Offset", "fragofs"); - registerField(PTYP_L3_IP, "Time to Live", "ttl"); - registerField(PTYP_L3_IP, "Protocol Id", "proto"); - registerField(PTYP_L3_IP, "Checksum", "cksum"); - registerField(PTYP_L3_IP, "Source IP", "srcip"); - registerField(PTYP_L3_IP, "Destination IP", "dstip"); -} - -void PacketModel::registerArpProto() -{ - // TODO (LOW) -} - -void PacketModel::registerTcpProto() -{ - registerProto(PTYP_L4_TCP, "Transmission Control Protocol", "TCP"); - - registerField(PTYP_L4_TCP, "Source Port", "srcport"); - registerField(PTYP_L4_TCP, "Destination Port", "dstport"); - registerField(PTYP_L4_TCP, "Sequence Number", "seqnum"); - registerField(PTYP_L4_TCP, "Acknowledgement Number", "acknum"); - registerField(PTYP_L4_TCP, "Header Length", "hdrlen"); - registerField(PTYP_L4_TCP, "Reserved", "rsvd"); - registerField(PTYP_L4_TCP, "Flags", "flags"); - registerField(PTYP_L4_TCP, "Window", "win"); - registerField(PTYP_L4_TCP, "Checksum", "cksum"); - registerField(PTYP_L4_TCP, "Urgent Pointer", "urgptr"); -} - -void PacketModel::registerUdpProto() -{ - registerProto(PTYP_L4_UDP, "User Datagram Protocol", "UDP"); - - registerField(PTYP_L4_UDP, "Source Port", "srcport"); - registerField(PTYP_L4_UDP, "Destination Port", "dstport"); - registerField(PTYP_L4_UDP, "Length", "len"); - registerField(PTYP_L4_UDP, "Checksum", "cksum"); -} - -void PacketModel::registerIcmpProto() -{ - // TODO (LOW) -} - -void PacketModel::registerIgmpProto() -{ - // TODO (LOW) -} - -void PacketModel::registerInvalidProto() -{ - registerProto(PTYP_INVALID, "Invalid Protocol (bug in code)", "invalid"); -} - -void PacketModel::registerData() -{ - registerProto(PTYP_DATA, "Data", "data"); -} - -#endif diff --git a/client/stream.cpp b/client/stream.cpp index 30568e5..653859c 100644 --- a/client/stream.cpp +++ b/client/stream.cpp @@ -1,3 +1,4 @@ +#include #include #include "stream.h" @@ -6,6 +7,72 @@ #define BASE_HEX 16 +QString PayloadProtocol::fieldTextValue(int index) +{ + int len; + quint32 pat; + QString textValue; + + if (parentStream) + { + len = parentStream->frameLen() - parentStream->protocolHeaderSize(); + pat = parentStream->pattern(); + } + else + { + len = 1500; // FIXME(HI): testing only + pat = 0x0a0b0c0d; + } + + // Make a larger string and then resize to the correct size to + // take care of the case where len is not a multiple of pattern size + if (len > 0) + { + // TODO(LOW): allow non-4byte patterns!!! + int w = 4; // data pattern size + + for (int i = 0; i < (len/w + 1); i++) + textValue.append(QString("%1").arg( + pat, w*2, BASE_HEX, QChar('0'))); + textValue.resize(len); + } + + return textValue; +} + +QByteArray PayloadProtocol::fieldRawValue(int index) +{ + int len; + quint32 pat; + QByteArray rawValue; + + if (parentStream) + { + len = parentStream->frameLen() - parentStream->protocolHeaderSize(); + pat = parentStream->pattern(); + } + else + { + len = 1500; // FIXME(HI): testing only + pat = 0x0a0b0c0d; + } + + // Make a larger byteArray and then resize to the correct size to + // take care of the case where len is not a multiple of pattern size + if (len > 0) + { + // TODO(LOW): allow non-4byte patterns!!! + int w = 4; // data pattern size + + rawValue.resize(len + 4); + for (int i = 0; i < (len/w + 1); i++) + qToBigEndian(pat, (uchar*) (rawValue.data() + i*sizeof(pat))); + rawValue.resize(len); + } + + return rawValue; +} + QString MacProtocol::fieldName(int index) { QString name; @@ -53,6 +120,24 @@ QByteArray MacProtocol::fieldRawValue(int index) { QByteArray rawValue; + switch(index) + { + case 0: + rawValue.resize(8); + qToBigEndian(dstMac(), (uchar *) rawValue.data()); + rawValue.remove(0, 2); + qDebug("dstMac(%d): %s", rawValue.size(), rawValue.toHex().constData()); + break; + case 1: + rawValue.resize(8); + qToBigEndian(srcMac(), (uchar *) rawValue.data()); + rawValue.remove(0, 2); + qDebug("srcMac(%d): %s", rawValue.size(), rawValue.toHex().constData()); + break; + default: + break; + } + return rawValue; } @@ -109,6 +194,24 @@ QByteArray LlcProtocol::fieldRawValue(int index) { QByteArray rawValue; + switch(index) + { + case 0: + rawValue.resize(1); + rawValue[0] = dsap(); + break; + case 1: + rawValue.resize(1); + rawValue[0] = ssap(); + break; + case 2: + rawValue.resize(1); + rawValue[0] = ctl(); + break; + default: + break; + } + return rawValue; } @@ -151,6 +254,17 @@ QByteArray SnapProtocol::fieldRawValue(int index) { QByteArray rawValue; + switch(index) + { + case 0: + rawValue.resize(4); + qToBigEndian(oui(), (uchar *) rawValue.data()); + rawValue.remove(0, 1); + break; + default: + break; + } + return rawValue; } @@ -191,9 +305,58 @@ QByteArray Eth2Protocol::fieldRawValue(int index) { QByteArray rawValue; + switch(index) + { + case 0: + rawValue.resize(2); + qToBigEndian(type(), (uchar*) rawValue.data()); + break; + default: + break; + } + return rawValue; } +QString Dot3Protocol::fieldName(int index) +{ + QString name; + + switch(index) + { + case 0: + name = QString("Length"); + break; + default: + name = QString(); + break; + } + return name; +} + +QString Dot3Protocol::fieldTextValue(int index) +{ + if (parentStream) + return QString("%1").arg(parentStream->frameLen()); + else + return QString("00"); +} + +QByteArray Dot3Protocol::fieldRawValue(int index) +{ + QByteArray ba; + + if (parentStream) + qToBigEndian((quint16) parentStream->frameLen(), (uchar*) ba.data()); + else + { + ba.resize(2); + ba[0] = ba[1] = 0; + } + + return ba; +} + int VlanProtocol::numFields() { if (isSingleTagged()) @@ -323,6 +486,56 @@ QByteArray VlanProtocol::fieldRawValue(int index) { QByteArray rawValue; + if (isDoubleTagged()) + { + switch(index) + { + case 0: + rawValue.resize(2); + qToBigEndian(stpid(), (uchar*) rawValue.data()); + break; + case 1: + rawValue.resize(2); + qToBigEndian((svlanPrio() << 13) | (svlanCfi() < 12) | svlanId(), + (uchar*) rawValue.data()); + break; + case 2: + // Combined with prio above + break; + case 3: + // Combined with prio above + break; + default: + index -= 4; + goto _single_tag; + } + + goto _exit; + } + +_single_tag: + switch(index) + { + case 0: + rawValue.resize(2); + qToBigEndian(ctpid(), (uchar*) rawValue.data()); + break; + case 1: + rawValue.resize(2); + qToBigEndian((cvlanPrio() << 13) | (cvlanCfi() < 12) | cvlanId(), + (uchar*) rawValue.data()); + break; + case 2: + // Combined with prio above + break; + case 3: + // Combined with prio above + break; + default: + break; + } + +_exit: return rawValue; } @@ -438,6 +651,60 @@ QByteArray IpProtocol::fieldRawValue(int index) { QByteArray rawValue; + switch(index) + { + case 0: + rawValue.resize(1); + //qToBigEndian((ver() << 4) | hdrLen(), (uchar*) rawValue.data()); + rawValue[0]=(ver() << 4) | hdrLen(); + break; + case 1: + // Combined with previous 4 bits of ver!! + break; + case 2: + rawValue.resize(1); + qToBigEndian(tos(), (uchar*) rawValue.data()); + break; + case 3: + rawValue.resize(2); + qToBigEndian(totLen(), (uchar*) rawValue.data()); + break; + case 4: + rawValue.resize(2); + qToBigEndian(id(), (uchar*) rawValue.data()); + break; + case 5: + rawValue.resize(2); + qToBigEndian((quint16)((flags() << 13) | fragOfs()), + (uchar*) rawValue.data()); + break; + case 6: + // Combined with previous 3 bits of flags!! + break; + case 7: + rawValue.resize(1); + qToBigEndian(ttl(), (uchar*) rawValue.data()); + break; + case 8: + rawValue.resize(1); + qToBigEndian(proto(), (uchar*) rawValue.data()); + break; + case 9: + rawValue.resize(2); + qToBigEndian(cksum(), (uchar*) rawValue.data()); + break; + case 10: + rawValue.resize(4); + qToBigEndian(srcIp(), (uchar*) rawValue.data()); + break; + case 11: + rawValue.resize(4); + qToBigEndian(dstIp(), (uchar*) rawValue.data()); + break; + default: + break; + } + return rawValue; } @@ -520,7 +787,7 @@ QString TcpProtocol::fieldTextValue(int index) break; case 7: textValue = QString("%1"). - arg(flags()); + arg(window(), 2, BASE_HEX, QChar('0')); break; case 8: textValue = QString("0x%1"). @@ -541,6 +808,51 @@ QByteArray TcpProtocol::fieldRawValue(int index) { QByteArray rawValue; + switch(index) + { + case 0: + rawValue.resize(2); + qToBigEndian(srcPort(), (uchar*) rawValue.data()); + break; + case 1: + rawValue.resize(2); + qToBigEndian(dstPort(), (uchar*) rawValue.data()); + break; + case 2: + rawValue.resize(4); + qToBigEndian(seqNum(), (uchar*) rawValue.data()); + break; + case 3: + rawValue.resize(4); + qToBigEndian(ackNum(), (uchar*) rawValue.data()); + break; + case 4: + rawValue.resize(1); + rawValue[0] = (hdrLen() << 4) | rsvd(); + break; + case 5: + // Combined with hdrLen above + break; + case 6: + rawValue.resize(1); + rawValue[0] = flags(); + break; + case 7: + rawValue.resize(2); + qToBigEndian(window(), (uchar*) rawValue.data()); + break; + case 8: + rawValue.resize(2); + qToBigEndian(cksum(), (uchar*) rawValue.data()); + break; + case 9: + rawValue.resize(2); + qToBigEndian(urgPtr(), (uchar*) rawValue.data()); + break; + default: + break; + } + return rawValue; } @@ -602,6 +914,28 @@ QByteArray UdpProtocol::fieldRawValue(int index) { QByteArray rawValue; + switch(index) + { + case 0: + rawValue.resize(2); + qToBigEndian(srcPort(), (uchar*) rawValue.data()); + break; + case 1: + rawValue.resize(2); + qToBigEndian(dstPort(), (uchar*) rawValue.data()); + break; + case 2: + rawValue.resize(2); + qToBigEndian(totLen(), (uchar*) rawValue.data()); + break; + case 3: + rawValue.resize(2); + qToBigEndian(cksum(), (uchar*) rawValue.data()); + break; + default: + break; + } + return rawValue; } @@ -622,12 +956,14 @@ Stream::Stream() // mCore->set_stream_id(mId); mUnknown = new UnknownProtocol; + mPayload = new PayloadProtocol(); //FIXME(MED): need to pass parent stream mMac = new MacProtocol; mLlc = new LlcProtocol; mSnap = new SnapProtocol; mEth2 = new Eth2Protocol; + mDot3 = new Dot3Protocol(); // FIXME(MED): need to pass parent stream mVlan = new VlanProtocol; mIp = new IpProtocol; @@ -776,9 +1112,23 @@ void Stream::updateSelectedProtocols() selectedProtocols.append(proto); _data: + + mProtocolHeaderSize = 0; +#ifndef SRIVATSP +#if 0 + for (int i = 0; i < selectedProtocols.size(); i++) + mProtocolHeaderSize += protocol(i)->protocolRawValue().size(); +#endif +#endif selectedProtocols.append(PTYP_DATA); } +int Stream::protocolHeaderSize() +{ + updateSelectedProtocols(); // FIXME(HI): shd not happen everytime + return mProtocolHeaderSize; +} + int Stream::numProtocols() { updateSelectedProtocols(); // FIXME(HI): shd not happen everytime @@ -815,7 +1165,7 @@ AbstractProtocol* Stream::protocol(int index) case PTYP_L2_ETH_2: return eth2(); case PTYP_L2_802_3_RAW: - return eth2(); // FIXME(HI): define a dot3 protocol? + return dot3(); case PTYP_L2_802_3_LLC: return llc(); @@ -843,7 +1193,7 @@ AbstractProtocol* Stream::protocol(int index) case PTYP_INVALID: return mUnknown; case PTYP_DATA: - return mUnknown; // FIXME(MED) define a "data" protocol? + return mPayload; default: return mUnknown; } diff --git a/client/stream.h b/client/stream.h index 0bb35cd..9500064 100644 --- a/client/stream.h +++ b/client/stream.h @@ -2,6 +2,7 @@ #define _STREAM_H #include + #include #include #include "../common/protocol.pb.h" @@ -17,6 +18,8 @@ class PacketModel; #define IP_PROTO_UDP 0x11 +class Stream; + class AbstractProtocol { // TODO(LOW) @@ -36,6 +39,16 @@ public: { return QString("AbsProto"); } virtual int numFields() { return 1; } + QByteArray protocolRawValue() + { + QByteArray ba; +#ifndef SRIVATSP +#else + for (int i=0; i < numFields(); i++) + ba.append(fieldRawValue(i)); +#endif + return ba; + } virtual QString fieldName(int index) { return QString("AbstractField"); } virtual QString fieldTextValue(int index) @@ -64,7 +77,31 @@ public: QString fieldTextValue(int index) { return QString("UnknownFieldValue"); } QByteArray fieldRawValue(int index) - { return QByteArray(4, '\0'); } + { return QByteArray(); } +}; + +class PayloadProtocol: public AbstractProtocol +{ + Stream *parentStream; + OstProto::Ack d; // FIXME(HI): move payload related vars from + // stream into here + +public: + PayloadProtocol (Stream *stream = NULL) { parentStream = stream; } + virtual ~PayloadProtocol() {} + + virtual ::google::protobuf::Message& data() { return d; } + + virtual QString protocolName() + { return QString("Payload Data"); } + QString protocolShortName() + { return QString("DATA"); } + int numFields() + { return 1; } + QString fieldName(int index) + { return QString("Data"); } + QString fieldTextValue(int index); + QByteArray fieldRawValue(int index); }; class MacProtocol : public AbstractProtocol @@ -238,6 +275,37 @@ public: QByteArray fieldRawValue(int index); }; + +class Dot3Protocol : public AbstractProtocol +{ +private: + Stream *parentStream; + OstProto::Ack d; // FIXME(HI): replace 'ack' with somehting else + +public: + Dot3Protocol(Stream *stream = NULL) + { parentStream = stream; qDebug("parentStream = %p", stream); } + virtual ~Dot3Protocol() {} + virtual ::google::protobuf::Message& data() {return d;} + +#if 0 // FIXME(HI): remove? + quint16 length() + { return d.length(); } + bool setLength(quint16 length) + { return true; } +#endif + + virtual QString protocolName() + { return QString("802.3 Length"); } + QString protocolShortName() + { return QString("LEN"); } + int numFields() + { return 1; } + QString fieldName(int index); + QString fieldTextValue(int index); + QByteArray fieldRawValue(int index); +}; + class VlanProtocol : public AbstractProtocol { OstProto::Vlan d; @@ -765,11 +833,14 @@ class Stream { OstProto::StreamCore *mCore; UnknownProtocol *mUnknown; + PayloadProtocol *mPayload; MacProtocol *mMac; LlcProtocol *mLlc; SnapProtocol *mSnap; Eth2Protocol *mEth2; + Dot3Protocol *mDot3; + VlanProtocol *mVlan; IpProtocol *mIp; @@ -781,11 +852,15 @@ class Stream { IgmpProtocol *mIgmp; public: + //PayloadProtocol* Payload() { return mPayload; } MacProtocol* mac() { return mMac; } + void* core() { return mCore; } // FIXME(HI): Debug ONLY + LlcProtocol* llc() { return mLlc; } SnapProtocol* snap() { return mSnap; } Eth2Protocol* eth2() { return mEth2; } + Dot3Protocol* dot3() { return mDot3; } VlanProtocol* vlan() { return mVlan; } IpProtocol* ip() { return mIp; } @@ -954,15 +1029,19 @@ public: //--------------------------------------------------------------- // Methods for use by Packet Model //--------------------------------------------------------------- - QList selectedProtocols; int numProtocols(); + + //! Includes ALL protocol headers excluding payload data + int protocolHeaderSize(); #if 0 int protocolId(int index); int protocolIndex(int id); #endif AbstractProtocol* protocol(int index); private: + QList selectedProtocols; + int mProtocolHeaderSize; void updateSelectedProtocols(); }; diff --git a/client/streamconfigdialog.cpp b/client/streamconfigdialog.cpp index a881dce..0202825 100644 --- a/client/streamconfigdialog.cpp +++ b/client/streamconfigdialog.cpp @@ -16,13 +16,13 @@ StreamConfigDialog::StreamConfigDialog(Port &port, uint streamIndex, //mpStreamList = streamList; mCurrentStreamIndex = streamIndex; LoadCurrentStream(); - mpPacketModel = new PacketModel(&mPort.streamByIndex(mCurrentStreamIndex), this); tvPacketTree->setModel(mpPacketModel); mpPacketModelTester = new ModelTest(mpPacketModel); tvPacketTree->header()->hide(); - + vwPacketDump->setModel(mpPacketModel); + vwPacketDump->setSelectionModel(tvPacketTree->selectionModel()); // FIXME(MED): Enable this navigation pbPrev->setDisabled(true); @@ -625,6 +625,11 @@ void StreamConfigDialog::StoreCurrentStream() { pStream->mac()->setDstMac( leDstMac->text().remove(QChar(' ')).toULongLong(&isOk, 16)); +#if 1 + qDebug("%s: dstMac = %llx [%s] %d", __FUNCTION__, + pStream->mac()->dstMac(), + leDstMac->text().toAscii().constData(), isOk); +#endif pStream->mac()->setDstMacMode( (MacProtocol::MacAddrMode) cmbDstMacMode->currentIndex()); pStream->mac()->setDstMacCount( @@ -634,6 +639,9 @@ void StreamConfigDialog::StoreCurrentStream() pStream->mac()->setSrcMac( leSrcMac->text().remove(QChar(' ')).toULongLong(&isOk, 16)); + qDebug("%s: srcMac = %llx [%s] %d", __FUNCTION__, + pStream->mac()->srcMac(), + leSrcMac->text().toAscii().constData(), isOk); pStream->mac()->setSrcMacMode( (MacProtocol::MacAddrMode) cmbSrcMacMode->currentIndex()); pStream->mac()->setSrcMacCount( diff --git a/client/streamconfigdialog.ui b/client/streamconfigdialog.ui index b568d52..503eb27 100644 --- a/client/streamconfigdialog.ui +++ b/client/streamconfigdialog.ui @@ -33,7 +33,7 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff - 0 + 2 @@ -2036,6 +2036,9 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-color: #ccccff QAbstractItemView::SelectItems + + true + diff --git a/common/protocol.proto b/common/protocol.proto index e620b2d..9cb835f 100644 --- a/common/protocol.proto +++ b/common/protocol.proto @@ -190,8 +190,8 @@ message StreamCore { optional uint32 data_start_ofs = 13; // Frame Length (includes CRC) - optional FrameLengthMode len_mode = 14; - optional uint32 frame_len = 15; + optional FrameLengthMode len_mode = 14 [default = e_fl_fixed]; + optional uint32 frame_len = 15 [default = 64]; optional uint32 frame_len_min = 16; optional uint32 frame_len_max = 17;