diff --git a/client/dumpview.cpp b/client/dumpview.cpp index d846164..0056502 100644 --- a/client/dumpview.cpp +++ b/client/dumpview.cpp @@ -1,387 +1,387 @@ -#include "dumpview.h" - -//! \todo Enable Scrollbars - -DumpView::DumpView(QWidget *parent) -{ - int w, h; - - // 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 - // 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); - mAsciiPaneTopRect = QRect(mDumpPaneTopRect.right()+w*3, 0, - w*(8+1+8), h); - qDebug("DumpView::DumpView"); -} - -QModelIndex DumpView::indexAt( const QPoint &point ) const -{ -#if 0 - int x = point.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 = point.y()/mLineHeight; - - if ((col < 16) && (row < ((data.size()+16)/16))) - { - selrow = row; - selcol = 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)", 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 - 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) -{ - // FIXME: Use new enum instead of Qt::UserRole - //! \todo (low): generalize this for any model not just our pkt model - - Q_ASSERT(!parent.isValid()); - - qDebug("!!!! %d $$$$", dump.size()); - - for(int i = 0; i < model()->rowCount(parent); i++) - { - QModelIndex index = model()->index(i, 0, parent); - - Q_ASSERT(index.isValid()); - - // Assumption: protocol data is in bytes (not bits) - qDebug("%d: %d bytes", i, model()->data(index, Qt::UserRole).toByteArray().size()); - dump.append(model()->data(index, Qt::UserRole).toByteArray()); - - } - - if (selectionModel()->selectedIndexes().size()) - { - int j, bits; - QModelIndex index; - - Q_ASSERT(selectionModel()->selectedIndexes().size() == 1); - index = selectionModel()->selectedIndexes().at(0); - - if (index.parent().isValid()) - { - // Field - - // SelOfs = SUM(protocol sizes before selected field's protocol) + - // SUM(field sizes before selected field) - - selOfs = 0; - j = index.parent().row() - 1; - while (j >= 0) - { - selOfs += model()->data(index.parent().sibling(j,0), - Qt::UserRole).toByteArray().size(); - j--; - } - - bits = 0; - j = index.row() - 1; - while (j >= 0) - { - bits += model()->data(index.sibling(j,0), Qt::UserRole+1). - toInt(); - j--; - } - selOfs += bits/8; - selSize = model()->data(index, Qt::UserRole).toByteArray().size(); - } - else - { - // Protocol - selOfs = 0; - j = index.row() - 1; - while (j >= 0) - { - selOfs += model()->data(index.sibling(j,0), Qt::UserRole). - toByteArray().size(); - j--; - } - selSize = model()->data(index, Qt::UserRole).toByteArray().size(); - } - } -} - -// TODO(LOW): rewrite this function - it's a mess! -void DumpView::paintEvent(QPaintEvent* event) -{ - QStylePainter painter(viewport()); - QRect offsetRect = mOffsetPaneTopRect; - QRect dumpRect = mDumpPaneTopRect; - QRect asciiRect = mAsciiPaneTopRect; - QPalette pal = palette(); - static QByteArray data; - //QByteArray ba; - int selOfs = -1, selSize; - int curSelOfs, curSelSize; - - 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))); - - if (model()) - { - data.clear(); - 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); - - // 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); - - // 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; - QString selectedAsciiStr, selectedDumpStr; - - qDebug("dumpview::paintEvent - Highlighted (%d, %d)", - curSelOfs, curSelSize); - - // construct the dumpStr and asciiStr - for (int k = curSelOfs; (k < (curSelOfs + curSelSize)); k++) - { - unsigned char c = data.at(k); - - // 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 ((curSelOfs - i) < 8) - r.translate(mCharWidth*(curSelOfs-i)*3, 0); - else - 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 ((curSelOfs - i) < 8) - r.translate(mCharWidth*(curSelOfs-i)*1, 0); - else - 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); - } -} - +#include "dumpview.h" + +//! \todo Enable Scrollbars + +DumpView::DumpView(QWidget *parent) +{ + int w, h; + + // 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 + // 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); + mAsciiPaneTopRect = QRect(mDumpPaneTopRect.right()+w*3, 0, + w*(8+1+8), h); + qDebug("DumpView::DumpView"); +} + +QModelIndex DumpView::indexAt( const QPoint &point ) const +{ +#if 0 + int x = point.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 = point.y()/mLineHeight; + + if ((col < 16) && (row < ((data.size()+16)/16))) + { + selrow = row; + selcol = 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)", 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 + 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) +{ + // FIXME: Use new enum instead of Qt::UserRole + //! \todo (low): generalize this for any model not just our pkt model + + Q_ASSERT(!parent.isValid()); + + qDebug("!!!! %d $$$$", dump.size()); + + for(int i = 0; i < model()->rowCount(parent); i++) + { + QModelIndex index = model()->index(i, 0, parent); + + Q_ASSERT(index.isValid()); + + // Assumption: protocol data is in bytes (not bits) + qDebug("%d: %d bytes", i, model()->data(index, Qt::UserRole).toByteArray().size()); + dump.append(model()->data(index, Qt::UserRole).toByteArray()); + + } + + if (selectionModel()->selectedIndexes().size()) + { + int j, bits; + QModelIndex index; + + Q_ASSERT(selectionModel()->selectedIndexes().size() == 1); + index = selectionModel()->selectedIndexes().at(0); + + if (index.parent().isValid()) + { + // Field + + // SelOfs = SUM(protocol sizes before selected field's protocol) + + // SUM(field sizes before selected field) + + selOfs = 0; + j = index.parent().row() - 1; + while (j >= 0) + { + selOfs += model()->data(index.parent().sibling(j,0), + Qt::UserRole).toByteArray().size(); + j--; + } + + bits = 0; + j = index.row() - 1; + while (j >= 0) + { + bits += model()->data(index.sibling(j,0), Qt::UserRole+1). + toInt(); + j--; + } + selOfs += bits/8; + selSize = model()->data(index, Qt::UserRole).toByteArray().size(); + } + else + { + // Protocol + selOfs = 0; + j = index.row() - 1; + while (j >= 0) + { + selOfs += model()->data(index.sibling(j,0), Qt::UserRole). + toByteArray().size(); + j--; + } + selSize = model()->data(index, Qt::UserRole).toByteArray().size(); + } + } +} + +// TODO(LOW): rewrite this function - it's a mess! +void DumpView::paintEvent(QPaintEvent* event) +{ + QStylePainter painter(viewport()); + QRect offsetRect = mOffsetPaneTopRect; + QRect dumpRect = mDumpPaneTopRect; + QRect asciiRect = mAsciiPaneTopRect; + QPalette pal = palette(); + static QByteArray data; + //QByteArray ba; + int selOfs = -1, selSize; + int curSelOfs, curSelSize; + + 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))); + + if (model()) + { + data.clear(); + 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); + + // 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); + + // 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; + QString selectedAsciiStr, selectedDumpStr; + + qDebug("dumpview::paintEvent - Highlighted (%d, %d)", + curSelOfs, curSelSize); + + // construct the dumpStr and asciiStr + for (int k = curSelOfs; (k < (curSelOfs + curSelSize)); k++) + { + unsigned char c = data.at(k); + + // 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 ((curSelOfs - i) < 8) + r.translate(mCharWidth*(curSelOfs-i)*3, 0); + else + 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 ((curSelOfs - i) < 8) + r.translate(mCharWidth*(curSelOfs-i)*1, 0); + else + 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 db17002..6f7db2e 100644 --- a/client/dumpview.h +++ b/client/dumpview.h @@ -1,42 +1,42 @@ -#include // FIXME: High - - -class DumpView: public QAbstractItemView -{ -public: - DumpView(QWidget *parent=0); - - QModelIndex indexAt( const QPoint &point ) const; - void scrollTo( const QModelIndex &index, ScrollHint hint = EnsureVisible ); - QRect visualRect( const QModelIndex &index ) const; - -protected: - 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: - void 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; } - -private: - QRect mOffsetPaneTopRect; - QRect mDumpPaneTopRect; - QRect mAsciiPaneTopRect; - int mSelectedRow, mSelectedCol; - int mLineHeight; - int mCharWidth; -}; - +#include // FIXME: High + + +class DumpView: public QAbstractItemView +{ +public: + DumpView(QWidget *parent=0); + + QModelIndex indexAt( const QPoint &point ) const; + void scrollTo( const QModelIndex &index, ScrollHint hint = EnsureVisible ); + QRect visualRect( const QModelIndex &index ) const; + +protected: + 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: + void 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; } + +private: + QRect mOffsetPaneTopRect; + QRect mDumpPaneTopRect; + QRect mAsciiPaneTopRect; + int mSelectedRow, mSelectedCol; + int mLineHeight; + int mCharWidth; +}; + diff --git a/client/hexlineedit.cpp b/client/hexlineedit.cpp index 5f099d0..4497710 100644 --- a/client/hexlineedit.cpp +++ b/client/hexlineedit.cpp @@ -1,72 +1,72 @@ -#include "hexlineedit.h" -#include "qdebug.h" - -QString & uintToHexStr(quint64 num, QString &hexStr, quint8 octets); - -HexLineEdit::HexLineEdit( QWidget * parent) - : QLineEdit(parent) -{ - //QLineEdit::QLineEdit(parent); -} - -void HexLineEdit::focusOutEvent( QFocusEvent *e ) -{ -#if 0 - const QValidator *v = validator(); - if ( v ) - { - int curpos = cursorPosition(); - QString str = text(); - if ( v->validate( str, curpos ) == QValidator::Acceptable ) - { - if ( curpos != cursorPosition() ) - setCursorPosition( curpos ); - if ( str != text() ) - setText( str ); - } - else - { - if ( curpos != cursorPosition() ) - setCursorPosition( curpos ); - str = text(); - v->fixup( str ); - if ( str != text() ) - { - setText( str ); - } - } - } - QLineEdit::focusOutEvent( e ); - emit focusOut(); -#else -#define uintToHexStr(num, bytesize) \ - QString("%1").arg((num), (bytesize)*2 , 16, QChar('0')) - - bool isOk; - ulong num; - - qDebug("before = %s\n", text().toAscii().data()); - num = text().remove(QChar(' ')).toULong(&isOk, 16); - setText(uintToHexStr(num, 4)); - qDebug("after = %s\n", text().toAscii().data()); -#undef uintToHexStr -#endif -} - -#if 0 -void HexLineEdit::focusInEvent( QFocusEvent *e ) -{ - QLineEdit::focusInEvent( e ); - emit focusIn(); -} - -void HexLineEdit::keyPressEvent( QKeyEvent *e ) -{ - QLineEdit::keyPressEvent( e ); - if ( e->key() == Key_Enter || e->key() == Key_Return ) - { - setSelection( 0, text().length() ); - } -} -#endif - +#include "hexlineedit.h" +#include "qdebug.h" + +QString & uintToHexStr(quint64 num, QString &hexStr, quint8 octets); + +HexLineEdit::HexLineEdit( QWidget * parent) + : QLineEdit(parent) +{ + //QLineEdit::QLineEdit(parent); +} + +void HexLineEdit::focusOutEvent( QFocusEvent *e ) +{ +#if 0 + const QValidator *v = validator(); + if ( v ) + { + int curpos = cursorPosition(); + QString str = text(); + if ( v->validate( str, curpos ) == QValidator::Acceptable ) + { + if ( curpos != cursorPosition() ) + setCursorPosition( curpos ); + if ( str != text() ) + setText( str ); + } + else + { + if ( curpos != cursorPosition() ) + setCursorPosition( curpos ); + str = text(); + v->fixup( str ); + if ( str != text() ) + { + setText( str ); + } + } + } + QLineEdit::focusOutEvent( e ); + emit focusOut(); +#else +#define uintToHexStr(num, bytesize) \ + QString("%1").arg((num), (bytesize)*2 , 16, QChar('0')) + + bool isOk; + ulong num; + + qDebug("before = %s\n", text().toAscii().data()); + num = text().remove(QChar(' ')).toULong(&isOk, 16); + setText(uintToHexStr(num, 4)); + qDebug("after = %s\n", text().toAscii().data()); +#undef uintToHexStr +#endif +} + +#if 0 +void HexLineEdit::focusInEvent( QFocusEvent *e ) +{ + QLineEdit::focusInEvent( e ); + emit focusIn(); +} + +void HexLineEdit::keyPressEvent( QKeyEvent *e ) +{ + QLineEdit::keyPressEvent( e ); + if ( e->key() == Key_Enter || e->key() == Key_Return ) + { + setSelection( 0, text().length() ); + } +} +#endif + diff --git a/client/hexlineedit.h b/client/hexlineedit.h index 937d263..09f638a 100644 --- a/client/hexlineedit.h +++ b/client/hexlineedit.h @@ -1,24 +1,24 @@ -#ifndef _HEXLINEEDIT -#define _HEXLINEEDIT - -#include - -class HexLineEdit : public QLineEdit -{ - Q_OBJECT -public: - // Constructors - HexLineEdit ( QWidget * parent); - -protected: - void focusOutEvent( QFocusEvent *e ); - //void focusInEvent( QFocusEvent *e ); - //void keyPressEvent( QKeyEvent *e ); - -signals: - //void focusIn(); - void focusOut(); -}; - -#endif - +#ifndef _HEXLINEEDIT +#define _HEXLINEEDIT + +#include + +class HexLineEdit : public QLineEdit +{ + Q_OBJECT +public: + // Constructors + HexLineEdit ( QWidget * parent); + +protected: + void focusOutEvent( QFocusEvent *e ); + //void focusInEvent( QFocusEvent *e ); + //void keyPressEvent( QKeyEvent *e ); + +signals: + //void focusIn(); + void focusOut(); +}; + +#endif + diff --git a/client/main.cpp b/client/main.cpp index 9a9a5d8..994952a 100644 --- a/client/main.cpp +++ b/client/main.cpp @@ -1,12 +1,12 @@ -#include "mainwindow.h" - -#include - -int main(int argc, char* argv[]) -{ - QApplication app(argc, argv); - MainWindow mainWin; - - mainWin.show(); - return app.exec(); -} +#include "mainwindow.h" + +#include + +int main(int argc, char* argv[]) +{ + QApplication app(argc, argv); + MainWindow mainWin; + + mainWin.show(); + return app.exec(); +} diff --git a/client/mainwindow.cpp b/client/mainwindow.cpp index 2aee434..0f818c5 100644 --- a/client/mainwindow.cpp +++ b/client/mainwindow.cpp @@ -1,65 +1,65 @@ -#include "mainwindow.h" - -#if 0 -#include "dbgthread.h" -#endif - -#include "portgrouplist.h" -#include "portstatswindow.h" -#include "portswindow.h" -#include "ui_about.h" - -#include -#include - -PortGroupList *pgl; - -MainWindow::MainWindow(QWidget *parent) - : QMainWindow (parent) -{ - localServer_ = new QProcess(this); - localServer_->start("drone.exe"); - - pgl = new PortGroupList; - - portsWindow = new PortsWindow(pgl, this); - statsWindow = new PortStatsWindow(pgl, this); - portsDock = new QDockWidget(tr("Ports"), this); - statsDock = new QDockWidget(tr("Stats"), this); - - setupUi(this); - - statsDock->setWidget(statsWindow); - addDockWidget(Qt::BottomDockWidgetArea, statsDock); - portsDock->setWidget(portsWindow); - addDockWidget(Qt::TopDockWidgetArea, portsDock); - - connect(actionFileExit, SIGNAL(triggered()), this, SLOT(close())); -#if 0 - { - DbgThread *dbg = new DbgThread(pgl); - dbg->start(); - } -#endif -} - -MainWindow::~MainWindow() -{ - delete pgl; - localServer_->terminate(); - localServer_->waitForFinished(); - delete localServer_; -} - -void MainWindow::on_actionHelpAbout_triggered() -{ - QDialog *aboutDialog = new QDialog; - - Ui::About about; - about.setupUi(aboutDialog); - - aboutDialog->exec(); - - delete aboutDialog; -} - +#include "mainwindow.h" + +#if 0 +#include "dbgthread.h" +#endif + +#include "portgrouplist.h" +#include "portstatswindow.h" +#include "portswindow.h" +#include "ui_about.h" + +#include +#include + +PortGroupList *pgl; + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow (parent) +{ + localServer_ = new QProcess(this); + localServer_->start("drone.exe"); + + pgl = new PortGroupList; + + portsWindow = new PortsWindow(pgl, this); + statsWindow = new PortStatsWindow(pgl, this); + portsDock = new QDockWidget(tr("Ports"), this); + statsDock = new QDockWidget(tr("Stats"), this); + + setupUi(this); + + statsDock->setWidget(statsWindow); + addDockWidget(Qt::BottomDockWidgetArea, statsDock); + portsDock->setWidget(portsWindow); + addDockWidget(Qt::TopDockWidgetArea, portsDock); + + connect(actionFileExit, SIGNAL(triggered()), this, SLOT(close())); +#if 0 + { + DbgThread *dbg = new DbgThread(pgl); + dbg->start(); + } +#endif +} + +MainWindow::~MainWindow() +{ + delete pgl; + localServer_->terminate(); + localServer_->waitForFinished(); + delete localServer_; +} + +void MainWindow::on_actionHelpAbout_triggered() +{ + QDialog *aboutDialog = new QDialog; + + Ui::About about; + about.setupUi(aboutDialog); + + aboutDialog->exec(); + + delete aboutDialog; +} + diff --git a/client/mainwindow.h b/client/mainwindow.h index 53c8eac..9ddd926 100644 --- a/client/mainwindow.h +++ b/client/mainwindow.h @@ -1,33 +1,33 @@ -#ifndef _MAIN_WINDOW_H -#define _MAIN_WINDOW_H - -#include "ui_mainwindow.h" -#include - -class PortsWindow; -class PortStatsWindow; - -class QDockWidget; -class QProcess; - -class MainWindow : public QMainWindow, private Ui::MainWindow -{ - Q_OBJECT - -private: - QProcess *localServer_; - PortsWindow *portsWindow; - PortStatsWindow *statsWindow; - QDockWidget *portsDock; - QDockWidget *statsDock; - -public: - MainWindow(QWidget *parent = 0); - ~MainWindow(); - -public slots: - void on_actionHelpAbout_triggered(); -}; - -#endif - +#ifndef _MAIN_WINDOW_H +#define _MAIN_WINDOW_H + +#include "ui_mainwindow.h" +#include + +class PortsWindow; +class PortStatsWindow; + +class QDockWidget; +class QProcess; + +class MainWindow : public QMainWindow, private Ui::MainWindow +{ + Q_OBJECT + +private: + QProcess *localServer_; + PortsWindow *portsWindow; + PortStatsWindow *statsWindow; + QDockWidget *portsDock; + QDockWidget *statsDock; + +public: + MainWindow(QWidget *parent = 0); + ~MainWindow(); + +public slots: + void on_actionHelpAbout_triggered(); +}; + +#endif + diff --git a/client/ostinato.pro b/client/ostinato.pro index b0dd570..3afbdc2 100644 --- a/client/ostinato.pro +++ b/client/ostinato.pro @@ -1,57 +1,57 @@ -TEMPLATE = app -CONFIG += qt debug -QT += network script -INCLUDEPATH += "../rpc/" "../common/" -LIBS += -lprotobuf -win32:LIBS += -L"../common/debug" -lostproto -unix: LIBS += -L"../common" -lostproto -win32:LIBS += -L"../rpc/debug" -lpbrpc -unix:LIBS += -L"../rpc" -lpbrpc -POST_TARGETDEPS += "../common/debug/libostproto.a" "../rpc/debug/libpbrpc.a" -RESOURCES += ostinato.qrc -HEADERS += \ - dumpview.h \ - hexlineedit.h \ - mainwindow.h \ - packetmodel.h \ - port.h \ - portgroup.h \ - portgrouplist.h \ - portmodel.h \ - portstatsmodel.h \ - portstatsfilterdialog.h \ - portstatswindow.h \ - portswindow.h \ - streamconfigdialog.h \ - streamlistdelegate.h \ - streammodel.h - -FORMS += \ - about.ui \ - mainwindow.ui \ - portstatsfilter.ui \ - portstatswindow.ui \ - portswindow.ui \ - streamconfigdialog.ui - -SOURCES += \ - dumpview.cpp \ - stream.cpp \ - hexlineedit.cpp \ - main.cpp \ - mainwindow.cpp \ - packetmodel.cpp \ - port.cpp \ - portgroup.cpp \ - portgrouplist.cpp \ - portmodel.cpp \ - portstatsmodel.cpp \ - portstatsfilterdialog.cpp \ - portstatswindow.cpp \ - portswindow.cpp \ - streamconfigdialog.cpp \ - streamlistdelegate.cpp \ - streammodel.cpp - -# TODO(LOW): Test only -include(modeltest.pri) +TEMPLATE = app +CONFIG += qt debug +QT += network script +INCLUDEPATH += "../rpc/" "../common/" +LIBS += -lprotobuf +win32:LIBS += -L"../common/debug" -lostproto +unix: LIBS += -L"../common" -lostproto +win32:LIBS += -L"../rpc/debug" -lpbrpc +unix:LIBS += -L"../rpc" -lpbrpc +POST_TARGETDEPS += "../common/debug/libostproto.a" "../rpc/debug/libpbrpc.a" +RESOURCES += ostinato.qrc +HEADERS += \ + dumpview.h \ + hexlineedit.h \ + mainwindow.h \ + packetmodel.h \ + port.h \ + portgroup.h \ + portgrouplist.h \ + portmodel.h \ + portstatsmodel.h \ + portstatsfilterdialog.h \ + portstatswindow.h \ + portswindow.h \ + streamconfigdialog.h \ + streamlistdelegate.h \ + streammodel.h + +FORMS += \ + about.ui \ + mainwindow.ui \ + portstatsfilter.ui \ + portstatswindow.ui \ + portswindow.ui \ + streamconfigdialog.ui + +SOURCES += \ + dumpview.cpp \ + stream.cpp \ + hexlineedit.cpp \ + main.cpp \ + mainwindow.cpp \ + packetmodel.cpp \ + port.cpp \ + portgroup.cpp \ + portgrouplist.cpp \ + portmodel.cpp \ + portstatsmodel.cpp \ + portstatsfilterdialog.cpp \ + portstatswindow.cpp \ + portswindow.cpp \ + streamconfigdialog.cpp \ + streamlistdelegate.cpp \ + streammodel.cpp + +# TODO(LOW): Test only +include(modeltest.pri) diff --git a/client/packetmodel.cpp b/client/packetmodel.cpp index a3aee4d..df5a30b 100644 --- a/client/packetmodel.cpp +++ b/client/packetmodel.cpp @@ -1,220 +1,220 @@ -#include - -#include "packetmodel.h" -#include "../common/protocollistiterator.h" -#include "../common/abstractprotocol.h" - -PacketModel::PacketModel(QObject *parent) -{ -} - -void PacketModel::setSelectedProtocols(ProtocolListIterator &iter) -{ - QList currentProtocols; - - iter.toFront(); - while (iter.hasNext()) - currentProtocols.append(iter.next()); - - if (mSelectedProtocols != currentProtocols) - { - mSelectedProtocols = currentProtocols; - reset(); - } -} - -int PacketModel::rowCount(const QModelIndex &parent) const -{ - IndexId parentId; - - // qDebug("in %s", __FUNCTION__); - - // Parent == Invalid i.e. Invisible Root. - // ==> Children are Protocol (Top Level) Items - if (!parent.isValid()) - return mSelectedProtocols.size(); - - // Parent - Valid Item - parentId.w = parent.internalId(); - switch(parentId.ws.type) - { - case ITYP_PROTOCOL: - return mSelectedProtocols.at(parentId.ws.protocol)->frameFieldCount(); - case ITYP_FIELD: - return 0; - default: - qWarning("%s: Unhandled ItemType", __FUNCTION__); - } - - Q_ASSERT(1 == 0); // Unreachable code - qWarning("%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; - - if (!hasIndex(row, col, parent)) - goto _exit; - - // Parent is Invisible Root - // Request for a Protocol Item - if (!parent.isValid()) - { - id.w = 0; - id.ws.type = ITYP_PROTOCOL; - id.ws.protocol = row; - index = createIndex(row, col, id.w); - goto _exit; - } - - // Parent is a Valid Item - parentId.w = parent.internalId(); - id.w = parentId.w; - switch(parentId.ws.type) - { - case ITYP_PROTOCOL: - id.ws.type = ITYP_FIELD; - index = createIndex(row, col, id.w); - goto _exit; - - case ITYP_FIELD: - Q_ASSERT(1 == 0); // Unreachable code - goto _exit; - - default: - qWarning("%s: Unhandled ItemType", __FUNCTION__); - } - - Q_ASSERT(1 == 0); // Unreachable code - -_exit: - return index; -} - -QModelIndex PacketModel::parent(const QModelIndex &index) const -{ - QModelIndex parentIndex; - IndexId id, parentId; - - if (!index.isValid()) - return QModelIndex(); - - id.w = index.internalId(); - parentId.w = id.w; - switch(id.ws.type) - { - case ITYP_PROTOCOL: - // return invalid index for invisible root - goto _exit; - - case ITYP_FIELD: - parentId.ws.type = ITYP_PROTOCOL; - parentIndex = createIndex(id.ws.protocol, 0, parentId.w); - goto _exit; - - default: - qWarning("%s: Unhandled ItemType", __FUNCTION__); - } - - Q_ASSERT(1 == 1); // Unreachable code - -_exit: - return parentIndex; -} - -QVariant PacketModel::data(const QModelIndex &index, int role) const -{ - IndexId id; - int fieldIdx = 0; - - if (!index.isValid()) - return QVariant(); - - id.w = index.internalId(); - - if (id.ws.type == ITYP_FIELD) - { - const AbstractProtocol *p = mSelectedProtocols.at(id.ws.protocol); - int n = index.row() + 1; - - while (n) - { - if (!(p->fieldFlags(fieldIdx).testFlag( - AbstractProtocol::FieldIsMeta))) - n--; - fieldIdx++; - } - fieldIdx--; - } - - // FIXME(HI): Relook at this completely - if (role == Qt::UserRole) - { - switch(id.ws.type) - { - case ITYP_PROTOCOL: - qDebug("*** %d/%d", id.ws.protocol, mSelectedProtocols.size()); - return mSelectedProtocols.at(id.ws.protocol)-> - protocolFrameValue(); - - case ITYP_FIELD: - return mSelectedProtocols.at(id.ws.protocol)->fieldData( - fieldIdx, AbstractProtocol::FieldFrameValue); - - default: - qWarning("%s: Unhandled ItemType", __FUNCTION__); - } - return QByteArray(); - } - - // FIXME: Use a new enum here instead of UserRole - if (role == (Qt::UserRole+1)) - { - switch(id.ws.type) - { - case ITYP_PROTOCOL: - return mSelectedProtocols.at(id.ws.protocol)-> - protocolFrameValue().size(); - - case ITYP_FIELD: - return mSelectedProtocols.at(id.ws.protocol)->fieldData( - fieldIdx, AbstractProtocol::FieldBitSize); - - default: - qWarning("%s: Unhandled ItemType", __FUNCTION__); - } - return QVariant(); - } - - if (role != Qt::DisplayRole) - return QVariant(); - - switch(id.ws.type) - { - case ITYP_PROTOCOL: - return QString("%1 (%2)") - .arg(mSelectedProtocols.at(id.ws.protocol)->shortName()) - .arg(mSelectedProtocols.at(id.ws.protocol)->name()); - - case ITYP_FIELD: - return mSelectedProtocols.at(id.ws.protocol)->fieldData(fieldIdx, - AbstractProtocol::FieldName).toString() + QString(" : ") + - mSelectedProtocols.at(id.ws.protocol)->fieldData(fieldIdx, - AbstractProtocol::FieldTextValue).toString(); - - default: - qWarning("%s: Unhandled ItemType", __FUNCTION__); - } - - Q_ASSERT(1 == 1); // Unreachable code - - return QVariant(); -} +#include + +#include "packetmodel.h" +#include "../common/protocollistiterator.h" +#include "../common/abstractprotocol.h" + +PacketModel::PacketModel(QObject *parent) +{ +} + +void PacketModel::setSelectedProtocols(ProtocolListIterator &iter) +{ + QList currentProtocols; + + iter.toFront(); + while (iter.hasNext()) + currentProtocols.append(iter.next()); + + if (mSelectedProtocols != currentProtocols) + { + mSelectedProtocols = currentProtocols; + reset(); + } +} + +int PacketModel::rowCount(const QModelIndex &parent) const +{ + IndexId parentId; + + // qDebug("in %s", __FUNCTION__); + + // Parent == Invalid i.e. Invisible Root. + // ==> Children are Protocol (Top Level) Items + if (!parent.isValid()) + return mSelectedProtocols.size(); + + // Parent - Valid Item + parentId.w = parent.internalId(); + switch(parentId.ws.type) + { + case ITYP_PROTOCOL: + return mSelectedProtocols.at(parentId.ws.protocol)->frameFieldCount(); + case ITYP_FIELD: + return 0; + default: + qWarning("%s: Unhandled ItemType", __FUNCTION__); + } + + Q_ASSERT(1 == 0); // Unreachable code + qWarning("%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; + + if (!hasIndex(row, col, parent)) + goto _exit; + + // Parent is Invisible Root + // Request for a Protocol Item + if (!parent.isValid()) + { + id.w = 0; + id.ws.type = ITYP_PROTOCOL; + id.ws.protocol = row; + index = createIndex(row, col, id.w); + goto _exit; + } + + // Parent is a Valid Item + parentId.w = parent.internalId(); + id.w = parentId.w; + switch(parentId.ws.type) + { + case ITYP_PROTOCOL: + id.ws.type = ITYP_FIELD; + index = createIndex(row, col, id.w); + goto _exit; + + case ITYP_FIELD: + Q_ASSERT(1 == 0); // Unreachable code + goto _exit; + + default: + qWarning("%s: Unhandled ItemType", __FUNCTION__); + } + + Q_ASSERT(1 == 0); // Unreachable code + +_exit: + return index; +} + +QModelIndex PacketModel::parent(const QModelIndex &index) const +{ + QModelIndex parentIndex; + IndexId id, parentId; + + if (!index.isValid()) + return QModelIndex(); + + id.w = index.internalId(); + parentId.w = id.w; + switch(id.ws.type) + { + case ITYP_PROTOCOL: + // return invalid index for invisible root + goto _exit; + + case ITYP_FIELD: + parentId.ws.type = ITYP_PROTOCOL; + parentIndex = createIndex(id.ws.protocol, 0, parentId.w); + goto _exit; + + default: + qWarning("%s: Unhandled ItemType", __FUNCTION__); + } + + Q_ASSERT(1 == 1); // Unreachable code + +_exit: + return parentIndex; +} + +QVariant PacketModel::data(const QModelIndex &index, int role) const +{ + IndexId id; + int fieldIdx = 0; + + if (!index.isValid()) + return QVariant(); + + id.w = index.internalId(); + + if (id.ws.type == ITYP_FIELD) + { + const AbstractProtocol *p = mSelectedProtocols.at(id.ws.protocol); + int n = index.row() + 1; + + while (n) + { + if (!(p->fieldFlags(fieldIdx).testFlag( + AbstractProtocol::FieldIsMeta))) + n--; + fieldIdx++; + } + fieldIdx--; + } + + // FIXME(HI): Relook at this completely + if (role == Qt::UserRole) + { + switch(id.ws.type) + { + case ITYP_PROTOCOL: + qDebug("*** %d/%d", id.ws.protocol, mSelectedProtocols.size()); + return mSelectedProtocols.at(id.ws.protocol)-> + protocolFrameValue(); + + case ITYP_FIELD: + return mSelectedProtocols.at(id.ws.protocol)->fieldData( + fieldIdx, AbstractProtocol::FieldFrameValue); + + default: + qWarning("%s: Unhandled ItemType", __FUNCTION__); + } + return QByteArray(); + } + + // FIXME: Use a new enum here instead of UserRole + if (role == (Qt::UserRole+1)) + { + switch(id.ws.type) + { + case ITYP_PROTOCOL: + return mSelectedProtocols.at(id.ws.protocol)-> + protocolFrameValue().size(); + + case ITYP_FIELD: + return mSelectedProtocols.at(id.ws.protocol)->fieldData( + fieldIdx, AbstractProtocol::FieldBitSize); + + default: + qWarning("%s: Unhandled ItemType", __FUNCTION__); + } + return QVariant(); + } + + if (role != Qt::DisplayRole) + return QVariant(); + + switch(id.ws.type) + { + case ITYP_PROTOCOL: + return QString("%1 (%2)") + .arg(mSelectedProtocols.at(id.ws.protocol)->shortName()) + .arg(mSelectedProtocols.at(id.ws.protocol)->name()); + + case ITYP_FIELD: + return mSelectedProtocols.at(id.ws.protocol)->fieldData(fieldIdx, + AbstractProtocol::FieldName).toString() + QString(" : ") + + mSelectedProtocols.at(id.ws.protocol)->fieldData(fieldIdx, + AbstractProtocol::FieldTextValue).toString(); + + default: + qWarning("%s: Unhandled ItemType", __FUNCTION__); + } + + Q_ASSERT(1 == 1); // Unreachable code + + return QVariant(); +} diff --git a/client/packetmodel.h b/client/packetmodel.h index 2568724..cd81a8f 100644 --- a/client/packetmodel.h +++ b/client/packetmodel.h @@ -1,40 +1,40 @@ -#ifndef _PACKET_MODEL_H -#define _PACKET_MODEL_H - -#include - -class ProtocolListIterator; -class AbstractProtocol; - -class PacketModel: public QAbstractItemModel -{ - -public: - PacketModel(QObject *parent = 0); - void setSelectedProtocols(ProtocolListIterator &iter); - - int rowCount(const QModelIndex &parent = QModelIndex()) const; - int columnCount(const QModelIndex &parent = QModelIndex()) const; - QVariant data(const QModelIndex &index, int role) const; - QVariant headerData(int section, Qt::Orientation orientation, - int role = Qt::DisplayRole) const { return QVariant(); } ; - QModelIndex index (int row, int col, const QModelIndex & parent = QModelIndex() ) const; - QModelIndex parent(const QModelIndex &index) const; - -private: - typedef union _IndexId - { - quint32 w; - struct - { - quint16 type; -#define ITYP_PROTOCOL 1 -#define ITYP_FIELD 2 - quint16 protocol; // protocol is valid for both ITYPs - } ws; - } IndexId; - - QList mSelectedProtocols; -}; -#endif - +#ifndef _PACKET_MODEL_H +#define _PACKET_MODEL_H + +#include + +class ProtocolListIterator; +class AbstractProtocol; + +class PacketModel: public QAbstractItemModel +{ + +public: + PacketModel(QObject *parent = 0); + void setSelectedProtocols(ProtocolListIterator &iter); + + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + QVariant data(const QModelIndex &index, int role) const; + QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const { return QVariant(); } ; + QModelIndex index (int row, int col, const QModelIndex & parent = QModelIndex() ) const; + QModelIndex parent(const QModelIndex &index) const; + +private: + typedef union _IndexId + { + quint32 w; + struct + { + quint16 type; +#define ITYP_PROTOCOL 1 +#define ITYP_FIELD 2 + quint16 protocol; // protocol is valid for both ITYPs + } ws; + } IndexId; + + QList mSelectedProtocols; +}; +#endif + diff --git a/client/port.cpp b/client/port.cpp index 8f708f1..2509927 100644 --- a/client/port.cpp +++ b/client/port.cpp @@ -1,197 +1,197 @@ -#include - -#include - -#include "port.h" -#include "pbhelper.h" - -uint Port::mAllocStreamId = 0; - -uint Port::newStreamId() -{ - return mAllocStreamId++; -} - -Port::Port(quint32 id, quint32 portGroupId) -{ - mPortId = id; - d.mutable_port_id()->set_id(id); - stats.mutable_port_id()->set_id(id); - mPortGroupId = portGroupId; -} - -Port::~Port() -{ -} - -void Port::updatePortConfig(OstProto::Port *port) -{ - d.MergeFrom(*port); -} - -void Port::updateStreamOrdinalsFromIndex() -{ - for (int i=0; i < mStreams.size(); i++) - mStreams[i]->setOrdinal(i); -} - -void Port::reorderStreamsByOrdinals() -{ - qSort(mStreams); -} - -bool Port::newStreamAt(int index) -{ - Stream *s = new Stream; - - if (index > mStreams.size()) - return false; - - s->setId(newStreamId()); - mStreams.insert(index, s); - updateStreamOrdinalsFromIndex(); - - return true; -} - -bool Port::deleteStreamAt(int index) -{ - if (index >= mStreams.size()) - return false; - - delete mStreams.takeAt(index); - updateStreamOrdinalsFromIndex(); - - return true; -} - -bool Port::insertStream(uint streamId) -{ - Stream *s = new Stream; - - s->setId(streamId); - - // FIXME(MED): If a stream with id already exists, what do we do? - mStreams.append(s); - - // Update mAllocStreamId to take into account the stream id received - // from server - if (mAllocStreamId <= streamId) - mAllocStreamId = streamId + 1; - - return true; -} - -bool Port::updateStream(uint streamId, OstProto::Stream *stream) -{ - int i, streamIndex; - - for (i = 0; i < mStreams.size(); i++) - { - if (streamId == mStreams[i]->id()) - goto _found; - } - - qDebug("%s: Invalid stream id %d", __FUNCTION__, streamId); - return false; - -_found: - streamIndex = i; - - mStreams[streamIndex]->protoDataCopyFrom(*stream); - reorderStreamsByOrdinals(); - - return true; -} - -void Port::getDeletedStreamsSinceLastSync( - OstProto::StreamIdList &streamIdList) -{ - streamIdList.clear_stream_id(); - for (int i = 0; i < mLastSyncStreamList.size(); i++) - { - int j; - - for (j = 0; j < mStreams.size(); j++) - { - if (mLastSyncStreamList[i] == mStreams[j]->id()) - break; - } - - if (j < mStreams.size()) - { - // stream still exists! - continue; - } - else - { - // stream has been deleted since last sync - OstProto::StreamId *s; - - s = streamIdList.add_stream_id(); - s->set_id(mLastSyncStreamList.at(i)); - } - } -} - -void Port::getNewStreamsSinceLastSync( - OstProto::StreamIdList &streamIdList) -{ - streamIdList.clear_stream_id(); - for (int i = 0; i < mStreams.size(); i++) - { - if (mLastSyncStreamList.contains(mStreams[i]->id())) - { - // existing stream! - continue; - } - else - { - // new stream! - OstProto::StreamId *s; - - s = streamIdList.add_stream_id(); - s->set_id(mStreams[i]->id()); - } - } -} - -void Port::getModifiedStreamsSinceLastSync( - OstProto::StreamConfigList &streamConfigList) -{ - qDebug("In %s", __FUNCTION__); - - //streamConfigList.mutable_port_id()->set_id(mPortId); - for (int i = 0; i < mStreams.size(); i++) - { - OstProto::Stream *s; - - s = streamConfigList.add_stream(); - mStreams[i]->protoDataCopyInto(*s); - } - qDebug("Done %s", __FUNCTION__); -} - -void Port::when_syncComplete() -{ - qSort(mStreams); - - mLastSyncStreamList.clear(); - for (int i=0; iid()); -} - -void Port::updateStats(OstProto::PortStats *portStats) -{ - OstProto::PortState oldState; - - oldState = stats.state(); - stats.MergeFrom(*portStats); - - if (oldState.link_state() != stats.state().link_state()) - { - qDebug("portstate changed"); - emit portDataChanged(mPortGroupId, mPortId); - } -} - +#include + +#include + +#include "port.h" +#include "pbhelper.h" + +uint Port::mAllocStreamId = 0; + +uint Port::newStreamId() +{ + return mAllocStreamId++; +} + +Port::Port(quint32 id, quint32 portGroupId) +{ + mPortId = id; + d.mutable_port_id()->set_id(id); + stats.mutable_port_id()->set_id(id); + mPortGroupId = portGroupId; +} + +Port::~Port() +{ +} + +void Port::updatePortConfig(OstProto::Port *port) +{ + d.MergeFrom(*port); +} + +void Port::updateStreamOrdinalsFromIndex() +{ + for (int i=0; i < mStreams.size(); i++) + mStreams[i]->setOrdinal(i); +} + +void Port::reorderStreamsByOrdinals() +{ + qSort(mStreams); +} + +bool Port::newStreamAt(int index) +{ + Stream *s = new Stream; + + if (index > mStreams.size()) + return false; + + s->setId(newStreamId()); + mStreams.insert(index, s); + updateStreamOrdinalsFromIndex(); + + return true; +} + +bool Port::deleteStreamAt(int index) +{ + if (index >= mStreams.size()) + return false; + + delete mStreams.takeAt(index); + updateStreamOrdinalsFromIndex(); + + return true; +} + +bool Port::insertStream(uint streamId) +{ + Stream *s = new Stream; + + s->setId(streamId); + + // FIXME(MED): If a stream with id already exists, what do we do? + mStreams.append(s); + + // Update mAllocStreamId to take into account the stream id received + // from server + if (mAllocStreamId <= streamId) + mAllocStreamId = streamId + 1; + + return true; +} + +bool Port::updateStream(uint streamId, OstProto::Stream *stream) +{ + int i, streamIndex; + + for (i = 0; i < mStreams.size(); i++) + { + if (streamId == mStreams[i]->id()) + goto _found; + } + + qDebug("%s: Invalid stream id %d", __FUNCTION__, streamId); + return false; + +_found: + streamIndex = i; + + mStreams[streamIndex]->protoDataCopyFrom(*stream); + reorderStreamsByOrdinals(); + + return true; +} + +void Port::getDeletedStreamsSinceLastSync( + OstProto::StreamIdList &streamIdList) +{ + streamIdList.clear_stream_id(); + for (int i = 0; i < mLastSyncStreamList.size(); i++) + { + int j; + + for (j = 0; j < mStreams.size(); j++) + { + if (mLastSyncStreamList[i] == mStreams[j]->id()) + break; + } + + if (j < mStreams.size()) + { + // stream still exists! + continue; + } + else + { + // stream has been deleted since last sync + OstProto::StreamId *s; + + s = streamIdList.add_stream_id(); + s->set_id(mLastSyncStreamList.at(i)); + } + } +} + +void Port::getNewStreamsSinceLastSync( + OstProto::StreamIdList &streamIdList) +{ + streamIdList.clear_stream_id(); + for (int i = 0; i < mStreams.size(); i++) + { + if (mLastSyncStreamList.contains(mStreams[i]->id())) + { + // existing stream! + continue; + } + else + { + // new stream! + OstProto::StreamId *s; + + s = streamIdList.add_stream_id(); + s->set_id(mStreams[i]->id()); + } + } +} + +void Port::getModifiedStreamsSinceLastSync( + OstProto::StreamConfigList &streamConfigList) +{ + qDebug("In %s", __FUNCTION__); + + //streamConfigList.mutable_port_id()->set_id(mPortId); + for (int i = 0; i < mStreams.size(); i++) + { + OstProto::Stream *s; + + s = streamConfigList.add_stream(); + mStreams[i]->protoDataCopyInto(*s); + } + qDebug("Done %s", __FUNCTION__); +} + +void Port::when_syncComplete() +{ + qSort(mStreams); + + mLastSyncStreamList.clear(); + for (int i=0; iid()); +} + +void Port::updateStats(OstProto::PortStats *portStats) +{ + OstProto::PortState oldState; + + oldState = stats.state(); + stats.MergeFrom(*portStats); + + if (oldState.link_state() != stats.state().link_state()) + { + qDebug("portstate changed"); + emit portDataChanged(mPortGroupId, mPortId); + } +} + diff --git a/client/port.h b/client/port.h index 09e025a..53842a5 100644 --- a/client/port.h +++ b/client/port.h @@ -1,98 +1,98 @@ -#ifndef _PORT_H -#define _PORT_H - -#include -#include -#include -#include "stream.h" - -//class StreamModel; - -class Port : public QObject { - - Q_OBJECT - - static uint mAllocStreamId; - OstProto::Port d; - OstProto::PortStats stats; - - // FIXME(HI): consider removing mPortId as it is duplicated inside 'd' - quint32 mPortId; - quint32 mPortGroupId; - QString mUserAlias; // user defined - - QList mLastSyncStreamList; - QList mStreams; // sorted by stream's ordinal value - - uint newStreamId(); - void updateStreamOrdinalsFromIndex(); - void reorderStreamsByOrdinals(); - -public: - enum AdminStatus { AdminDisable, AdminEnable }; - enum ControlMode { ControlShared, ControlExclusive }; - - // FIXME(HIGH): default args is a hack for QList operations on Port - Port(quint32 id = 0xFFFFFFFF, quint32 pgId = 0xFFFFFFFF); - ~Port(); - - quint32 portGroupId() const { return mPortGroupId; } - const QString& userAlias() const { return mUserAlias; } - - quint32 id() const - { return d.port_id().id(); } - const QString name() const - { return QString().fromStdString(d.name()); } - const QString description() const - { return QString().fromStdString(d.description()); } - AdminStatus adminStatus() - { return (d.is_enabled()?AdminEnable:AdminDisable); } - ControlMode controlMode() - { return (d.is_exclusive_control()?ControlExclusive:ControlShared); } - - //void setAdminEnable(AdminStatus status) { mAdminStatus = status; } - void setAlias(QString &alias) { mUserAlias = alias; } - //void setExclusive(bool flag); - - int numStreams() { return mStreams.size(); } - Stream* streamByIndex(int index) - { - Q_ASSERT(index < mStreams.size()); - return mStreams[index]; - } - OstProto::LinkState linkState() - { return stats.state().link_state(); } - - OstProto::PortStats getStats() { return stats; } - - // FIXME(MED): naming inconsistency - PortConfig/Stream; also retVal - void updatePortConfig(OstProto::Port *port); - - //! Used by StreamModel - //@{ - bool newStreamAt(int index); - bool deleteStreamAt(int index); - //@} - - //! Used by MyService::Stub to update from config received from server - //@{ - bool insertStream(uint streamId); - bool updateStream(uint streamId, OstProto::Stream *stream); - //@} - - void getDeletedStreamsSinceLastSync(OstProto::StreamIdList &streamIdList); - void getNewStreamsSinceLastSync(OstProto::StreamIdList &streamIdList); - void getModifiedStreamsSinceLastSync( - OstProto::StreamConfigList &streamConfigList); - - - void when_syncComplete(); - - void updateStats(OstProto::PortStats *portStats); - -signals: - void portDataChanged(int portGroupId, int portId); - -}; - -#endif +#ifndef _PORT_H +#define _PORT_H + +#include +#include +#include +#include "stream.h" + +//class StreamModel; + +class Port : public QObject { + + Q_OBJECT + + static uint mAllocStreamId; + OstProto::Port d; + OstProto::PortStats stats; + + // FIXME(HI): consider removing mPortId as it is duplicated inside 'd' + quint32 mPortId; + quint32 mPortGroupId; + QString mUserAlias; // user defined + + QList mLastSyncStreamList; + QList mStreams; // sorted by stream's ordinal value + + uint newStreamId(); + void updateStreamOrdinalsFromIndex(); + void reorderStreamsByOrdinals(); + +public: + enum AdminStatus { AdminDisable, AdminEnable }; + enum ControlMode { ControlShared, ControlExclusive }; + + // FIXME(HIGH): default args is a hack for QList operations on Port + Port(quint32 id = 0xFFFFFFFF, quint32 pgId = 0xFFFFFFFF); + ~Port(); + + quint32 portGroupId() const { return mPortGroupId; } + const QString& userAlias() const { return mUserAlias; } + + quint32 id() const + { return d.port_id().id(); } + const QString name() const + { return QString().fromStdString(d.name()); } + const QString description() const + { return QString().fromStdString(d.description()); } + AdminStatus adminStatus() + { return (d.is_enabled()?AdminEnable:AdminDisable); } + ControlMode controlMode() + { return (d.is_exclusive_control()?ControlExclusive:ControlShared); } + + //void setAdminEnable(AdminStatus status) { mAdminStatus = status; } + void setAlias(QString &alias) { mUserAlias = alias; } + //void setExclusive(bool flag); + + int numStreams() { return mStreams.size(); } + Stream* streamByIndex(int index) + { + Q_ASSERT(index < mStreams.size()); + return mStreams[index]; + } + OstProto::LinkState linkState() + { return stats.state().link_state(); } + + OstProto::PortStats getStats() { return stats; } + + // FIXME(MED): naming inconsistency - PortConfig/Stream; also retVal + void updatePortConfig(OstProto::Port *port); + + //! Used by StreamModel + //@{ + bool newStreamAt(int index); + bool deleteStreamAt(int index); + //@} + + //! Used by MyService::Stub to update from config received from server + //@{ + bool insertStream(uint streamId); + bool updateStream(uint streamId, OstProto::Stream *stream); + //@} + + void getDeletedStreamsSinceLastSync(OstProto::StreamIdList &streamIdList); + void getNewStreamsSinceLastSync(OstProto::StreamIdList &streamIdList); + void getModifiedStreamsSinceLastSync( + OstProto::StreamConfigList &streamConfigList); + + + void when_syncComplete(); + + void updateStats(OstProto::PortStats *portStats); + +signals: + void portDataChanged(int portGroupId, int portId); + +}; + +#endif diff --git a/client/portgroup.cpp b/client/portgroup.cpp index e26d2a1..4ec94c3 100644 --- a/client/portgroup.cpp +++ b/client/portgroup.cpp @@ -1,718 +1,718 @@ -#include -#include - -#include "portgroup.h" - - -quint32 PortGroup::mPortGroupAllocId = 0; - -PortGroup::PortGroup(QHostAddress ip, quint16 port) -{ - // Allocate an id for self - mPortGroupId = PortGroup::mPortGroupAllocId++; - - rpcChannel = new PbRpcChannel(ip, port); - - /*! - \todo (HIGH) RPC Controller should be allocated and deleted for each RPC invocation - as implemented currently, if a RPC is invoked before the previous completes, - rpc controller is overwritten due to the Reset() call - maybe we need to pass the - pointer to the controller to the callback function also? - */ - rpcController = new PbRpcController; - rpcControllerStats = new PbRpcController; - isGetStatsPending_ = false; - serviceStub = new OstProto::OstService::Stub(rpcChannel, - OstProto::OstService::STUB_OWNS_CHANNEL); - - // FIXME(LOW):Can't for my life figure out why this ain't working! - //QMetaObject::connectSlotsByName(this); - connect(rpcChannel, SIGNAL(stateChanged(QAbstractSocket::SocketState)), - this, SLOT(on_rpcChannel_stateChanged())); - connect(rpcChannel, SIGNAL(connected()), - this, SLOT(on_rpcChannel_connected())); - connect(rpcChannel, SIGNAL(disconnected()), - this, SLOT(on_rpcChannel_disconnected())); - connect(rpcChannel, SIGNAL(error(QAbstractSocket::SocketError)), - this, SLOT(on_rpcChannel_error(QAbstractSocket::SocketError))); -} - -PortGroup::~PortGroup() -{ - qDebug("PortGroup Destructor"); - // Disconnect and free rpc channel etc. - PortGroup::disconnectFromHost(); - delete serviceStub; -} - - -// ------------------------------------------------ -// Slots -// ------------------------------------------------ -void PortGroup::on_rpcChannel_stateChanged() -{ - qDebug("state changed"); - emit portGroupDataChanged(mPortGroupId); -} - -void PortGroup::on_rpcChannel_connected() -{ - OstProto::Void void_; - OstProto::PortIdList *portIdList; - - qDebug("connected\n"); - emit portGroupDataChanged(mPortGroupId); - - qDebug("requesting portlist ..."); - portIdList = new OstProto::PortIdList(); - rpcController->Reset(); - serviceStub->getPortIdList(rpcController, &void_, portIdList, - NewCallback(this, &PortGroup::processPortIdList, portIdList)); -} - -void PortGroup::on_rpcChannel_disconnected() -{ - qDebug("disconnected\n"); - emit portListAboutToBeChanged(mPortGroupId); - - while (!mPorts.isEmpty()) - delete mPorts.takeFirst(); - - emit portListChanged(mPortGroupId); - emit portGroupDataChanged(mPortGroupId); -} - -void PortGroup::on_rpcChannel_error(QAbstractSocket::SocketError socketError) -{ - qDebug("error\n"); - emit portGroupDataChanged(mPortGroupId); -} - -void PortGroup::when_configApply(int portIndex, uint *cookie) -{ - uint *op; - OstProto::Ack *ack; - - Q_ASSERT(portIndex < mPorts.size()); - - if (state() != QAbstractSocket::ConnectedState) - { - if (cookie != NULL) - delete cookie; - return; - } - - if (cookie == NULL) - { - // cookie[0]: op [0 - delete, 1 - add, 2 - modify, 3 - Done!] - // cookie[1]: *ack - cookie = new uint[2]; - ack = new OstProto::Ack; - - cookie[0] = (uint) 0; - cookie[1] = (uint) ack; - } - else - { - ack = (OstProto::Ack*) cookie[1]; - } - - Q_ASSERT(cookie != NULL); - op = &cookie[0]; - - switch (*op) - { - case 0: - { - OstProto::StreamIdList streamIdList; - - qDebug("applying 'deleted streams' ..."); - - streamIdList.mutable_port_id()->set_id(mPorts[portIndex]->id()); - mPorts[portIndex]->getDeletedStreamsSinceLastSync(streamIdList); - - (*op)++; - rpcController->Reset(); - serviceStub->deleteStream(rpcController, &streamIdList, ack, - ::google::protobuf::NewCallback(this, &PortGroup::when_configApply, portIndex, cookie)); - break; - } - - case 1: - { - OstProto::StreamIdList streamIdList; - - qDebug("applying 'new streams' ..."); - - streamIdList.mutable_port_id()->set_id(mPorts[portIndex]->id()); - mPorts[portIndex]->getNewStreamsSinceLastSync(streamIdList); - - (*op)++; - rpcController->Reset(); - serviceStub->addStream(rpcController, &streamIdList, ack, - ::google::protobuf::NewCallback(this, &PortGroup::when_configApply, portIndex, cookie)); - break; - } - - case 2: - { - OstProto::StreamConfigList streamConfigList; - - qDebug("applying 'modified streams' ..."); - - streamConfigList.mutable_port_id()->set_id(mPorts[portIndex]->id()); - mPorts[portIndex]->getModifiedStreamsSinceLastSync(streamConfigList); - - (*op)++; - rpcController->Reset(); - serviceStub->modifyStream(rpcController, &streamConfigList, ack, - ::google::protobuf::NewCallback(this, &PortGroup::when_configApply, portIndex, cookie)); - break; - } - - case 3: - qDebug("apply completed"); - mPorts[portIndex]->when_syncComplete(); - delete cookie; - break; - - default: - qDebug("%s: Unknown Op!!!", __FUNCTION__); - break; - } -} - -void PortGroup::processPortIdList(OstProto::PortIdList *portIdList) -{ - qDebug("got a portlist ..."); - - if (rpcController->Failed()) - { - qDebug("%s: rpc failed", __FUNCTION__); - goto _error_exit; - } - - emit portListAboutToBeChanged(mPortGroupId); - - for(int i = 0; i < portIdList->port_id_size(); i++) - { - Port *p; - - p = new Port(portIdList->port_id(i).id(), mPortGroupId); - connect(p, SIGNAL(portDataChanged(int, int)), - this, SIGNAL(portGroupDataChanged(int, int))); - qDebug("before port append\n"); - mPorts.append(p); - } - - emit portListChanged(mPortGroupId); - - this->portIdList.CopyFrom(*portIdList); - - // Request PortConfigList - { - OstProto::PortConfigList *portConfigList; - - qDebug("requesting port config list ..."); - portConfigList = new OstProto::PortConfigList(); - rpcController->Reset(); - serviceStub->getPortConfig(rpcController, - portIdList, portConfigList, NewCallback(this, - &PortGroup::processPortConfigList, portConfigList)); - } - - goto _exit; - -_error_exit: -_exit: - delete portIdList; -} - -void PortGroup::processPortConfigList(OstProto::PortConfigList *portConfigList) -{ - qDebug("In %s", __FUNCTION__); - - if (rpcController->Failed()) - { - qDebug("%s: rpc failed", __FUNCTION__); - goto _error_exit; - } - - emit portListAboutToBeChanged(mPortGroupId); - - for(int i = 0; i < portConfigList->port_size(); i++) - { - uint id; - - id = portConfigList->port(i).port_id().id(); - // FIXME: don't mix port id & index into mPorts[] - mPorts[id]->updatePortConfig(portConfigList->mutable_port(i)); - } - - emit portListChanged(mPortGroupId); - - // FIXME: check if we need new signals since we are not changing the - // number of ports, just the port data - - if (numPorts() > 0) - getStreamIdList(); - -_error_exit: - delete portConfigList; -} - -void PortGroup::getStreamIdList(int portIndex, - OstProto::StreamIdList *streamIdList) -{ - ::OstProto::PortId portId; - - qDebug("In %s", __FUNCTION__); - - if (streamIdList == NULL) - { - // First invocation (uses default params) - - // request StreamIdList for first port - - Q_ASSERT(portIndex == 0); - Q_ASSERT(numPorts() > 0); - streamIdList = new ::OstProto::StreamIdList(); - - goto _request; - } - - qDebug("got a streamIdlist ..."); - - if (rpcController->Failed()) - { - qDebug("%s: rpc failed", __FUNCTION__); - goto _next_port; // FIXME(MED): Partial RPC - } - - Q_ASSERT(portIndex < numPorts()); - - if (streamIdList->port_id().id() != mPorts[portIndex]->id()) - { - qDebug("%s: Invalid portId %d (expected %d) received for portIndex %d", - __FUNCTION__, streamIdList->port_id().id(), mPorts[portIndex]->id(), - portIndex); - goto _next_port; // FIXME(MED): Partial RPC - } - - // FIXME(MED): need to mPorts.clear()??? - for(int i = 0; i < streamIdList->stream_id_size(); i++) - { - uint streamId; - - streamId = streamIdList->stream_id(i).id(); - mPorts[portIndex]->insertStream(streamId); - } - -_next_port: - // FIXME(HI): ideally we shd use signals/slots but this means - // we will have to use Port* instead of Port with QList<> - - // need to find a way for this - mPorts[portIndex]->when_syncComplete(); - portIndex++; - if (portIndex >= numPorts()) - { - // We're done for all ports !!! - - // FIXME(HI): some way to reset streammodel - - delete streamIdList; - - if (numPorts() > 0) - getStreamConfigList(); - - goto _exit; - } - -_request: - portId.set_id(mPorts[portIndex]->id()); - streamIdList->Clear(); - - rpcController->Reset(); - serviceStub->getStreamIdList(rpcController, &portId, streamIdList, - NewCallback(this, &PortGroup::getStreamIdList, - portIndex, streamIdList)); - - goto _exit; - - - -_exit: - return; -} - -void PortGroup::getStreamConfigList(int portIndex, - OstProto::StreamConfigList *streamConfigList) -{ - OstProto::StreamIdList streamIdList; - - qDebug("In %s", __PRETTY_FUNCTION__); - - if (streamConfigList == NULL) - { - // First invocation using default params - // - request for first port - - Q_ASSERT(portIndex == 0); - Q_ASSERT(numPorts() > 0); - - streamConfigList = new OstProto::StreamConfigList; - - goto _request; - } - - qDebug("got a streamconfiglist"); - - if (rpcController->Failed()) - { - qDebug("%s: rpc failed", __FUNCTION__); - goto _next_port; - } - - Q_ASSERT(portIndex < numPorts()); - - if (streamConfigList->port_id().id() != mPorts[portIndex]->id()) - { - qDebug("%s: Invalid portId %d (expected %d) received for portIndex %d", - __FUNCTION__, streamConfigList->port_id().id(), - mPorts[portIndex]->id(), portIndex); - goto _next_port; // FIXME(MED): Partial RPC - } - - // FIXME(MED): need to mStreams.clear()??? - for(int i = 0; i < streamConfigList->stream_size(); i++) - { - uint streamId; - - streamId = streamConfigList->stream(i).stream_id().id(); - mPorts[portIndex]->updateStream(streamId, - streamConfigList->mutable_stream(i)); - } - -_next_port: - portIndex++; - - if (portIndex >= numPorts()) - { - // We're done for all ports !!! - - // FIXME(HI): some way to reset streammodel - - delete streamConfigList; - goto _exit; - } - -_request: - qDebug("requesting stream config list ..."); - - streamIdList.Clear(); - streamIdList.mutable_port_id()->set_id(mPorts[portIndex]->id()); - for (int j = 0; j < mPorts[portIndex]->numStreams(); j++) - { - OstProto::StreamId *s; - - s = streamIdList.add_stream_id(); - s->set_id(mPorts[portIndex]->streamByIndex(j)->id()); - } - streamConfigList->Clear(); - - rpcController->Reset(); - serviceStub->getStreamConfig(rpcController, - &streamIdList, streamConfigList, NewCallback(this, - &PortGroup::getStreamConfigList, portIndex, streamConfigList)); - -_exit: - return; -} - -void PortGroup::processModifyStreamAck(OstProto::Ack *ack) -{ - qDebug("In %s", __FUNCTION__); - - qDebug("Modify Successful!!"); - - // TODO(HI): Apply Button should now be disabled???!!!!??? -} - -void PortGroup::startTx(QList *portList) -{ - OstProto::PortIdList portIdList; - OstProto::Ack *ack; - - qDebug("In %s", __FUNCTION__); - - if (state() != QAbstractSocket::ConnectedState) - return; - - ack = new OstProto::Ack; - if (portList == NULL) - goto _exit; - else - { - for (int i = 0; i < portList->size(); i++) - { - OstProto::PortId *portId; - portId = portIdList.add_port_id(); - portId->set_id(portList->at(i)); - } - } - - serviceStub->startTx(rpcController, &portIdList, ack, - NewCallback(this, &PortGroup::processStartTxAck, ack)); -_exit: - return; -} - -void PortGroup::stopTx(QList *portList) -{ - OstProto::PortIdList portIdList; - OstProto::Ack *ack; - - qDebug("In %s", __FUNCTION__); - - if (state() != QAbstractSocket::ConnectedState) - goto _exit; - - if ((portList == NULL) || (portList->size() == 0)) - goto _exit; - - ack = new OstProto::Ack; - - for (int i = 0; i < portList->size(); i++) - { - OstProto::PortId *portId; - portId = portIdList.add_port_id(); - portId->set_id(portList->at(i)); - } - - rpcController->Reset(); - serviceStub->stopTx(rpcController, &portIdList, ack, - NewCallback(this, &PortGroup::processStopTxAck, ack)); -_exit: - return; -} - -void PortGroup::startCapture(QList *portList) -{ - OstProto::PortIdList portIdList; - OstProto::Ack *ack; - - qDebug("In %s", __FUNCTION__); - - if (state() != QAbstractSocket::ConnectedState) - return; - - if ((portList == NULL) || (portList->size() == 0)) - goto _exit; - - ack = new OstProto::Ack; - - for (int i = 0; i < portList->size(); i++) - { - OstProto::PortId *portId; - portId = portIdList.add_port_id(); - portId->set_id(portList->at(i)); - } - - rpcController->Reset(); - serviceStub->startCapture(rpcController, &portIdList, ack, - NewCallback(this, &PortGroup::processStartCaptureAck, ack)); -_exit: - return; -} - -void PortGroup::stopCapture(QList *portList) -{ - OstProto::PortIdList portIdList; - OstProto::Ack *ack; - - qDebug("In %s", __FUNCTION__); - - if (state() != QAbstractSocket::ConnectedState) - return; - - if ((portList == NULL) || (portList->size() == 0)) - goto _exit; - - ack = new OstProto::Ack; - for (int i = 0; i < portList->size(); i++) - { - OstProto::PortId *portId; - portId = portIdList.add_port_id(); - portId->set_id(portList->at(i)); - } - - rpcController->Reset(); - serviceStub->stopCapture(rpcController, &portIdList, ack, - NewCallback(this, &PortGroup::processStopCaptureAck, ack)); -_exit: - return; -} - -void PortGroup::viewCapture(QList *portList) -{ - static QTemporaryFile *capFile = NULL; - - qDebug("In %s", __FUNCTION__); - - if (state() != QAbstractSocket::ConnectedState) - goto _exit; - - if ((portList == NULL) || (portList->size() != 1)) - goto _exit; - - if (capFile) - delete capFile; - - /*! \todo (MED) unable to reuse the same file 'coz capFile->resize(0) is - not working - it fails everytime */ - capFile = new QTemporaryFile(); - capFile->open(); - qDebug("Temp CapFile = %s", capFile->fileName().toAscii().constData()); - - for (int i = 0; i < portList->size(); i++) - { - OstProto::PortId portId; - OstProto::CaptureBuffer *buf; - - portId.set_id(portList->at(i)); - - buf = new OstProto::CaptureBuffer; - rpcController->Reset(); - rpcController->setBinaryBlob(capFile); - serviceStub->getCaptureBuffer(rpcController, &portId, buf, - NewCallback(this, &PortGroup::processViewCaptureAck, buf, (QFile*) capFile)); - } -_exit: - return; -} - -void PortGroup::processStartTxAck(OstProto::Ack *ack) -{ - qDebug("In %s", __FUNCTION__); - - delete ack; -} - -void PortGroup::processStopTxAck(OstProto::Ack *ack) -{ - qDebug("In %s", __FUNCTION__); - - delete ack; -} - -void PortGroup::processStartCaptureAck(OstProto::Ack *ack) -{ - qDebug("In %s", __FUNCTION__); - - delete ack; -} - -void PortGroup::processStopCaptureAck(OstProto::Ack *ack) -{ - qDebug("In %s", __FUNCTION__); - - delete ack; -} - -void PortGroup::processViewCaptureAck(OstProto::CaptureBuffer *buf, QFile *capFile) -{ - qDebug("In %s", __FUNCTION__); - - capFile->flush(); - capFile->close(); - - if (!QProcess::startDetached("C:/Program Files/Wireshark/wireshark.exe", - QStringList() << capFile->fileName())) - qDebug("Failed starting Wireshark"); - - delete buf; -} - -void PortGroup::getPortStats() -{ - OstProto::PortStatsList *portStatsList; - - //qDebug("In %s", __FUNCTION__); - - if (state() != QAbstractSocket::ConnectedState) - return; - - if (isGetStatsPending_) - return; - - portStatsList = new OstProto::PortStatsList; - rpcControllerStats->Reset(); - isGetStatsPending_ = true; - serviceStub->getStats(rpcControllerStats, &portIdList, portStatsList, - NewCallback(this, &PortGroup::processPortStatsList, portStatsList)); -} - -void PortGroup::processPortStatsList(OstProto::PortStatsList *portStatsList) -{ - //qDebug("In %s", __FUNCTION__); - - if (rpcControllerStats->Failed()) - { - qDebug("%s: rpc failed", __FUNCTION__); - goto _error_exit; - } - - for(int i = 0; i < portStatsList->port_stats_size(); i++) - { - uint id; - - id = portStatsList->port_stats(i).port_id().id(); - // FIXME: don't mix port id & index into mPorts[] - mPorts[id]->updateStats(portStatsList->mutable_port_stats(i)); - } - - emit statsChanged(mPortGroupId); - -_error_exit: - delete portStatsList; - isGetStatsPending_ = false; -} - -void PortGroup::clearPortStats(QList *portList) -{ - OstProto::PortIdList portIdList; - OstProto::Ack *ack; - - qDebug("In %s", __FUNCTION__); - - if (state() != QAbstractSocket::ConnectedState) - return; - - ack = new OstProto::Ack; - if (portList == NULL) - portIdList.CopyFrom(this->portIdList); - else - { - for (int i = 0; i < portList->size(); i++) - { - OstProto::PortId *portId; - - portId = portIdList.add_port_id(); - portId->set_id(portList->at(i)); - } - } - - rpcController->Reset(); - serviceStub->clearStats(rpcController, &portIdList, ack, - NewCallback(this, &PortGroup::processClearStatsAck, ack)); -} - -void PortGroup::processClearStatsAck(OstProto::Ack *ack) -{ - qDebug("In %s", __FUNCTION__); - - // Refresh stats immediately after a stats clear/reset - getPortStats(); - - delete ack; -} - +#include +#include + +#include "portgroup.h" + + +quint32 PortGroup::mPortGroupAllocId = 0; + +PortGroup::PortGroup(QHostAddress ip, quint16 port) +{ + // Allocate an id for self + mPortGroupId = PortGroup::mPortGroupAllocId++; + + rpcChannel = new PbRpcChannel(ip, port); + + /*! + \todo (HIGH) RPC Controller should be allocated and deleted for each RPC invocation + as implemented currently, if a RPC is invoked before the previous completes, + rpc controller is overwritten due to the Reset() call - maybe we need to pass the + pointer to the controller to the callback function also? + */ + rpcController = new PbRpcController; + rpcControllerStats = new PbRpcController; + isGetStatsPending_ = false; + serviceStub = new OstProto::OstService::Stub(rpcChannel, + OstProto::OstService::STUB_OWNS_CHANNEL); + + // FIXME(LOW):Can't for my life figure out why this ain't working! + //QMetaObject::connectSlotsByName(this); + connect(rpcChannel, SIGNAL(stateChanged(QAbstractSocket::SocketState)), + this, SLOT(on_rpcChannel_stateChanged())); + connect(rpcChannel, SIGNAL(connected()), + this, SLOT(on_rpcChannel_connected())); + connect(rpcChannel, SIGNAL(disconnected()), + this, SLOT(on_rpcChannel_disconnected())); + connect(rpcChannel, SIGNAL(error(QAbstractSocket::SocketError)), + this, SLOT(on_rpcChannel_error(QAbstractSocket::SocketError))); +} + +PortGroup::~PortGroup() +{ + qDebug("PortGroup Destructor"); + // Disconnect and free rpc channel etc. + PortGroup::disconnectFromHost(); + delete serviceStub; +} + + +// ------------------------------------------------ +// Slots +// ------------------------------------------------ +void PortGroup::on_rpcChannel_stateChanged() +{ + qDebug("state changed"); + emit portGroupDataChanged(mPortGroupId); +} + +void PortGroup::on_rpcChannel_connected() +{ + OstProto::Void void_; + OstProto::PortIdList *portIdList; + + qDebug("connected\n"); + emit portGroupDataChanged(mPortGroupId); + + qDebug("requesting portlist ..."); + portIdList = new OstProto::PortIdList(); + rpcController->Reset(); + serviceStub->getPortIdList(rpcController, &void_, portIdList, + NewCallback(this, &PortGroup::processPortIdList, portIdList)); +} + +void PortGroup::on_rpcChannel_disconnected() +{ + qDebug("disconnected\n"); + emit portListAboutToBeChanged(mPortGroupId); + + while (!mPorts.isEmpty()) + delete mPorts.takeFirst(); + + emit portListChanged(mPortGroupId); + emit portGroupDataChanged(mPortGroupId); +} + +void PortGroup::on_rpcChannel_error(QAbstractSocket::SocketError socketError) +{ + qDebug("error\n"); + emit portGroupDataChanged(mPortGroupId); +} + +void PortGroup::when_configApply(int portIndex, uint *cookie) +{ + uint *op; + OstProto::Ack *ack; + + Q_ASSERT(portIndex < mPorts.size()); + + if (state() != QAbstractSocket::ConnectedState) + { + if (cookie != NULL) + delete cookie; + return; + } + + if (cookie == NULL) + { + // cookie[0]: op [0 - delete, 1 - add, 2 - modify, 3 - Done!] + // cookie[1]: *ack + cookie = new uint[2]; + ack = new OstProto::Ack; + + cookie[0] = (uint) 0; + cookie[1] = (uint) ack; + } + else + { + ack = (OstProto::Ack*) cookie[1]; + } + + Q_ASSERT(cookie != NULL); + op = &cookie[0]; + + switch (*op) + { + case 0: + { + OstProto::StreamIdList streamIdList; + + qDebug("applying 'deleted streams' ..."); + + streamIdList.mutable_port_id()->set_id(mPorts[portIndex]->id()); + mPorts[portIndex]->getDeletedStreamsSinceLastSync(streamIdList); + + (*op)++; + rpcController->Reset(); + serviceStub->deleteStream(rpcController, &streamIdList, ack, + ::google::protobuf::NewCallback(this, &PortGroup::when_configApply, portIndex, cookie)); + break; + } + + case 1: + { + OstProto::StreamIdList streamIdList; + + qDebug("applying 'new streams' ..."); + + streamIdList.mutable_port_id()->set_id(mPorts[portIndex]->id()); + mPorts[portIndex]->getNewStreamsSinceLastSync(streamIdList); + + (*op)++; + rpcController->Reset(); + serviceStub->addStream(rpcController, &streamIdList, ack, + ::google::protobuf::NewCallback(this, &PortGroup::when_configApply, portIndex, cookie)); + break; + } + + case 2: + { + OstProto::StreamConfigList streamConfigList; + + qDebug("applying 'modified streams' ..."); + + streamConfigList.mutable_port_id()->set_id(mPorts[portIndex]->id()); + mPorts[portIndex]->getModifiedStreamsSinceLastSync(streamConfigList); + + (*op)++; + rpcController->Reset(); + serviceStub->modifyStream(rpcController, &streamConfigList, ack, + ::google::protobuf::NewCallback(this, &PortGroup::when_configApply, portIndex, cookie)); + break; + } + + case 3: + qDebug("apply completed"); + mPorts[portIndex]->when_syncComplete(); + delete cookie; + break; + + default: + qDebug("%s: Unknown Op!!!", __FUNCTION__); + break; + } +} + +void PortGroup::processPortIdList(OstProto::PortIdList *portIdList) +{ + qDebug("got a portlist ..."); + + if (rpcController->Failed()) + { + qDebug("%s: rpc failed", __FUNCTION__); + goto _error_exit; + } + + emit portListAboutToBeChanged(mPortGroupId); + + for(int i = 0; i < portIdList->port_id_size(); i++) + { + Port *p; + + p = new Port(portIdList->port_id(i).id(), mPortGroupId); + connect(p, SIGNAL(portDataChanged(int, int)), + this, SIGNAL(portGroupDataChanged(int, int))); + qDebug("before port append\n"); + mPorts.append(p); + } + + emit portListChanged(mPortGroupId); + + this->portIdList.CopyFrom(*portIdList); + + // Request PortConfigList + { + OstProto::PortConfigList *portConfigList; + + qDebug("requesting port config list ..."); + portConfigList = new OstProto::PortConfigList(); + rpcController->Reset(); + serviceStub->getPortConfig(rpcController, + portIdList, portConfigList, NewCallback(this, + &PortGroup::processPortConfigList, portConfigList)); + } + + goto _exit; + +_error_exit: +_exit: + delete portIdList; +} + +void PortGroup::processPortConfigList(OstProto::PortConfigList *portConfigList) +{ + qDebug("In %s", __FUNCTION__); + + if (rpcController->Failed()) + { + qDebug("%s: rpc failed", __FUNCTION__); + goto _error_exit; + } + + emit portListAboutToBeChanged(mPortGroupId); + + for(int i = 0; i < portConfigList->port_size(); i++) + { + uint id; + + id = portConfigList->port(i).port_id().id(); + // FIXME: don't mix port id & index into mPorts[] + mPorts[id]->updatePortConfig(portConfigList->mutable_port(i)); + } + + emit portListChanged(mPortGroupId); + + // FIXME: check if we need new signals since we are not changing the + // number of ports, just the port data + + if (numPorts() > 0) + getStreamIdList(); + +_error_exit: + delete portConfigList; +} + +void PortGroup::getStreamIdList(int portIndex, + OstProto::StreamIdList *streamIdList) +{ + ::OstProto::PortId portId; + + qDebug("In %s", __FUNCTION__); + + if (streamIdList == NULL) + { + // First invocation (uses default params) - + // request StreamIdList for first port + + Q_ASSERT(portIndex == 0); + Q_ASSERT(numPorts() > 0); + streamIdList = new ::OstProto::StreamIdList(); + + goto _request; + } + + qDebug("got a streamIdlist ..."); + + if (rpcController->Failed()) + { + qDebug("%s: rpc failed", __FUNCTION__); + goto _next_port; // FIXME(MED): Partial RPC + } + + Q_ASSERT(portIndex < numPorts()); + + if (streamIdList->port_id().id() != mPorts[portIndex]->id()) + { + qDebug("%s: Invalid portId %d (expected %d) received for portIndex %d", + __FUNCTION__, streamIdList->port_id().id(), mPorts[portIndex]->id(), + portIndex); + goto _next_port; // FIXME(MED): Partial RPC + } + + // FIXME(MED): need to mPorts.clear()??? + for(int i = 0; i < streamIdList->stream_id_size(); i++) + { + uint streamId; + + streamId = streamIdList->stream_id(i).id(); + mPorts[portIndex]->insertStream(streamId); + } + +_next_port: + // FIXME(HI): ideally we shd use signals/slots but this means + // we will have to use Port* instead of Port with QList<> - + // need to find a way for this + mPorts[portIndex]->when_syncComplete(); + portIndex++; + if (portIndex >= numPorts()) + { + // We're done for all ports !!! + + // FIXME(HI): some way to reset streammodel + + delete streamIdList; + + if (numPorts() > 0) + getStreamConfigList(); + + goto _exit; + } + +_request: + portId.set_id(mPorts[portIndex]->id()); + streamIdList->Clear(); + + rpcController->Reset(); + serviceStub->getStreamIdList(rpcController, &portId, streamIdList, + NewCallback(this, &PortGroup::getStreamIdList, + portIndex, streamIdList)); + + goto _exit; + + + +_exit: + return; +} + +void PortGroup::getStreamConfigList(int portIndex, + OstProto::StreamConfigList *streamConfigList) +{ + OstProto::StreamIdList streamIdList; + + qDebug("In %s", __PRETTY_FUNCTION__); + + if (streamConfigList == NULL) + { + // First invocation using default params + // - request for first port + + Q_ASSERT(portIndex == 0); + Q_ASSERT(numPorts() > 0); + + streamConfigList = new OstProto::StreamConfigList; + + goto _request; + } + + qDebug("got a streamconfiglist"); + + if (rpcController->Failed()) + { + qDebug("%s: rpc failed", __FUNCTION__); + goto _next_port; + } + + Q_ASSERT(portIndex < numPorts()); + + if (streamConfigList->port_id().id() != mPorts[portIndex]->id()) + { + qDebug("%s: Invalid portId %d (expected %d) received for portIndex %d", + __FUNCTION__, streamConfigList->port_id().id(), + mPorts[portIndex]->id(), portIndex); + goto _next_port; // FIXME(MED): Partial RPC + } + + // FIXME(MED): need to mStreams.clear()??? + for(int i = 0; i < streamConfigList->stream_size(); i++) + { + uint streamId; + + streamId = streamConfigList->stream(i).stream_id().id(); + mPorts[portIndex]->updateStream(streamId, + streamConfigList->mutable_stream(i)); + } + +_next_port: + portIndex++; + + if (portIndex >= numPorts()) + { + // We're done for all ports !!! + + // FIXME(HI): some way to reset streammodel + + delete streamConfigList; + goto _exit; + } + +_request: + qDebug("requesting stream config list ..."); + + streamIdList.Clear(); + streamIdList.mutable_port_id()->set_id(mPorts[portIndex]->id()); + for (int j = 0; j < mPorts[portIndex]->numStreams(); j++) + { + OstProto::StreamId *s; + + s = streamIdList.add_stream_id(); + s->set_id(mPorts[portIndex]->streamByIndex(j)->id()); + } + streamConfigList->Clear(); + + rpcController->Reset(); + serviceStub->getStreamConfig(rpcController, + &streamIdList, streamConfigList, NewCallback(this, + &PortGroup::getStreamConfigList, portIndex, streamConfigList)); + +_exit: + return; +} + +void PortGroup::processModifyStreamAck(OstProto::Ack *ack) +{ + qDebug("In %s", __FUNCTION__); + + qDebug("Modify Successful!!"); + + // TODO(HI): Apply Button should now be disabled???!!!!??? +} + +void PortGroup::startTx(QList *portList) +{ + OstProto::PortIdList portIdList; + OstProto::Ack *ack; + + qDebug("In %s", __FUNCTION__); + + if (state() != QAbstractSocket::ConnectedState) + return; + + ack = new OstProto::Ack; + if (portList == NULL) + goto _exit; + else + { + for (int i = 0; i < portList->size(); i++) + { + OstProto::PortId *portId; + portId = portIdList.add_port_id(); + portId->set_id(portList->at(i)); + } + } + + serviceStub->startTx(rpcController, &portIdList, ack, + NewCallback(this, &PortGroup::processStartTxAck, ack)); +_exit: + return; +} + +void PortGroup::stopTx(QList *portList) +{ + OstProto::PortIdList portIdList; + OstProto::Ack *ack; + + qDebug("In %s", __FUNCTION__); + + if (state() != QAbstractSocket::ConnectedState) + goto _exit; + + if ((portList == NULL) || (portList->size() == 0)) + goto _exit; + + ack = new OstProto::Ack; + + for (int i = 0; i < portList->size(); i++) + { + OstProto::PortId *portId; + portId = portIdList.add_port_id(); + portId->set_id(portList->at(i)); + } + + rpcController->Reset(); + serviceStub->stopTx(rpcController, &portIdList, ack, + NewCallback(this, &PortGroup::processStopTxAck, ack)); +_exit: + return; +} + +void PortGroup::startCapture(QList *portList) +{ + OstProto::PortIdList portIdList; + OstProto::Ack *ack; + + qDebug("In %s", __FUNCTION__); + + if (state() != QAbstractSocket::ConnectedState) + return; + + if ((portList == NULL) || (portList->size() == 0)) + goto _exit; + + ack = new OstProto::Ack; + + for (int i = 0; i < portList->size(); i++) + { + OstProto::PortId *portId; + portId = portIdList.add_port_id(); + portId->set_id(portList->at(i)); + } + + rpcController->Reset(); + serviceStub->startCapture(rpcController, &portIdList, ack, + NewCallback(this, &PortGroup::processStartCaptureAck, ack)); +_exit: + return; +} + +void PortGroup::stopCapture(QList *portList) +{ + OstProto::PortIdList portIdList; + OstProto::Ack *ack; + + qDebug("In %s", __FUNCTION__); + + if (state() != QAbstractSocket::ConnectedState) + return; + + if ((portList == NULL) || (portList->size() == 0)) + goto _exit; + + ack = new OstProto::Ack; + for (int i = 0; i < portList->size(); i++) + { + OstProto::PortId *portId; + portId = portIdList.add_port_id(); + portId->set_id(portList->at(i)); + } + + rpcController->Reset(); + serviceStub->stopCapture(rpcController, &portIdList, ack, + NewCallback(this, &PortGroup::processStopCaptureAck, ack)); +_exit: + return; +} + +void PortGroup::viewCapture(QList *portList) +{ + static QTemporaryFile *capFile = NULL; + + qDebug("In %s", __FUNCTION__); + + if (state() != QAbstractSocket::ConnectedState) + goto _exit; + + if ((portList == NULL) || (portList->size() != 1)) + goto _exit; + + if (capFile) + delete capFile; + + /*! \todo (MED) unable to reuse the same file 'coz capFile->resize(0) is + not working - it fails everytime */ + capFile = new QTemporaryFile(); + capFile->open(); + qDebug("Temp CapFile = %s", capFile->fileName().toAscii().constData()); + + for (int i = 0; i < portList->size(); i++) + { + OstProto::PortId portId; + OstProto::CaptureBuffer *buf; + + portId.set_id(portList->at(i)); + + buf = new OstProto::CaptureBuffer; + rpcController->Reset(); + rpcController->setBinaryBlob(capFile); + serviceStub->getCaptureBuffer(rpcController, &portId, buf, + NewCallback(this, &PortGroup::processViewCaptureAck, buf, (QFile*) capFile)); + } +_exit: + return; +} + +void PortGroup::processStartTxAck(OstProto::Ack *ack) +{ + qDebug("In %s", __FUNCTION__); + + delete ack; +} + +void PortGroup::processStopTxAck(OstProto::Ack *ack) +{ + qDebug("In %s", __FUNCTION__); + + delete ack; +} + +void PortGroup::processStartCaptureAck(OstProto::Ack *ack) +{ + qDebug("In %s", __FUNCTION__); + + delete ack; +} + +void PortGroup::processStopCaptureAck(OstProto::Ack *ack) +{ + qDebug("In %s", __FUNCTION__); + + delete ack; +} + +void PortGroup::processViewCaptureAck(OstProto::CaptureBuffer *buf, QFile *capFile) +{ + qDebug("In %s", __FUNCTION__); + + capFile->flush(); + capFile->close(); + + if (!QProcess::startDetached("C:/Program Files/Wireshark/wireshark.exe", + QStringList() << capFile->fileName())) + qDebug("Failed starting Wireshark"); + + delete buf; +} + +void PortGroup::getPortStats() +{ + OstProto::PortStatsList *portStatsList; + + //qDebug("In %s", __FUNCTION__); + + if (state() != QAbstractSocket::ConnectedState) + return; + + if (isGetStatsPending_) + return; + + portStatsList = new OstProto::PortStatsList; + rpcControllerStats->Reset(); + isGetStatsPending_ = true; + serviceStub->getStats(rpcControllerStats, &portIdList, portStatsList, + NewCallback(this, &PortGroup::processPortStatsList, portStatsList)); +} + +void PortGroup::processPortStatsList(OstProto::PortStatsList *portStatsList) +{ + //qDebug("In %s", __FUNCTION__); + + if (rpcControllerStats->Failed()) + { + qDebug("%s: rpc failed", __FUNCTION__); + goto _error_exit; + } + + for(int i = 0; i < portStatsList->port_stats_size(); i++) + { + uint id; + + id = portStatsList->port_stats(i).port_id().id(); + // FIXME: don't mix port id & index into mPorts[] + mPorts[id]->updateStats(portStatsList->mutable_port_stats(i)); + } + + emit statsChanged(mPortGroupId); + +_error_exit: + delete portStatsList; + isGetStatsPending_ = false; +} + +void PortGroup::clearPortStats(QList *portList) +{ + OstProto::PortIdList portIdList; + OstProto::Ack *ack; + + qDebug("In %s", __FUNCTION__); + + if (state() != QAbstractSocket::ConnectedState) + return; + + ack = new OstProto::Ack; + if (portList == NULL) + portIdList.CopyFrom(this->portIdList); + else + { + for (int i = 0; i < portList->size(); i++) + { + OstProto::PortId *portId; + + portId = portIdList.add_port_id(); + portId->set_id(portList->at(i)); + } + } + + rpcController->Reset(); + serviceStub->clearStats(rpcController, &portIdList, ack, + NewCallback(this, &PortGroup::processClearStatsAck, ack)); +} + +void PortGroup::processClearStatsAck(OstProto::Ack *ack) +{ + qDebug("In %s", __FUNCTION__); + + // Refresh stats immediately after a stats clear/reset + getPortStats(); + + delete ack; +} + diff --git a/client/portgroup.h b/client/portgroup.h index a503910..4566b46 100644 --- a/client/portgroup.h +++ b/client/portgroup.h @@ -1,119 +1,119 @@ -#ifndef _PORT_GROUP_H -#define _PORT_GROUP_H - -#include "port.h" -#include -#include - -#include "../common/protocol.pb.h" -#include "pbrpcchannel.h" - -/* TODO -HIGH -MED -LOW -- Allow hostnames in addition to IP Address as "server address" -*/ - -#define DEFAULT_SERVER_PORT 7878 - -class QFile; - -class PortGroup : public QObject { - Q_OBJECT - -private: - quint32 mPortGroupId; - static quint32 mPortGroupAllocId; - QString mUserAlias; // user defined -#if 0 // PB - QTcpSocket *mpSocket; - QHostAddress mServerAddress; - quint16 mServerPort; -#endif - PbRpcChannel *rpcChannel; - PbRpcController *rpcController; - PbRpcController *rpcControllerStats; - bool isGetStatsPending_; - ::OstProto::OstService::Stub *serviceStub; - - ::OstProto::PortIdList portIdList; -public: // FIXME(HIGH): member access - QList mPorts; - -public: - PortGroup(QHostAddress ip = QHostAddress::LocalHost, - quint16 port = DEFAULT_SERVER_PORT); - ~PortGroup(); - - void connectToHost() { rpcChannel->establish(); } - void connectToHost(QHostAddress ip, quint16 port) - { rpcChannel->establish(ip, port); } - void disconnectFromHost() { rpcChannel->tearDown(); } - - int numPorts() const { return mPorts.size(); } - quint32 id() const { return mPortGroupId; } - - const QString& userAlias() const { return mUserAlias; } - void setUserAlias(QString alias) { mUserAlias = alias; }; - - const QHostAddress& serverAddress() const - { return rpcChannel->serverAddress(); } - quint16 serverPort() const - { return rpcChannel->serverPort(); } - QAbstractSocket::SocketState state() const - { return rpcChannel->state(); } - - void processPortIdList(OstProto::PortIdList *portIdList); - void processPortConfigList(OstProto::PortConfigList *portConfigList); - - void getStreamIdList(int portIndex = 0, - OstProto::StreamIdList *streamIdList = NULL); - void getStreamConfigList(int portIndex = 0, - OstProto::StreamConfigList *streamConfigList = NULL); - - void processModifyStreamAck(OstProto::Ack *ack); - - void startTx(QList *portList = NULL); - void processStartTxAck(OstProto::Ack *ack); - void stopTx(QList *portList = NULL); - void processStopTxAck(OstProto::Ack *ack); - - void startCapture(QList *portList = NULL); - void processStartCaptureAck(OstProto::Ack *ack); - void stopCapture(QList *portList = NULL); - void processStopCaptureAck(OstProto::Ack *ack); - void viewCapture(QList *portList = NULL); - void processViewCaptureAck(OstProto::CaptureBuffer *buf, QFile *capFile); - - void getPortStats(); - void processPortStatsList(OstProto::PortStatsList *portStatsList); - void clearPortStats(QList *portList = NULL); - void processClearStatsAck(OstProto::Ack *ack); - -signals: - void portGroupDataChanged(int portGroupId, int portId = 0xFFFF); - void portListAboutToBeChanged(quint32 portGroupId); - void portListChanged(quint32 portGroupId); - void statsChanged(quint32 portGroupId); - -private slots: - void on_rpcChannel_stateChanged(); - void on_rpcChannel_connected(); - void on_rpcChannel_disconnected(); - void on_rpcChannel_error(QAbstractSocket::SocketError socketError); - -public slots: - void when_configApply(int portIndex, uint *cookie = NULL); -#if 0 // PB - void on_rpcChannel_when_dataAvail(); -#endif - -private: -#if 0 // PB - void ProcessCapabilityInfo(const char *msg, qint32 size); - void ProcessMsg(const char *msg, quint32 size); -#endif -}; - -#endif +#ifndef _PORT_GROUP_H +#define _PORT_GROUP_H + +#include "port.h" +#include +#include + +#include "../common/protocol.pb.h" +#include "pbrpcchannel.h" + +/* TODO +HIGH +MED +LOW +- Allow hostnames in addition to IP Address as "server address" +*/ + +#define DEFAULT_SERVER_PORT 7878 + +class QFile; + +class PortGroup : public QObject { + Q_OBJECT + +private: + quint32 mPortGroupId; + static quint32 mPortGroupAllocId; + QString mUserAlias; // user defined +#if 0 // PB + QTcpSocket *mpSocket; + QHostAddress mServerAddress; + quint16 mServerPort; +#endif + PbRpcChannel *rpcChannel; + PbRpcController *rpcController; + PbRpcController *rpcControllerStats; + bool isGetStatsPending_; + ::OstProto::OstService::Stub *serviceStub; + + ::OstProto::PortIdList portIdList; +public: // FIXME(HIGH): member access + QList mPorts; + +public: + PortGroup(QHostAddress ip = QHostAddress::LocalHost, + quint16 port = DEFAULT_SERVER_PORT); + ~PortGroup(); + + void connectToHost() { rpcChannel->establish(); } + void connectToHost(QHostAddress ip, quint16 port) + { rpcChannel->establish(ip, port); } + void disconnectFromHost() { rpcChannel->tearDown(); } + + int numPorts() const { return mPorts.size(); } + quint32 id() const { return mPortGroupId; } + + const QString& userAlias() const { return mUserAlias; } + void setUserAlias(QString alias) { mUserAlias = alias; }; + + const QHostAddress& serverAddress() const + { return rpcChannel->serverAddress(); } + quint16 serverPort() const + { return rpcChannel->serverPort(); } + QAbstractSocket::SocketState state() const + { return rpcChannel->state(); } + + void processPortIdList(OstProto::PortIdList *portIdList); + void processPortConfigList(OstProto::PortConfigList *portConfigList); + + void getStreamIdList(int portIndex = 0, + OstProto::StreamIdList *streamIdList = NULL); + void getStreamConfigList(int portIndex = 0, + OstProto::StreamConfigList *streamConfigList = NULL); + + void processModifyStreamAck(OstProto::Ack *ack); + + void startTx(QList *portList = NULL); + void processStartTxAck(OstProto::Ack *ack); + void stopTx(QList *portList = NULL); + void processStopTxAck(OstProto::Ack *ack); + + void startCapture(QList *portList = NULL); + void processStartCaptureAck(OstProto::Ack *ack); + void stopCapture(QList *portList = NULL); + void processStopCaptureAck(OstProto::Ack *ack); + void viewCapture(QList *portList = NULL); + void processViewCaptureAck(OstProto::CaptureBuffer *buf, QFile *capFile); + + void getPortStats(); + void processPortStatsList(OstProto::PortStatsList *portStatsList); + void clearPortStats(QList *portList = NULL); + void processClearStatsAck(OstProto::Ack *ack); + +signals: + void portGroupDataChanged(int portGroupId, int portId = 0xFFFF); + void portListAboutToBeChanged(quint32 portGroupId); + void portListChanged(quint32 portGroupId); + void statsChanged(quint32 portGroupId); + +private slots: + void on_rpcChannel_stateChanged(); + void on_rpcChannel_connected(); + void on_rpcChannel_disconnected(); + void on_rpcChannel_error(QAbstractSocket::SocketError socketError); + +public slots: + void when_configApply(int portIndex, uint *cookie = NULL); +#if 0 // PB + void on_rpcChannel_when_dataAvail(); +#endif + +private: +#if 0 // PB + void ProcessCapabilityInfo(const char *msg, qint32 size); + void ProcessMsg(const char *msg, quint32 size); +#endif +}; + +#endif diff --git a/client/portgrouplist.cpp b/client/portgrouplist.cpp index 3e67d01..49aa539 100644 --- a/client/portgrouplist.cpp +++ b/client/portgrouplist.cpp @@ -1,98 +1,98 @@ -#include "portgrouplist.h" - -// TODO(LOW): Remove -#include - -PortGroupList::PortGroupList() - : mPortGroupListModel(this), - mStreamListModel(this), - mPortStatsModel(this, this) -{ - PortGroup *pg; - - // TODO(LOW): Remove - new ModelTest(getStreamModel()); - new ModelTest(getPortModel()); - new ModelTest(getPortStatsModel()); - - // Add the "Local" Port Group - pg = new PortGroup; - addPortGroup(*pg); -} - -bool PortGroupList::isPortGroup(const QModelIndex& index) -{ - return mPortGroupListModel.isPortGroup(index); -} - -bool PortGroupList::isPort(const QModelIndex& index) -{ - return mPortGroupListModel.isPort(index); -} - -PortGroup& PortGroupList::portGroup(const QModelIndex& index) -{ - Q_ASSERT(mPortGroupListModel.isPortGroup(index)); - - return *(mPortGroups[index.row()]); -} - -Port& PortGroupList::port(const QModelIndex& index) -{ - Q_ASSERT(mPortGroupListModel.isPort(index)); - return (*mPortGroups.at(index.parent().row())->mPorts[index.row()]); -} - -void PortGroupList::addPortGroup(PortGroup &portGroup) -{ - mPortGroupListModel.portGroupAboutToBeAppended(); - - connect(&portGroup, SIGNAL(portGroupDataChanged(int, int)), - &mPortGroupListModel, SLOT(when_portGroupDataChanged(int, int))); -#if 0 - connect(&portGroup, SIGNAL(portListAboutToBeChanged(quint32)), - &mPortGroupListModel, SLOT(triggerLayoutAboutToBeChanged())); - connect(&portGroup, SIGNAL(portListChanged(quint32)), - &mPortGroupListModel, SLOT(triggerLayoutChanged())); -#endif - connect(&portGroup, SIGNAL(portListChanged(quint32)), - &mPortGroupListModel, SLOT(when_portListChanged())); - - connect(&portGroup, SIGNAL(portListChanged(quint32)), - &mPortStatsModel, SLOT(when_portListChanged())); - - connect(&portGroup, SIGNAL(statsChanged(quint32)), - &mPortStatsModel, SLOT(when_portGroup_stats_update(quint32))); - - mPortGroups.append(&portGroup); - portGroup.connectToHost(); - - mPortGroupListModel.portGroupAppended(); - - mPortStatsModel.when_portListChanged(); -} - -void PortGroupList::removePortGroup(PortGroup &portGroup) -{ - mPortGroupListModel.portGroupAboutToBeRemoved(&portGroup); - - PortGroup* pg = mPortGroups.takeAt(mPortGroups.indexOf(&portGroup)); - qDebug("after takeAt()"); - mPortGroupListModel.portGroupRemoved(); - - delete pg; - - mPortStatsModel.when_portListChanged(); -} - -//.................... -// Private Methods -//.................... -int PortGroupList::indexOfPortGroup(quint32 portGroupId) -{ - for (int i = 0; i < mPortGroups.size(); i++) { - if (mPortGroups.value(i)->id() == portGroupId) - return i; - } - return -1; -} +#include "portgrouplist.h" + +// TODO(LOW): Remove +#include + +PortGroupList::PortGroupList() + : mPortGroupListModel(this), + mStreamListModel(this), + mPortStatsModel(this, this) +{ + PortGroup *pg; + + // TODO(LOW): Remove + new ModelTest(getStreamModel()); + new ModelTest(getPortModel()); + new ModelTest(getPortStatsModel()); + + // Add the "Local" Port Group + pg = new PortGroup; + addPortGroup(*pg); +} + +bool PortGroupList::isPortGroup(const QModelIndex& index) +{ + return mPortGroupListModel.isPortGroup(index); +} + +bool PortGroupList::isPort(const QModelIndex& index) +{ + return mPortGroupListModel.isPort(index); +} + +PortGroup& PortGroupList::portGroup(const QModelIndex& index) +{ + Q_ASSERT(mPortGroupListModel.isPortGroup(index)); + + return *(mPortGroups[index.row()]); +} + +Port& PortGroupList::port(const QModelIndex& index) +{ + Q_ASSERT(mPortGroupListModel.isPort(index)); + return (*mPortGroups.at(index.parent().row())->mPorts[index.row()]); +} + +void PortGroupList::addPortGroup(PortGroup &portGroup) +{ + mPortGroupListModel.portGroupAboutToBeAppended(); + + connect(&portGroup, SIGNAL(portGroupDataChanged(int, int)), + &mPortGroupListModel, SLOT(when_portGroupDataChanged(int, int))); +#if 0 + connect(&portGroup, SIGNAL(portListAboutToBeChanged(quint32)), + &mPortGroupListModel, SLOT(triggerLayoutAboutToBeChanged())); + connect(&portGroup, SIGNAL(portListChanged(quint32)), + &mPortGroupListModel, SLOT(triggerLayoutChanged())); +#endif + connect(&portGroup, SIGNAL(portListChanged(quint32)), + &mPortGroupListModel, SLOT(when_portListChanged())); + + connect(&portGroup, SIGNAL(portListChanged(quint32)), + &mPortStatsModel, SLOT(when_portListChanged())); + + connect(&portGroup, SIGNAL(statsChanged(quint32)), + &mPortStatsModel, SLOT(when_portGroup_stats_update(quint32))); + + mPortGroups.append(&portGroup); + portGroup.connectToHost(); + + mPortGroupListModel.portGroupAppended(); + + mPortStatsModel.when_portListChanged(); +} + +void PortGroupList::removePortGroup(PortGroup &portGroup) +{ + mPortGroupListModel.portGroupAboutToBeRemoved(&portGroup); + + PortGroup* pg = mPortGroups.takeAt(mPortGroups.indexOf(&portGroup)); + qDebug("after takeAt()"); + mPortGroupListModel.portGroupRemoved(); + + delete pg; + + mPortStatsModel.when_portListChanged(); +} + +//.................... +// Private Methods +//.................... +int PortGroupList::indexOfPortGroup(quint32 portGroupId) +{ + for (int i = 0; i < mPortGroups.size(); i++) { + if (mPortGroups.value(i)->id() == portGroupId) + return i; + } + return -1; +} diff --git a/client/portgrouplist.h b/client/portgrouplist.h index e5e398b..3dd8f5f 100644 --- a/client/portgrouplist.h +++ b/client/portgrouplist.h @@ -1,52 +1,52 @@ -#ifndef _PORT_GROUP_LIST_H -#define _PORT_GROUP_LIST_H - -#include "portgroup.h" -#include -#include -#include "portmodel.h" -#include "streammodel.h" -#include "portstatsmodel.h" - -class PortModel; -class StreamModel; - -class PortGroupList : public QObject { - - Q_OBJECT - - friend class PortModel; - friend class StreamModel; - friend class PortStatsModel; - - QList mPortGroups; - PortModel mPortGroupListModel; - StreamModel mStreamListModel; - PortStatsModel mPortStatsModel; - -// Methods -public: - PortGroupList(); - - - PortModel* getPortModel() { return &mPortGroupListModel; } - PortStatsModel* getPortStatsModel() { return &mPortStatsModel; } - StreamModel* getStreamModel() { return &mStreamListModel; } - - bool isPortGroup(const QModelIndex& index); - bool isPort(const QModelIndex& index); - PortGroup& portGroup(const QModelIndex& index); - Port& port(const QModelIndex& index); - - int numPortGroups() { return mPortGroups.size(); } - PortGroup& portGroupByIndex(int index) { return *(mPortGroups[index]); } - - void addPortGroup(PortGroup &portGroup); - void removePortGroup(PortGroup &portGroup); - -private: - int indexOfPortGroup(quint32 portGroupId); - -}; - -#endif +#ifndef _PORT_GROUP_LIST_H +#define _PORT_GROUP_LIST_H + +#include "portgroup.h" +#include +#include +#include "portmodel.h" +#include "streammodel.h" +#include "portstatsmodel.h" + +class PortModel; +class StreamModel; + +class PortGroupList : public QObject { + + Q_OBJECT + + friend class PortModel; + friend class StreamModel; + friend class PortStatsModel; + + QList mPortGroups; + PortModel mPortGroupListModel; + StreamModel mStreamListModel; + PortStatsModel mPortStatsModel; + +// Methods +public: + PortGroupList(); + + + PortModel* getPortModel() { return &mPortGroupListModel; } + PortStatsModel* getPortStatsModel() { return &mPortStatsModel; } + StreamModel* getStreamModel() { return &mStreamListModel; } + + bool isPortGroup(const QModelIndex& index); + bool isPort(const QModelIndex& index); + PortGroup& portGroup(const QModelIndex& index); + Port& port(const QModelIndex& index); + + int numPortGroups() { return mPortGroups.size(); } + PortGroup& portGroupByIndex(int index) { return *(mPortGroups[index]); } + + void addPortGroup(PortGroup &portGroup); + void removePortGroup(PortGroup &portGroup); + +private: + int indexOfPortGroup(quint32 portGroupId); + +}; + +#endif diff --git a/client/portmodel.cpp b/client/portmodel.cpp index ff5c482..6ab422e 100644 --- a/client/portmodel.cpp +++ b/client/portmodel.cpp @@ -1,311 +1,311 @@ -#include "portmodel.h" -#include "portgrouplist.h" -#include - -#if 0 -#define DBG0(x) qDebug(x) -#define DBG1(x, p1) qDebug(x, (p1)) -#else -#define DBG0(x) {} -#define DBG1(x, p1) {} -#endif - -PortModel::PortModel(PortGroupList *p, QObject *parent) - : QAbstractItemModel(parent) -{ - pgl = p; -} - -int PortModel::rowCount(const QModelIndex &parent) const -{ - // qDebug("RowCount Enter\n"); - if (!parent.isValid()) - { - // Top Level Item - //qDebug("RowCount (Top) Exit: %d\n", pgl->mPortGroups.size()); - return pgl->mPortGroups.size(); - } - // qDebug("RowCount non top %d, %d, %llx\n", - // parent.row(), parent.column(), parent.internalId()); - - quint16 pg = (parent.internalId() >> 16) & 0xFFFF; - quint16 p = parent.internalId() & 0xFFFF; - if (p == 0xFFFF) - { -#if 0 // wrong code? - int count = 0; - foreach(PortGroup *pg, pgl->mPortGroups) - { - count += pg->numPorts(); - } - //qDebug("RowCount (Mid) Exit: %d\n", count); - return count; -#endif - if (parent.column() == 0) - return pgl->mPortGroups.value(pgl->indexOfPortGroup(pg))->numPorts(); - else - return 0; - } - else - { - // Leaf Item - return 0; - } -} - -int PortModel::columnCount(const QModelIndex &parent ) const -{ - return 1; // FIXME: hardcoding -} - -Qt::ItemFlags PortModel::flags(const QModelIndex &index) const -{ - return QAbstractItemModel::flags(index); // FIXME: no need for this func -} -QVariant PortModel::data(const QModelIndex &index, int role) const -{ - - DBG0("Enter PortModel data\n"); - - // Check for a valid index - if (!index.isValid()) - return QVariant(); - - DBG1("PortModel::data(index).row = %d", index.row()); - DBG1("PortModel::data(index).column = %0d", index.column()); - DBG1("PortModel::data(index).internalId = %08llx", index.internalId()); - - QModelIndex parent = index.parent(); - - if (!parent.isValid()) - { - // Top Level Item - PortGroup - if ((role == Qt::DisplayRole)) - { - DBG0("Exit PortModel data 1\n"); - return QString("Port Group %1: %2 [%3:%4] (%5)"). - arg(pgl->mPortGroups.at(index.row())->id()). - arg(pgl->mPortGroups.at(index.row())->userAlias()). - arg(pgl->mPortGroups.at(index.row())->serverAddress().toString()). - arg(pgl->mPortGroups.at(index.row())->serverPort()). - arg(pgl->mPortGroups.value(index.row())->numPorts()); - } - else if ((role == Qt::DecorationRole)) - { - DBG0("Exit PortModel data 2\n"); - switch(pgl->mPortGroups.at(index.row())->state()) - { - case QAbstractSocket::UnconnectedState: - return QIcon(":/icons/bullet_red.png"); - - case QAbstractSocket::HostLookupState: - return QIcon(":/icons/bullet_yellow.png"); - - case QAbstractSocket::ConnectingState: - case QAbstractSocket::ClosingState: - return QIcon(":/icons/bullet_orange.png"); - - case QAbstractSocket::ConnectedState: - return QIcon(":/icons/bullet_green.png"); - - - case QAbstractSocket::BoundState: - case QAbstractSocket::ListeningState: - default: - return QIcon(":/icons/bullet_error.png"); - } - } - else - { - DBG0("Exit PortModel data 3\n"); - return QVariant(); - } - } - else - { - // Non Top Level - Port - if ((role == Qt::DisplayRole)) - { - DBG0("Exit PortModel data 4\n"); - if (pgl->mPortGroups.at(parent.row())->numPorts() == 0) - return QVariant(); - - return QString("Port %1: %2 [%3] (%4)"). - arg(pgl->mPortGroups.at( - parent.row())->mPorts[index.row()]->id()). - arg(pgl->mPortGroups.at( - parent.row())->mPorts[index.row()]->name()). - arg(QHostAddress("0.0.0.0").toString()). // FIXME(LOW) - arg(pgl->mPortGroups.at( - parent.row())->mPorts[index.row()]->description()); - } - else if ((role == Qt::DecorationRole)) - { - DBG0("Exit PortModel data 5\n"); - if (pgl->mPortGroups.at(parent.row())->numPorts() == 0) - return QVariant(); - switch(pgl->mPortGroups.at(parent.row())->mPorts[index.row()]->linkState()) - { - case OstProto::LinkStateUnknown: - return QIcon(":/icons/bullet_white.png"); - case OstProto::LinkStateDown: - return QIcon(":/icons/bullet_red.png"); - case OstProto::LinkStateUp: - return QIcon(":/icons/bullet_green.png"); - default: - qFatal("unexpected/unimplemented port oper state"); - } - } - else - { - DBG0("Exit PortModel data 6\n"); - return QVariant(); - } - } - - return QVariant(); -} - -QVariant PortModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - if (role != Qt::DisplayRole) - return QVariant(); - - if (orientation == Qt::Horizontal) - return QVariant(); - else - return QString("Name"); -} - -QModelIndex PortModel::index (int row, int col, - const QModelIndex & parent) const -{ - if (!hasIndex(row, col, parent)) - return QModelIndex(); - - //qDebug("index: R=%d, C=%d, PR=%d, PC=%d, PID=%llx\n", - // row, col, parent.row(), parent.column(), parent.internalId()); - - if (!parent.isValid()) - { - // Top Level Item - quint16 pg = pgl->mPortGroups.value(row)->id(), p = 0xFFFF; - quint32 id = (pg << 16) | p; - //qDebug("index (top) dbg: PG=%d, P=%d, ID=%x\n", pg, p, id); - - return createIndex(row, col, id); - } - else - { - quint16 pg = parent.internalId() >> 16; - quint16 p = pgl->mPortGroups.value(parent.row())->mPorts.value(row)->id(); - quint32 id = (pg << 16) | p; - //qDebug("index (nontop) dbg: PG=%d, P=%d, ID=%x\n", pg, p, id); - - return createIndex(row, col, id); - } -} - -QModelIndex PortModel::parent(const QModelIndex &index) const -{ - if (!index.isValid()) - return QModelIndex(); - - //qDebug("parent: R=%d, C=%d ID=%llx\n", - // index.row(), index.column(), index.internalId()); - - quint16 pg = index.internalId() >> 16; - quint16 p = index.internalId() & 0x0000FFFF; - - //qDebug("parent dbg: PG=%d, P=%d\n", pg, p); - - if (p == 0xFFFF) - { - //qDebug("parent ret: NULL\n"); - // Top Level Item - PG - return QModelIndex(); - } - - quint32 id = (pg << 16) | 0xFFFF; - //qDebug("parent ret: R=%d, C=%d, ID=%x\n", pg, 0, id); - - return createIndex(pgl->indexOfPortGroup(pg), 0, id); - -} - -bool PortModel::isPortGroup(const QModelIndex& index) -{ - if ((index.internalId() & 0xFFFF) == 0xFFFF) - return true; - else - return false; -} - -bool PortModel::isPort(const QModelIndex& index) -{ - if ((index.internalId() & 0xFFFF) != 0xFFFF) - return true; - else - return false; -} - -quint32 PortModel::portGroupId(const QModelIndex& index) -{ - return (index.internalId()) >> 16 & 0xFFFF; -} - -quint32 PortModel::portId(const QModelIndex& index) -{ - return (index.internalId()) & 0xFFFF; -} - - - -// ---------------------------------------------- -// Slots -// ---------------------------------------------- -void PortModel::when_portGroupDataChanged(int portGroupId, int portId) -{ - QModelIndex index; - int row; - - if (portId == 0xFFFF) - row = pgl->indexOfPortGroup(portGroupId); - else - row = portId; - - index = createIndex(row, 0, (portGroupId << 16) | portId); - - emit dataChanged(index, index); -} - -void PortModel::portGroupAboutToBeAppended() -{ - int row; - - row = pgl->mPortGroups.size(); - beginInsertRows(QModelIndex(), row, row); -} - -void PortModel::portGroupAppended() -{ - endInsertRows(); -} - -void PortModel::portGroupAboutToBeRemoved(PortGroup *portGroup) -{ - int row; - - row = pgl->mPortGroups.indexOf(portGroup); - beginRemoveRows(QModelIndex(), row, row); -} - -void PortModel::portGroupRemoved() -{ - endRemoveRows(); -} - -void PortModel::when_portListChanged() -{ - reset(); -} +#include "portmodel.h" +#include "portgrouplist.h" +#include + +#if 0 +#define DBG0(x) qDebug(x) +#define DBG1(x, p1) qDebug(x, (p1)) +#else +#define DBG0(x) {} +#define DBG1(x, p1) {} +#endif + +PortModel::PortModel(PortGroupList *p, QObject *parent) + : QAbstractItemModel(parent) +{ + pgl = p; +} + +int PortModel::rowCount(const QModelIndex &parent) const +{ + // qDebug("RowCount Enter\n"); + if (!parent.isValid()) + { + // Top Level Item + //qDebug("RowCount (Top) Exit: %d\n", pgl->mPortGroups.size()); + return pgl->mPortGroups.size(); + } + // qDebug("RowCount non top %d, %d, %llx\n", + // parent.row(), parent.column(), parent.internalId()); + + quint16 pg = (parent.internalId() >> 16) & 0xFFFF; + quint16 p = parent.internalId() & 0xFFFF; + if (p == 0xFFFF) + { +#if 0 // wrong code? + int count = 0; + foreach(PortGroup *pg, pgl->mPortGroups) + { + count += pg->numPorts(); + } + //qDebug("RowCount (Mid) Exit: %d\n", count); + return count; +#endif + if (parent.column() == 0) + return pgl->mPortGroups.value(pgl->indexOfPortGroup(pg))->numPorts(); + else + return 0; + } + else + { + // Leaf Item + return 0; + } +} + +int PortModel::columnCount(const QModelIndex &parent ) const +{ + return 1; // FIXME: hardcoding +} + +Qt::ItemFlags PortModel::flags(const QModelIndex &index) const +{ + return QAbstractItemModel::flags(index); // FIXME: no need for this func +} +QVariant PortModel::data(const QModelIndex &index, int role) const +{ + + DBG0("Enter PortModel data\n"); + + // Check for a valid index + if (!index.isValid()) + return QVariant(); + + DBG1("PortModel::data(index).row = %d", index.row()); + DBG1("PortModel::data(index).column = %0d", index.column()); + DBG1("PortModel::data(index).internalId = %08llx", index.internalId()); + + QModelIndex parent = index.parent(); + + if (!parent.isValid()) + { + // Top Level Item - PortGroup + if ((role == Qt::DisplayRole)) + { + DBG0("Exit PortModel data 1\n"); + return QString("Port Group %1: %2 [%3:%4] (%5)"). + arg(pgl->mPortGroups.at(index.row())->id()). + arg(pgl->mPortGroups.at(index.row())->userAlias()). + arg(pgl->mPortGroups.at(index.row())->serverAddress().toString()). + arg(pgl->mPortGroups.at(index.row())->serverPort()). + arg(pgl->mPortGroups.value(index.row())->numPorts()); + } + else if ((role == Qt::DecorationRole)) + { + DBG0("Exit PortModel data 2\n"); + switch(pgl->mPortGroups.at(index.row())->state()) + { + case QAbstractSocket::UnconnectedState: + return QIcon(":/icons/bullet_red.png"); + + case QAbstractSocket::HostLookupState: + return QIcon(":/icons/bullet_yellow.png"); + + case QAbstractSocket::ConnectingState: + case QAbstractSocket::ClosingState: + return QIcon(":/icons/bullet_orange.png"); + + case QAbstractSocket::ConnectedState: + return QIcon(":/icons/bullet_green.png"); + + + case QAbstractSocket::BoundState: + case QAbstractSocket::ListeningState: + default: + return QIcon(":/icons/bullet_error.png"); + } + } + else + { + DBG0("Exit PortModel data 3\n"); + return QVariant(); + } + } + else + { + // Non Top Level - Port + if ((role == Qt::DisplayRole)) + { + DBG0("Exit PortModel data 4\n"); + if (pgl->mPortGroups.at(parent.row())->numPorts() == 0) + return QVariant(); + + return QString("Port %1: %2 [%3] (%4)"). + arg(pgl->mPortGroups.at( + parent.row())->mPorts[index.row()]->id()). + arg(pgl->mPortGroups.at( + parent.row())->mPorts[index.row()]->name()). + arg(QHostAddress("0.0.0.0").toString()). // FIXME(LOW) + arg(pgl->mPortGroups.at( + parent.row())->mPorts[index.row()]->description()); + } + else if ((role == Qt::DecorationRole)) + { + DBG0("Exit PortModel data 5\n"); + if (pgl->mPortGroups.at(parent.row())->numPorts() == 0) + return QVariant(); + switch(pgl->mPortGroups.at(parent.row())->mPorts[index.row()]->linkState()) + { + case OstProto::LinkStateUnknown: + return QIcon(":/icons/bullet_white.png"); + case OstProto::LinkStateDown: + return QIcon(":/icons/bullet_red.png"); + case OstProto::LinkStateUp: + return QIcon(":/icons/bullet_green.png"); + default: + qFatal("unexpected/unimplemented port oper state"); + } + } + else + { + DBG0("Exit PortModel data 6\n"); + return QVariant(); + } + } + + return QVariant(); +} + +QVariant PortModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (role != Qt::DisplayRole) + return QVariant(); + + if (orientation == Qt::Horizontal) + return QVariant(); + else + return QString("Name"); +} + +QModelIndex PortModel::index (int row, int col, + const QModelIndex & parent) const +{ + if (!hasIndex(row, col, parent)) + return QModelIndex(); + + //qDebug("index: R=%d, C=%d, PR=%d, PC=%d, PID=%llx\n", + // row, col, parent.row(), parent.column(), parent.internalId()); + + if (!parent.isValid()) + { + // Top Level Item + quint16 pg = pgl->mPortGroups.value(row)->id(), p = 0xFFFF; + quint32 id = (pg << 16) | p; + //qDebug("index (top) dbg: PG=%d, P=%d, ID=%x\n", pg, p, id); + + return createIndex(row, col, id); + } + else + { + quint16 pg = parent.internalId() >> 16; + quint16 p = pgl->mPortGroups.value(parent.row())->mPorts.value(row)->id(); + quint32 id = (pg << 16) | p; + //qDebug("index (nontop) dbg: PG=%d, P=%d, ID=%x\n", pg, p, id); + + return createIndex(row, col, id); + } +} + +QModelIndex PortModel::parent(const QModelIndex &index) const +{ + if (!index.isValid()) + return QModelIndex(); + + //qDebug("parent: R=%d, C=%d ID=%llx\n", + // index.row(), index.column(), index.internalId()); + + quint16 pg = index.internalId() >> 16; + quint16 p = index.internalId() & 0x0000FFFF; + + //qDebug("parent dbg: PG=%d, P=%d\n", pg, p); + + if (p == 0xFFFF) + { + //qDebug("parent ret: NULL\n"); + // Top Level Item - PG + return QModelIndex(); + } + + quint32 id = (pg << 16) | 0xFFFF; + //qDebug("parent ret: R=%d, C=%d, ID=%x\n", pg, 0, id); + + return createIndex(pgl->indexOfPortGroup(pg), 0, id); + +} + +bool PortModel::isPortGroup(const QModelIndex& index) +{ + if ((index.internalId() & 0xFFFF) == 0xFFFF) + return true; + else + return false; +} + +bool PortModel::isPort(const QModelIndex& index) +{ + if ((index.internalId() & 0xFFFF) != 0xFFFF) + return true; + else + return false; +} + +quint32 PortModel::portGroupId(const QModelIndex& index) +{ + return (index.internalId()) >> 16 & 0xFFFF; +} + +quint32 PortModel::portId(const QModelIndex& index) +{ + return (index.internalId()) & 0xFFFF; +} + + + +// ---------------------------------------------- +// Slots +// ---------------------------------------------- +void PortModel::when_portGroupDataChanged(int portGroupId, int portId) +{ + QModelIndex index; + int row; + + if (portId == 0xFFFF) + row = pgl->indexOfPortGroup(portGroupId); + else + row = portId; + + index = createIndex(row, 0, (portGroupId << 16) | portId); + + emit dataChanged(index, index); +} + +void PortModel::portGroupAboutToBeAppended() +{ + int row; + + row = pgl->mPortGroups.size(); + beginInsertRows(QModelIndex(), row, row); +} + +void PortModel::portGroupAppended() +{ + endInsertRows(); +} + +void PortModel::portGroupAboutToBeRemoved(PortGroup *portGroup) +{ + int row; + + row = pgl->mPortGroups.indexOf(portGroup); + beginRemoveRows(QModelIndex(), row, row); +} + +void PortModel::portGroupRemoved() +{ + endRemoveRows(); +} + +void PortModel::when_portListChanged() +{ + reset(); +} diff --git a/client/portmodel.h b/client/portmodel.h index eea9763..7f3b821 100644 --- a/client/portmodel.h +++ b/client/portmodel.h @@ -1,51 +1,51 @@ -#ifndef _PORT_MODEL_H -#define _PORT_MODEL_H - -#include - -class PortGroupList; -class PortGroup; - -class PortModel : public QAbstractItemModel -{ - Q_OBJECT - - friend class PortGroupList; - - PortGroupList *pgl; - - public: - PortModel(PortGroupList *p, QObject *parent = 0); - - int rowCount(const QModelIndex &parent = QModelIndex()) const; - int columnCount(const QModelIndex &parent = QModelIndex()) const; - Qt::ItemFlags flags(const QModelIndex &index) const; - QVariant data(const QModelIndex &index, int role) const; - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; - QModelIndex index (int row, int col, const QModelIndex & parent = QModelIndex() ) const; - QModelIndex parent(const QModelIndex &index) const; - - bool isPortGroup(const QModelIndex& index); - bool isPort(const QModelIndex& index); - quint32 portGroupId(const QModelIndex& index); - quint32 portId(const QModelIndex& index); - - -private slots: - void when_portGroupDataChanged(int portGroupId, int portId); - - void portGroupAboutToBeAppended(); - void portGroupAppended(); - void portGroupAboutToBeRemoved(PortGroup *portGroup); - void portGroupRemoved(); - - void when_portListChanged(); - -#if 0 - void triggerLayoutAboutToBeChanged(); - void triggerLayoutChanged(); -#endif - -}; - -#endif +#ifndef _PORT_MODEL_H +#define _PORT_MODEL_H + +#include + +class PortGroupList; +class PortGroup; + +class PortModel : public QAbstractItemModel +{ + Q_OBJECT + + friend class PortGroupList; + + PortGroupList *pgl; + + public: + PortModel(PortGroupList *p, QObject *parent = 0); + + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + QVariant data(const QModelIndex &index, int role) const; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + QModelIndex index (int row, int col, const QModelIndex & parent = QModelIndex() ) const; + QModelIndex parent(const QModelIndex &index) const; + + bool isPortGroup(const QModelIndex& index); + bool isPort(const QModelIndex& index); + quint32 portGroupId(const QModelIndex& index); + quint32 portId(const QModelIndex& index); + + +private slots: + void when_portGroupDataChanged(int portGroupId, int portId); + + void portGroupAboutToBeAppended(); + void portGroupAppended(); + void portGroupAboutToBeRemoved(PortGroup *portGroup); + void portGroupRemoved(); + + void when_portListChanged(); + +#if 0 + void triggerLayoutAboutToBeChanged(); + void triggerLayoutChanged(); +#endif + +}; + +#endif diff --git a/client/portstatsfilterdialog.cpp b/client/portstatsfilterdialog.cpp index b21bd37..4291fea 100644 --- a/client/portstatsfilterdialog.cpp +++ b/client/portstatsfilterdialog.cpp @@ -1,111 +1,111 @@ -#include "portstatsfilterdialog.h" - -PortStatsFilterDialog::PortStatsFilterDialog(QWidget *parent) -{ - setupUi(this); - - mUnselected.setSortRole(PositionRole); - - lvUnselected->setModel(&mUnselected); - lvSelected->setModel(&mSelected); -} - -QList PortStatsFilterDialog::getItemList(bool* ok, - QAbstractItemModel *model, Qt::Orientation orientation, - QList initial) -{ - QList 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); - item->setFlags(Qt::ItemIsSelectable - | Qt::ItemIsDragEnabled - //| Qt::ItemIsDropEnabled - | Qt::ItemIsEnabled); - - 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; - while (lvUnselected->selectionModel()->selectedIndexes().size()) - { - item = mUnselected.takeItem(lvUnselected->selectionModel()-> - selectedIndexes().at(0).row()); - if (mUnselected.removeRow(lvUnselected->selectionModel()-> - selectedIndexes().at(0).row())) - mSelected.appendRow(item); - } -} - -void PortStatsFilterDialog::on_tbSelectOut_clicked() -{ - QStandardItem *item; - - while (lvSelected->selectionModel()->selectedIndexes().size()) - { - item = mSelected.takeItem(lvSelected->selectionModel()-> - selectedIndexes().at(0).row()); - if (mSelected.removeRow(lvSelected->selectionModel()-> - selectedIndexes().at(0).row())) - { - mUnselected.appendRow(item); - mUnselected.sort(0); - } - } -} - -void PortStatsFilterDialog::on_lvUnselected_doubleClicked(const QModelIndex &index) -{ - QStandardItem *item; - - item = mUnselected.takeItem(lvUnselected->currentIndex().row()); - if (mUnselected.removeRow(lvUnselected->currentIndex().row())) - mSelected.appendRow(item); -} - -void PortStatsFilterDialog::on_lvSelected_doubleClicked(const QModelIndex &index) -{ - QStandardItem *item; - - item = mSelected.takeItem(lvSelected->currentIndex().row()); - if (mSelected.removeRow(lvSelected->currentIndex().row())) - { - mUnselected.appendRow(item); - mUnselected.sort(0); - } -} - +#include "portstatsfilterdialog.h" + +PortStatsFilterDialog::PortStatsFilterDialog(QWidget *parent) +{ + setupUi(this); + + mUnselected.setSortRole(PositionRole); + + lvUnselected->setModel(&mUnselected); + lvSelected->setModel(&mSelected); +} + +QList PortStatsFilterDialog::getItemList(bool* ok, + QAbstractItemModel *model, Qt::Orientation orientation, + QList initial) +{ + QList 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); + item->setFlags(Qt::ItemIsSelectable + | Qt::ItemIsDragEnabled + //| Qt::ItemIsDropEnabled + | Qt::ItemIsEnabled); + + 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; + while (lvUnselected->selectionModel()->selectedIndexes().size()) + { + item = mUnselected.takeItem(lvUnselected->selectionModel()-> + selectedIndexes().at(0).row()); + if (mUnselected.removeRow(lvUnselected->selectionModel()-> + selectedIndexes().at(0).row())) + mSelected.appendRow(item); + } +} + +void PortStatsFilterDialog::on_tbSelectOut_clicked() +{ + QStandardItem *item; + + while (lvSelected->selectionModel()->selectedIndexes().size()) + { + item = mSelected.takeItem(lvSelected->selectionModel()-> + selectedIndexes().at(0).row()); + if (mSelected.removeRow(lvSelected->selectionModel()-> + selectedIndexes().at(0).row())) + { + mUnselected.appendRow(item); + mUnselected.sort(0); + } + } +} + +void PortStatsFilterDialog::on_lvUnselected_doubleClicked(const QModelIndex &index) +{ + QStandardItem *item; + + item = mUnselected.takeItem(lvUnselected->currentIndex().row()); + if (mUnselected.removeRow(lvUnselected->currentIndex().row())) + mSelected.appendRow(item); +} + +void PortStatsFilterDialog::on_lvSelected_doubleClicked(const QModelIndex &index) +{ + QStandardItem *item; + + item = mSelected.takeItem(lvSelected->currentIndex().row()); + if (mSelected.removeRow(lvSelected->currentIndex().row())) + { + mUnselected.appendRow(item); + mUnselected.sort(0); + } +} + diff --git a/client/portstatsfilterdialog.h b/client/portstatsfilterdialog.h index ce8016c..28d94ed 100644 --- a/client/portstatsfilterdialog.h +++ b/client/portstatsfilterdialog.h @@ -1,35 +1,35 @@ -#ifndef _PORT_STATS_FILTER_DIALOG_H -#define _PORT_STATS_FILTER_DIALOG_H - -#include -#include -#include -#include "ui_portstatsfilter.h" -#include "portgrouplist.h" - -class PortStatsFilterDialog : public QDialog, public Ui::PortStatsFilterDialog -{ - Q_OBJECT - -public: - PortStatsFilterDialog(QWidget *parent = 0); - QList getItemList(bool* ok, QAbstractItemModel *model, - Qt::Orientation orientation = Qt::Vertical, - QList initial = QList()); - -private: - enum ItemRole { - PositionRole = Qt::UserRole + 1 - }; - QStandardItemModel mUnselected; - QStandardItemModel mSelected; - -private slots: - void on_tbSelectIn_clicked(); - void on_tbSelectOut_clicked(); - void on_lvUnselected_doubleClicked(const QModelIndex &index); - void on_lvSelected_doubleClicked(const QModelIndex &index); -}; - -#endif - +#ifndef _PORT_STATS_FILTER_DIALOG_H +#define _PORT_STATS_FILTER_DIALOG_H + +#include +#include +#include +#include "ui_portstatsfilter.h" +#include "portgrouplist.h" + +class PortStatsFilterDialog : public QDialog, public Ui::PortStatsFilterDialog +{ + Q_OBJECT + +public: + PortStatsFilterDialog(QWidget *parent = 0); + QList getItemList(bool* ok, QAbstractItemModel *model, + Qt::Orientation orientation = Qt::Vertical, + QList initial = QList()); + +private: + enum ItemRole { + PositionRole = Qt::UserRole + 1 + }; + QStandardItemModel mUnselected; + QStandardItemModel mSelected; + +private slots: + void on_tbSelectIn_clicked(); + void on_tbSelectOut_clicked(); + void on_lvUnselected_doubleClicked(const QModelIndex &index); + void on_lvSelected_doubleClicked(const QModelIndex &index); +}; + +#endif + diff --git a/client/portstatsmodel.cpp b/client/portstatsmodel.cpp index 5aec2b6..58993e4 100644 --- a/client/portstatsmodel.cpp +++ b/client/portstatsmodel.cpp @@ -1,288 +1,288 @@ -#include "portstatsmodel.h" -#include "portgrouplist.h" - -#include - -PortStatsModel::PortStatsModel(PortGroupList *p, QObject *parent) - : QAbstractTableModel(parent) -{ - QTimer *timer; - - pgl = p; - - timer = new QTimer(); - connect(timer, SIGNAL(timeout()), this, SLOT(updateStats())); - timer->start(1000); -} - -int PortStatsModel::rowCount(const QModelIndex &parent) const -{ - if (parent.isValid()) - return 0; - - if (numPorts.isEmpty()) - return 0; - - if (numPorts.last() == 0) - return 0; - - return (int) e_STAT_MAX; -} - -int PortStatsModel::columnCount(const QModelIndex &parent ) const -{ - if (parent.isValid()) - return 0; - else - if (numPorts.isEmpty()) - return 0; - else - return numPorts.last(); -} - -void PortStatsModel::getDomainIndexes(const QModelIndex &index, - uint &portGroupIdx, uint &portIdx) const -{ - int portNum; - - // TODO(LOW): Optimize using binary search: see qLowerBound() - portNum = index.column() + 1; - for (portGroupIdx = 0; portGroupIdx < (uint) numPorts.size(); portGroupIdx++) - if (portNum <= numPorts.at(portGroupIdx)) - break; - - if (portGroupIdx) - { - if (numPorts.at(portGroupIdx -1)) - portIdx = (portNum - 1) % numPorts.at(portGroupIdx - 1); - else - portIdx = portNum - 1; - } - else - portIdx = portNum - 1; - - //qDebug("PSM: %d - %d, %d", index.column(), portGroupIdx, portIdx); -} - -QVariant PortStatsModel::data(const QModelIndex &index, int role) const -{ - uint pgidx, pidx; - int row; - - // Check for a valid index - if (!index.isValid()) - return QVariant(); - - // Check for row/column limits - row = index.row(); - if (row >= e_STAT_MAX) - return QVariant(); - - if (numPorts.isEmpty()) - return QVariant(); - - if (index.column() >= (numPorts.last())) - return QVariant(); - - getDomainIndexes(index, pgidx, pidx); - - // Check role - if (role == Qt::DisplayRole) - { - OstProto::PortStats stats; - - stats = pgl->mPortGroups.at(pgidx)->mPorts[pidx]->getStats(); - - switch(row) - { - // States - case e_LINK_STATE: - return LinkStateName.at(stats.state().link_state()); - - case e_TRANSMIT_STATE: - return BoolStateName.at(stats.state().is_transmit_on()); - - case e_CAPTURE_STATE: - return BoolStateName.at(stats.state().is_capture_on()); - - // Statistics - case e_STAT_FRAMES_RCVD: - return stats.rx_pkts(); - - case e_STAT_FRAMES_SENT: - return stats.tx_pkts(); - - case e_STAT_FRAME_SEND_RATE: - return stats.tx_pps(); - - case e_STAT_FRAME_RECV_RATE: - return stats.rx_pps(); - - case e_STAT_BYTES_RCVD: - return stats.rx_bytes(); - - case e_STAT_BYTES_SENT: - return stats.tx_bytes(); - - case e_STAT_BYTE_SEND_RATE: - return stats.tx_bps(); - - case e_STAT_BYTE_RECV_RATE: - return stats.rx_bps(); - -#if 0 - case e_STAT_FRAMES_RCVD_NIC: - return stats.rx_pkts_nic(); - - case e_STAT_FRAMES_SENT_NIC: - return stats.tx_pkts_nic(); - - case e_STAT_BYTES_RCVD_NIC: - return stats.rx_bytes_nic(); - - case e_STAT_BYTES_SENT_NIC: - return stats.tx_bytes_nic(); -#endif - default: - qWarning("%s: Unhandled stats id %d\n", __FUNCTION__, - index.row()); - return 0; - } - } - else if (role == Qt::TextAlignmentRole) - { - if (row >= e_STATE_START && row <= e_STATE_END) - return Qt::AlignHCenter; - else if (row >= e_STATISTICS_START && row <= e_STATISTICS_END) - return Qt::AlignRight; - else - return QVariant(); - } - else - return QVariant(); - -} - -QVariant PortStatsModel::headerData(int section, Qt::Orientation orientation, int role) const -{ -#ifdef Q_OS_WIN32 - // TODO(MED): The limitations should be the server's not the client's! - // Ideally we shd enhance the protocol to convey limitation(s), if any, - // from server to client - if (role == Qt::ToolTipRole) - { - if (orientation == Qt::Horizontal) - { - return QString("Limitation(s)" - "

Frames/Bytes Receieved: Includes non Ostinato Tx pkts also (Tx by Ostinato are not included)
" - "Frames/Bytes Sent: Only Ostinato Tx pkts (Tx by others NOT included)

" - "

Rx/Tx Rates are derived from the above and hence subject to same limitations

" - ); - } - else - return QVariant(); - } -#endif - - if (role != Qt::DisplayRole) - return QVariant(); - - if (orientation == Qt::Horizontal) - { - uint portGroupIdx, portIdx; - - getDomainIndexes(index(0, section), portGroupIdx, portIdx); -#ifdef Q_OS_WIN32 - return QString("Port %1-%2 (*)").arg(portGroupIdx).arg(portIdx); -#else - return QString("Port %1-%2").arg(portGroupIdx).arg(portIdx); -#endif - } - else - return PortStatName.at(section); -} - -void PortStatsModel::portListFromIndex(QModelIndexList indices, - QList &portList) -{ - int i, j; - QModelIndexList selectedCols(indices); - - portList.clear(); - - //selectedCols = indices.selectedColumns(); - for (i = 0; i < selectedCols.size(); i++) - { - uint portGroupIdx, portIdx; - - getDomainIndexes(selectedCols.at(i), portGroupIdx, portIdx); - for (j = 0; j < portList.size(); j++) - { - if (portList[j].portGroupId == portGroupIdx) - break; - } - - if (j >= portList.size()) - { - // PortGroup Not found - PortGroupAndPortList p; - - p.portGroupId = portGroupIdx; - p.portList.append(portIdx); - - portList.append(p); - } - else - { - // PortGroup found - - portList[j].portList.append(portIdx); - } - } -} - -// -// Slots -// -void PortStatsModel::when_portListChanged() -{ - int i, count = 0; - - // recalc numPorts - while (numPorts.size()) - numPorts.removeFirst(); - - for (i = 0; i < pgl->mPortGroups.size(); i++) - { - count += pgl->mPortGroups.at(i)->numPorts(); - numPorts.append(count); - } - - reset(); -} - -void PortStatsModel::on_portStatsUpdate(int port, void*stats) -{ - QModelIndex topLeft = index(port, 0, QModelIndex()); - QModelIndex bottomRight = index(port, e_STAT_MAX, QModelIndex()); - - emit dataChanged(topLeft, bottomRight); -} - -void PortStatsModel::updateStats() -{ - // Request each portgroup to fetch updated stats - the port group - // raises a signal once updated stats are available - for (int i = 0; i < pgl->mPortGroups.size(); i++) - pgl->mPortGroups[i]->getPortStats(); -} - -void PortStatsModel::when_portGroup_stats_update(quint32 portGroupId) -{ - // FIXME(MED): update only the changed ports, not all - - QModelIndex topLeft = index(0, 0, QModelIndex()); - QModelIndex bottomRight = index(rowCount(), columnCount(), QModelIndex()); - - emit dataChanged(topLeft, bottomRight); -} +#include "portstatsmodel.h" +#include "portgrouplist.h" + +#include + +PortStatsModel::PortStatsModel(PortGroupList *p, QObject *parent) + : QAbstractTableModel(parent) +{ + QTimer *timer; + + pgl = p; + + timer = new QTimer(); + connect(timer, SIGNAL(timeout()), this, SLOT(updateStats())); + timer->start(1000); +} + +int PortStatsModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) + return 0; + + if (numPorts.isEmpty()) + return 0; + + if (numPorts.last() == 0) + return 0; + + return (int) e_STAT_MAX; +} + +int PortStatsModel::columnCount(const QModelIndex &parent ) const +{ + if (parent.isValid()) + return 0; + else + if (numPorts.isEmpty()) + return 0; + else + return numPorts.last(); +} + +void PortStatsModel::getDomainIndexes(const QModelIndex &index, + uint &portGroupIdx, uint &portIdx) const +{ + int portNum; + + // TODO(LOW): Optimize using binary search: see qLowerBound() + portNum = index.column() + 1; + for (portGroupIdx = 0; portGroupIdx < (uint) numPorts.size(); portGroupIdx++) + if (portNum <= numPorts.at(portGroupIdx)) + break; + + if (portGroupIdx) + { + if (numPorts.at(portGroupIdx -1)) + portIdx = (portNum - 1) % numPorts.at(portGroupIdx - 1); + else + portIdx = portNum - 1; + } + else + portIdx = portNum - 1; + + //qDebug("PSM: %d - %d, %d", index.column(), portGroupIdx, portIdx); +} + +QVariant PortStatsModel::data(const QModelIndex &index, int role) const +{ + uint pgidx, pidx; + int row; + + // Check for a valid index + if (!index.isValid()) + return QVariant(); + + // Check for row/column limits + row = index.row(); + if (row >= e_STAT_MAX) + return QVariant(); + + if (numPorts.isEmpty()) + return QVariant(); + + if (index.column() >= (numPorts.last())) + return QVariant(); + + getDomainIndexes(index, pgidx, pidx); + + // Check role + if (role == Qt::DisplayRole) + { + OstProto::PortStats stats; + + stats = pgl->mPortGroups.at(pgidx)->mPorts[pidx]->getStats(); + + switch(row) + { + // States + case e_LINK_STATE: + return LinkStateName.at(stats.state().link_state()); + + case e_TRANSMIT_STATE: + return BoolStateName.at(stats.state().is_transmit_on()); + + case e_CAPTURE_STATE: + return BoolStateName.at(stats.state().is_capture_on()); + + // Statistics + case e_STAT_FRAMES_RCVD: + return stats.rx_pkts(); + + case e_STAT_FRAMES_SENT: + return stats.tx_pkts(); + + case e_STAT_FRAME_SEND_RATE: + return stats.tx_pps(); + + case e_STAT_FRAME_RECV_RATE: + return stats.rx_pps(); + + case e_STAT_BYTES_RCVD: + return stats.rx_bytes(); + + case e_STAT_BYTES_SENT: + return stats.tx_bytes(); + + case e_STAT_BYTE_SEND_RATE: + return stats.tx_bps(); + + case e_STAT_BYTE_RECV_RATE: + return stats.rx_bps(); + +#if 0 + case e_STAT_FRAMES_RCVD_NIC: + return stats.rx_pkts_nic(); + + case e_STAT_FRAMES_SENT_NIC: + return stats.tx_pkts_nic(); + + case e_STAT_BYTES_RCVD_NIC: + return stats.rx_bytes_nic(); + + case e_STAT_BYTES_SENT_NIC: + return stats.tx_bytes_nic(); +#endif + default: + qWarning("%s: Unhandled stats id %d\n", __FUNCTION__, + index.row()); + return 0; + } + } + else if (role == Qt::TextAlignmentRole) + { + if (row >= e_STATE_START && row <= e_STATE_END) + return Qt::AlignHCenter; + else if (row >= e_STATISTICS_START && row <= e_STATISTICS_END) + return Qt::AlignRight; + else + return QVariant(); + } + else + return QVariant(); + +} + +QVariant PortStatsModel::headerData(int section, Qt::Orientation orientation, int role) const +{ +#ifdef Q_OS_WIN32 + // TODO(MED): The limitations should be the server's not the client's! + // Ideally we shd enhance the protocol to convey limitation(s), if any, + // from server to client + if (role == Qt::ToolTipRole) + { + if (orientation == Qt::Horizontal) + { + return QString("Limitation(s)" + "

Frames/Bytes Receieved: Includes non Ostinato Tx pkts also (Tx by Ostinato are not included)
" + "Frames/Bytes Sent: Only Ostinato Tx pkts (Tx by others NOT included)

" + "

Rx/Tx Rates are derived from the above and hence subject to same limitations

" + ); + } + else + return QVariant(); + } +#endif + + if (role != Qt::DisplayRole) + return QVariant(); + + if (orientation == Qt::Horizontal) + { + uint portGroupIdx, portIdx; + + getDomainIndexes(index(0, section), portGroupIdx, portIdx); +#ifdef Q_OS_WIN32 + return QString("Port %1-%2 (*)").arg(portGroupIdx).arg(portIdx); +#else + return QString("Port %1-%2").arg(portGroupIdx).arg(portIdx); +#endif + } + else + return PortStatName.at(section); +} + +void PortStatsModel::portListFromIndex(QModelIndexList indices, + QList &portList) +{ + int i, j; + QModelIndexList selectedCols(indices); + + portList.clear(); + + //selectedCols = indices.selectedColumns(); + for (i = 0; i < selectedCols.size(); i++) + { + uint portGroupIdx, portIdx; + + getDomainIndexes(selectedCols.at(i), portGroupIdx, portIdx); + for (j = 0; j < portList.size(); j++) + { + if (portList[j].portGroupId == portGroupIdx) + break; + } + + if (j >= portList.size()) + { + // PortGroup Not found + PortGroupAndPortList p; + + p.portGroupId = portGroupIdx; + p.portList.append(portIdx); + + portList.append(p); + } + else + { + // PortGroup found + + portList[j].portList.append(portIdx); + } + } +} + +// +// Slots +// +void PortStatsModel::when_portListChanged() +{ + int i, count = 0; + + // recalc numPorts + while (numPorts.size()) + numPorts.removeFirst(); + + for (i = 0; i < pgl->mPortGroups.size(); i++) + { + count += pgl->mPortGroups.at(i)->numPorts(); + numPorts.append(count); + } + + reset(); +} + +void PortStatsModel::on_portStatsUpdate(int port, void*stats) +{ + QModelIndex topLeft = index(port, 0, QModelIndex()); + QModelIndex bottomRight = index(port, e_STAT_MAX, QModelIndex()); + + emit dataChanged(topLeft, bottomRight); +} + +void PortStatsModel::updateStats() +{ + // Request each portgroup to fetch updated stats - the port group + // raises a signal once updated stats are available + for (int i = 0; i < pgl->mPortGroups.size(); i++) + pgl->mPortGroups[i]->getPortStats(); +} + +void PortStatsModel::when_portGroup_stats_update(quint32 portGroupId) +{ + // FIXME(MED): update only the changed ports, not all + + QModelIndex topLeft = index(0, 0, QModelIndex()); + QModelIndex bottomRight = index(rowCount(), columnCount(), QModelIndex()); + + emit dataChanged(topLeft, bottomRight); +} diff --git a/client/portstatsmodel.h b/client/portstatsmodel.h index e253e22..3baa7c2 100644 --- a/client/portstatsmodel.h +++ b/client/portstatsmodel.h @@ -1,117 +1,117 @@ -#ifndef _PORT_STATS_MODEL_H -#define _PORT_STATS_MODEL_H - -#include -#include - -typedef enum { - // State - e_STATE_START = 0, - - e_LINK_STATE = e_STATE_START, - e_TRANSMIT_STATE, - e_CAPTURE_STATE, - - e_STATE_END = e_CAPTURE_STATE, - - // Statistics - e_STATISTICS_START, - - e_STAT_FRAMES_RCVD = e_STATISTICS_START, - e_STAT_FRAMES_SENT, - e_STAT_FRAME_SEND_RATE, - e_STAT_FRAME_RECV_RATE, - e_STAT_BYTES_RCVD, - e_STAT_BYTES_SENT, - e_STAT_BYTE_SEND_RATE, - e_STAT_BYTE_RECV_RATE, -#if 0 - e_STAT_FRAMES_RCVD_NIC, - e_STAT_FRAMES_SENT_NIC, - e_STAT_BYTES_RCVD_NIC, - e_STAT_BYTES_SENT_NIC, -#endif - - e_STATISTICS_END = e_STAT_BYTE_RECV_RATE, - - e_STAT_MAX -} PortStat; - -static QStringList PortStatName = (QStringList() - << "Link State" - << "Transmit State" - << "Capture State" - - << "Frames Received" - << "Frames Sent" - << "Frame Send Rate (fps)" - << "Frame Receive Rate (fps)" - << "Bytes Received" - << "Bytes Sent" - << "Byte Send Rate (Bps)" - << "Byte Receive Rate (Bps)" -#if 0 - << "Frames Received (NIC)" - << "Frames Sent (NIC)" - << "Bytes Received (NIC)" - << "Bytes Sent (NIC)" -#endif -); - -static QStringList LinkStateName = (QStringList() - << "Unknown" - << "Down" - << "Up" -); - -static QStringList BoolStateName = (QStringList() - << "Off" - << "On" -); - -class PortGroupList; - -class PortStatsModel : public QAbstractTableModel -{ - Q_OBJECT - - public: - - PortStatsModel(PortGroupList *p, 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; - QVariant headerData(int section, Qt::Orientation orientation, - int role = Qt::DisplayRole) const; - - class PortGroupAndPortList { - public: - uint portGroupId; - QList portList; - }; - void portListFromIndex(QModelIndexList indices, - QList &portList); - - public slots: - void when_portListChanged(); - void on_portStatsUpdate(int port, void*stats); - void when_portGroup_stats_update(quint32 portGroupId); - - private slots: - void updateStats(); - - private: - PortGroupList *pgl; - - // numPorts stores the num of ports per portgroup - // in the same order as the portgroups are index in the pgl - // Also it stores them as cumulative totals - QList numPorts; - - void getDomainIndexes(const QModelIndex &index, - uint &portGroupIdx, uint &portIdx) const; - -}; - -#endif +#ifndef _PORT_STATS_MODEL_H +#define _PORT_STATS_MODEL_H + +#include +#include + +typedef enum { + // State + e_STATE_START = 0, + + e_LINK_STATE = e_STATE_START, + e_TRANSMIT_STATE, + e_CAPTURE_STATE, + + e_STATE_END = e_CAPTURE_STATE, + + // Statistics + e_STATISTICS_START, + + e_STAT_FRAMES_RCVD = e_STATISTICS_START, + e_STAT_FRAMES_SENT, + e_STAT_FRAME_SEND_RATE, + e_STAT_FRAME_RECV_RATE, + e_STAT_BYTES_RCVD, + e_STAT_BYTES_SENT, + e_STAT_BYTE_SEND_RATE, + e_STAT_BYTE_RECV_RATE, +#if 0 + e_STAT_FRAMES_RCVD_NIC, + e_STAT_FRAMES_SENT_NIC, + e_STAT_BYTES_RCVD_NIC, + e_STAT_BYTES_SENT_NIC, +#endif + + e_STATISTICS_END = e_STAT_BYTE_RECV_RATE, + + e_STAT_MAX +} PortStat; + +static QStringList PortStatName = (QStringList() + << "Link State" + << "Transmit State" + << "Capture State" + + << "Frames Received" + << "Frames Sent" + << "Frame Send Rate (fps)" + << "Frame Receive Rate (fps)" + << "Bytes Received" + << "Bytes Sent" + << "Byte Send Rate (Bps)" + << "Byte Receive Rate (Bps)" +#if 0 + << "Frames Received (NIC)" + << "Frames Sent (NIC)" + << "Bytes Received (NIC)" + << "Bytes Sent (NIC)" +#endif +); + +static QStringList LinkStateName = (QStringList() + << "Unknown" + << "Down" + << "Up" +); + +static QStringList BoolStateName = (QStringList() + << "Off" + << "On" +); + +class PortGroupList; + +class PortStatsModel : public QAbstractTableModel +{ + Q_OBJECT + + public: + + PortStatsModel(PortGroupList *p, 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; + QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const; + + class PortGroupAndPortList { + public: + uint portGroupId; + QList portList; + }; + void portListFromIndex(QModelIndexList indices, + QList &portList); + + public slots: + void when_portListChanged(); + void on_portStatsUpdate(int port, void*stats); + void when_portGroup_stats_update(quint32 portGroupId); + + private slots: + void updateStats(); + + private: + PortGroupList *pgl; + + // numPorts stores the num of ports per portgroup + // in the same order as the portgroups are index in the pgl + // Also it stores them as cumulative totals + QList numPorts; + + void getDomainIndexes(const QModelIndex &index, + uint &portGroupIdx, uint &portIdx) const; + +}; + +#endif diff --git a/client/portstatswindow.cpp b/client/portstatswindow.cpp index c10834d..9b8b224 100644 --- a/client/portstatswindow.cpp +++ b/client/portstatswindow.cpp @@ -1,161 +1,161 @@ - -#include "portstatswindow.h" -#include "portstatsmodel.h" -#include "portstatsfilterdialog.h" - -#include "QHeaderView" - -PortStatsWindow::PortStatsWindow(PortGroupList *pgl, QWidget *parent) - : QWidget(parent) -{ - setupUi(this); - - this->pgl = pgl; - model = pgl->getPortStatsModel(); - tvPortStats->setModel(model); - - tvPortStats->verticalHeader()->setHighlightSections(false); - tvPortStats->verticalHeader()->setDefaultSectionSize( - tvPortStats->verticalHeader()->minimumSectionSize()); - -} - -PortStatsWindow::~PortStatsWindow() -{ -} - -/* ------------- SLOTS -------------- */ - -void PortStatsWindow::on_tbStartTransmit_clicked() -{ - QList pgpl; - - // Get selected ports - model->portListFromIndex(tvPortStats->selectionModel()->selectedColumns(), - pgpl); - - // Clear selected ports, portgroup by portgroup - for (int i = 0; i < pgpl.size(); i++) - { - pgl->portGroupByIndex(pgpl.at(i).portGroupId). - startTx(&pgpl[i].portList); - } -} - -void PortStatsWindow::on_tbStopTransmit_clicked() -{ - QList pgpl; - - // Get selected ports - model->portListFromIndex(tvPortStats->selectionModel()->selectedColumns(), - pgpl); - - // Clear selected ports, portgroup by portgroup - for (int i = 0; i < pgpl.size(); i++) - { - pgl->portGroupByIndex(pgpl.at(i).portGroupId). - stopTx(&pgpl[i].portList); - } -} - -void PortStatsWindow::on_tbStartCapture_clicked() -{ - // TODO(MED) - QList pgpl; - - // Get selected ports - model->portListFromIndex(tvPortStats->selectionModel()->selectedColumns(), - pgpl); - - // Clear selected ports, portgroup by portgroup - for (int i = 0; i < pgpl.size(); i++) - { - pgl->portGroupByIndex(pgpl.at(i).portGroupId). - startCapture(&pgpl[i].portList); - } -} - -void PortStatsWindow::on_tbStopCapture_clicked() -{ - // TODO(MED) - QList pgpl; - - // Get selected ports - model->portListFromIndex(tvPortStats->selectionModel()->selectedColumns(), - pgpl); - - // Clear selected ports, portgroup by portgroup - for (int i = 0; i < pgpl.size(); i++) - { - pgl->portGroupByIndex(pgpl.at(i).portGroupId). - stopCapture(&pgpl[i].portList); - } -} - -void PortStatsWindow::on_tbViewCapture_clicked() -{ - // TODO(MED) - QList pgpl; - - // Get selected ports - model->portListFromIndex(tvPortStats->selectionModel()->selectedColumns(), - pgpl); - - // Clear selected ports, portgroup by portgroup - for (int i = 0; i < pgpl.size(); i++) - { - pgl->portGroupByIndex(pgpl.at(i).portGroupId). - viewCapture(&pgpl[i].portList); - } -} - -void PortStatsWindow::on_tbClear_clicked() -{ - QList portList; - - // Get selected ports - model->portListFromIndex(tvPortStats->selectionModel()->selectedColumns(), - portList); - - // Clear selected ports, portgroup by portgroup - for (int i = 0; i < portList.size(); i++) - { - pgl->portGroupByIndex(portList.at(i).portGroupId). - clearPortStats(&portList[i].portList); - } -} - -void PortStatsWindow::on_tbClearAll_clicked() -{ - for (int i = 0; i < pgl->numPortGroups(); i++) - { - pgl->portGroupByIndex(0).clearPortStats(); - } -} - -void PortStatsWindow::on_tbFilter_clicked() -{ - bool ok; - QList 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) - { - // hide/show sections first ... - for(int i = 0; i < model->columnCount(); i++) - tvPortStats->setColumnHidden(i, !newColumns.contains(i)); - - // ... then for the 'shown' columns, set the visual index - for(int i = 0; i < newColumns.size(); i++) - { - tvPortStats->horizontalHeader()->moveSection(tvPortStats-> - horizontalHeader()->visualIndex(newColumns.at(i)), i); - } - } -} + +#include "portstatswindow.h" +#include "portstatsmodel.h" +#include "portstatsfilterdialog.h" + +#include "QHeaderView" + +PortStatsWindow::PortStatsWindow(PortGroupList *pgl, QWidget *parent) + : QWidget(parent) +{ + setupUi(this); + + this->pgl = pgl; + model = pgl->getPortStatsModel(); + tvPortStats->setModel(model); + + tvPortStats->verticalHeader()->setHighlightSections(false); + tvPortStats->verticalHeader()->setDefaultSectionSize( + tvPortStats->verticalHeader()->minimumSectionSize()); + +} + +PortStatsWindow::~PortStatsWindow() +{ +} + +/* ------------- SLOTS -------------- */ + +void PortStatsWindow::on_tbStartTransmit_clicked() +{ + QList pgpl; + + // Get selected ports + model->portListFromIndex(tvPortStats->selectionModel()->selectedColumns(), + pgpl); + + // Clear selected ports, portgroup by portgroup + for (int i = 0; i < pgpl.size(); i++) + { + pgl->portGroupByIndex(pgpl.at(i).portGroupId). + startTx(&pgpl[i].portList); + } +} + +void PortStatsWindow::on_tbStopTransmit_clicked() +{ + QList pgpl; + + // Get selected ports + model->portListFromIndex(tvPortStats->selectionModel()->selectedColumns(), + pgpl); + + // Clear selected ports, portgroup by portgroup + for (int i = 0; i < pgpl.size(); i++) + { + pgl->portGroupByIndex(pgpl.at(i).portGroupId). + stopTx(&pgpl[i].portList); + } +} + +void PortStatsWindow::on_tbStartCapture_clicked() +{ + // TODO(MED) + QList pgpl; + + // Get selected ports + model->portListFromIndex(tvPortStats->selectionModel()->selectedColumns(), + pgpl); + + // Clear selected ports, portgroup by portgroup + for (int i = 0; i < pgpl.size(); i++) + { + pgl->portGroupByIndex(pgpl.at(i).portGroupId). + startCapture(&pgpl[i].portList); + } +} + +void PortStatsWindow::on_tbStopCapture_clicked() +{ + // TODO(MED) + QList pgpl; + + // Get selected ports + model->portListFromIndex(tvPortStats->selectionModel()->selectedColumns(), + pgpl); + + // Clear selected ports, portgroup by portgroup + for (int i = 0; i < pgpl.size(); i++) + { + pgl->portGroupByIndex(pgpl.at(i).portGroupId). + stopCapture(&pgpl[i].portList); + } +} + +void PortStatsWindow::on_tbViewCapture_clicked() +{ + // TODO(MED) + QList pgpl; + + // Get selected ports + model->portListFromIndex(tvPortStats->selectionModel()->selectedColumns(), + pgpl); + + // Clear selected ports, portgroup by portgroup + for (int i = 0; i < pgpl.size(); i++) + { + pgl->portGroupByIndex(pgpl.at(i).portGroupId). + viewCapture(&pgpl[i].portList); + } +} + +void PortStatsWindow::on_tbClear_clicked() +{ + QList portList; + + // Get selected ports + model->portListFromIndex(tvPortStats->selectionModel()->selectedColumns(), + portList); + + // Clear selected ports, portgroup by portgroup + for (int i = 0; i < portList.size(); i++) + { + pgl->portGroupByIndex(portList.at(i).portGroupId). + clearPortStats(&portList[i].portList); + } +} + +void PortStatsWindow::on_tbClearAll_clicked() +{ + for (int i = 0; i < pgl->numPortGroups(); i++) + { + pgl->portGroupByIndex(0).clearPortStats(); + } +} + +void PortStatsWindow::on_tbFilter_clicked() +{ + bool ok; + QList 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) + { + // hide/show sections first ... + for(int i = 0; i < model->columnCount(); i++) + tvPortStats->setColumnHidden(i, !newColumns.contains(i)); + + // ... then for the 'shown' columns, set the visual index + for(int i = 0; i < newColumns.size(); i++) + { + tvPortStats->horizontalHeader()->moveSection(tvPortStats-> + horizontalHeader()->visualIndex(newColumns.at(i)), i); + } + } +} diff --git a/client/portstatswindow.h b/client/portstatswindow.h index a390446..b2ad6f2 100644 --- a/client/portstatswindow.h +++ b/client/portstatswindow.h @@ -1,37 +1,37 @@ -#ifndef _PORT_STATS_WINDOW_H -#define _PORT_STATS_WINDOW_H - -#include -#include -#include "ui_portstatswindow.h" -#include "portgrouplist.h" -#include "portstatsmodel.h" - -class PortStatsWindow : public QWidget, public Ui::PortStatsWindow -{ - Q_OBJECT - -public: - PortStatsWindow(PortGroupList *pgl, QWidget *parent = 0); - ~PortStatsWindow(); - -private: - PortGroupList *pgl; - PortStatsModel *model; - -private slots: - void on_tbStartTransmit_clicked(); - void on_tbStopTransmit_clicked(); - - void on_tbStartCapture_clicked(); - void on_tbStopCapture_clicked(); - void on_tbViewCapture_clicked(); - - void on_tbClear_clicked(); - void on_tbClearAll_clicked(); - - void on_tbFilter_clicked(); -}; - -#endif - +#ifndef _PORT_STATS_WINDOW_H +#define _PORT_STATS_WINDOW_H + +#include +#include +#include "ui_portstatswindow.h" +#include "portgrouplist.h" +#include "portstatsmodel.h" + +class PortStatsWindow : public QWidget, public Ui::PortStatsWindow +{ + Q_OBJECT + +public: + PortStatsWindow(PortGroupList *pgl, QWidget *parent = 0); + ~PortStatsWindow(); + +private: + PortGroupList *pgl; + PortStatsModel *model; + +private slots: + void on_tbStartTransmit_clicked(); + void on_tbStopTransmit_clicked(); + + void on_tbStartCapture_clicked(); + void on_tbStopCapture_clicked(); + void on_tbViewCapture_clicked(); + + void on_tbClear_clicked(); + void on_tbClearAll_clicked(); + + void on_tbFilter_clicked(); +}; + +#endif + diff --git a/client/portswindow.cpp b/client/portswindow.cpp index 23684db..c8dd179 100644 --- a/client/portswindow.cpp +++ b/client/portswindow.cpp @@ -1,416 +1,416 @@ -#include "portswindow.h" -#include "streamlistdelegate.h" -#include "streamconfigdialog.h" -#include -#include - -PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent) -{ - StreamListDelegate *delegate = new StreamListDelegate; - //slm = new StreamListModel(); - //plm = new PortGroupList(); - plm = pgl; - - setupUi(this); - - tvStreamList->setItemDelegate(delegate); - - tvStreamList->verticalHeader()->setDefaultSectionSize( - tvStreamList->verticalHeader()->minimumSectionSize()); - - // Populate Context Menu Actions - tvPortList->addAction(actionNew_Port_Group); - tvPortList->addAction(actionDelete_Port_Group); - tvPortList->addAction(actionConnect_Port_Group); - tvPortList->addAction(actionDisconnect_Port_Group); - - tvStreamList->addAction(actionNew_Stream); - tvStreamList->addAction(actionEdit_Stream); - tvStreamList->addAction(actionDelete_Stream); - - tvStreamList->setModel(plm->getStreamModel()); - tvPortList->setModel(plm->getPortModel()); - - connect( plm->getPortModel(), - SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), - this, SLOT(when_portModel_dataChanged(const QModelIndex&, - const QModelIndex&))); - - connect(plm->getPortModel(), SIGNAL(modelReset()), - SLOT(when_portModel_reset())); - - connect( tvPortList->selectionModel(), - SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), - this, SLOT(when_portView_currentChanged(const QModelIndex&, - const QModelIndex&))); - - connect( tvStreamList->selectionModel(), - SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), - this, SLOT(when_streamView_currentChanged(const QModelIndex&, - const QModelIndex&))); - connect( tvStreamList->selectionModel(), - SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), - this, SLOT(when_streamView_selectionChanged())); - -#if 0 - connect( tvPortList->selectionModel(), - SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), - plm->getStreamModel(), SLOT(setCurrentPortIndex(const QModelIndex&))); -#endif - - tvStreamList->resizeColumnToContents(StreamModel::StreamIcon); - tvStreamList->resizeColumnToContents(StreamModel::StreamStatus); - - // Initially we don't have any ports/streams - so send signal triggers - when_portView_currentChanged(QModelIndex(), QModelIndex()); - when_streamView_currentChanged(QModelIndex(), QModelIndex()); - - //! \todo Hide the Aggregate Box till we add support - frAggregate->setHidden(true); -} - -PortsWindow::~PortsWindow() -{ -} - -void PortsWindow::on_tvStreamList_activated(const QModelIndex & index) -{ - StreamConfigDialog *scd; - - if (!index.isValid()) - { - qDebug("%s: invalid index", __FUNCTION__); - return; - } - scd = new StreamConfigDialog(plm->port(tvPortList->currentIndex()), - index.row(), this); - qDebug("stream list activated\n"); - scd->exec(); // TODO: chk retval - delete scd; -} - -void PortsWindow::when_portView_currentChanged(const QModelIndex& current, - const QModelIndex& previous) -{ - plm->getStreamModel()->setCurrentPortIndex(current); - updatePortViewActions(current); - updateStreamViewActions(); - - if (!current.isValid()) - { - qDebug("setting stacked widget to blank page"); - swDetail->setCurrentIndex(2); // blank page - } - else - { - if (plm->isPortGroup(current)) - { - swDetail->setCurrentIndex(1); // portGroup detail page - } - else if (plm->isPort(current)) - { - swDetail->setCurrentIndex(0); // port detail page - } - } -} - -void PortsWindow::when_streamView_currentChanged(const QModelIndex& current, - const QModelIndex& previous) -{ - qDebug("stream view current changed"); - updateStreamViewActions(); -} - -void PortsWindow::when_streamView_selectionChanged() -{ - qDebug("stream view selection changed"); - updateStreamViewActions(); -} - -void PortsWindow::when_portModel_dataChanged(const QModelIndex& topLeft, - const QModelIndex& bottomRight) -{ -#if 0 // not sure why the >= <= operators are not overloaded in QModelIndex - if ((tvPortList->currentIndex() >= topLeft) && - (tvPortList->currentIndex() <= bottomRight)) -#endif - if ((topLeft < tvPortList->currentIndex()) || - (topLeft == tvPortList->currentIndex()) && - ((tvPortList->currentIndex() < bottomRight)) || - (tvPortList->currentIndex() == bottomRight)) - { - updatePortViewActions(tvPortList->currentIndex()); - } -} - -void PortsWindow::when_portModel_reset() -{ - when_portView_currentChanged(QModelIndex(), tvPortList->currentIndex()); -} - -#if 0 -void PortsWindow::updateStreamViewActions(const QModelIndex& current) -{ - if (current.isValid()) - actionDelete_Stream->setEnabled(true); - else - actionDelete_Stream->setDisabled(true); -} -#endif - -void PortsWindow::updateStreamViewActions() -{ - // For some reason hasSelection() returns true even if selection size is 0 - // so additional check for size introduced - if (tvStreamList->selectionModel()->hasSelection() && - (tvStreamList->selectionModel()->selection().size() > 0)) - { - qDebug("Has selection %d", - tvStreamList->selectionModel()->selection().size()); - - // If more than one non-contiguous ranges selected, - // disable "New" and "Edit" - if (tvStreamList->selectionModel()->selection().size() > 1) - { - actionNew_Stream->setDisabled(true); - actionEdit_Stream->setDisabled(true); - } - else - { - actionNew_Stream->setEnabled(true); - - // Enable "Edit" only if the single range has a single row - if (tvStreamList->selectionModel()->selection().at(0).height() > 1) - actionEdit_Stream->setDisabled(true); - else - actionEdit_Stream->setEnabled(true); - } - - // Delete is always enabled as long as we have a selection - actionDelete_Stream->setEnabled(true); - } - else - { - qDebug("No selection"); - actionNew_Stream->setEnabled(true); - actionEdit_Stream->setDisabled(true); - actionDelete_Stream->setDisabled(true); - } -} - -void PortsWindow::updatePortViewActions(const QModelIndex& current) -{ - if (!current.isValid()) - { - qDebug("current is now invalid"); - actionDelete_Port_Group->setDisabled(true); - actionConnect_Port_Group->setDisabled(true); - actionDisconnect_Port_Group->setDisabled(true); - - goto _EXIT; - } - - qDebug("currentChanged %llx", current.internalId()); - - if (plm->isPortGroup(current)) - { - actionDelete_Port_Group->setEnabled(true); - switch(plm->portGroup(current).state()) - { - case QAbstractSocket::UnconnectedState: - case QAbstractSocket::ClosingState: - qDebug("state = unconnected|closing"); - actionConnect_Port_Group->setEnabled(true); - actionDisconnect_Port_Group->setDisabled(true); - break; - - case QAbstractSocket::HostLookupState: - case QAbstractSocket::ConnectingState: - case QAbstractSocket::ConnectedState: - qDebug("state = lookup|connecting|connected"); - actionConnect_Port_Group->setDisabled(true); - actionDisconnect_Port_Group->setEnabled(true); - break; - - - case QAbstractSocket::BoundState: - case QAbstractSocket::ListeningState: - default: - // FIXME(LOW): indicate error - qDebug("unexpected state"); - break; - } - } - else if (plm->isPort(current)) - { - actionDelete_Port_Group->setEnabled(false); - actionConnect_Port_Group->setEnabled(false); - actionDisconnect_Port_Group->setEnabled(false); - } - -_EXIT: - return; -} - -void PortsWindow::on_pbApply_clicked() -{ - QModelIndex curPort; - QModelIndex curPortGroup; - - curPort = tvPortList->selectionModel()->currentIndex(); - if (!curPort.isValid()) - { - qDebug("%s: curPort is invalid", __FUNCTION__); - goto _exit; - } - - if (!plm->isPort(curPort)) - { - qDebug("%s: curPort is not a port", __FUNCTION__); - goto _exit; - } - - curPortGroup = plm->getPortModel()->parent(curPort); - if (!curPortGroup.isValid()) - { - qDebug("%s: curPortGroup is invalid", __FUNCTION__); - goto _exit; - } - if (!plm->isPortGroup(curPortGroup)) - { - qDebug("%s: curPortGroup is not a portGroup", __FUNCTION__); - goto _exit; - } - - // FIXME(HI): shd this be a signal? - //portGroup.when_configApply(port); - // FIXME(MED): mixing port id and index!!! - plm->portGroup(curPortGroup).when_configApply(plm->port(curPort).id()); - -_exit: - return; - -#if 0 - // TODO (LOW): This block is for testing only - QModelIndex current = tvPortList->selectionModel()->currentIndex(); - - if (current.isValid()) - qDebug("current = %llx", current.internalId()); - else - qDebug("current is invalid"); -#endif -} - -void PortsWindow::on_actionNew_Port_Group_triggered() -{ - bool ok; - QString text = QInputDialog::getText(this, - "Add Port Group", "Port Group Address (IP[:Port])", - QLineEdit::Normal, lastNewPortGroup, &ok); - - if (ok) - { - QStringList addr = text.split(":"); - if (addr.size() == 1) // Port unspecified - addr.append(QString().setNum(DEFAULT_SERVER_PORT)); - PortGroup *pg = new PortGroup(QHostAddress(addr[0]),addr[1].toUShort()); - plm->addPortGroup(*pg); - lastNewPortGroup = text; - } -} - -void PortsWindow::on_actionDelete_Port_Group_triggered() -{ - QModelIndex current = tvPortList->selectionModel()->currentIndex(); - - if (current.isValid()) - plm->removePortGroup(plm->portGroup(current)); -} - -void PortsWindow::on_actionConnect_Port_Group_triggered() -{ - QModelIndex current = tvPortList->selectionModel()->currentIndex(); - - if (current.isValid()) - plm->portGroup(current).connectToHost(); -} - -void PortsWindow::on_actionDisconnect_Port_Group_triggered() -{ - QModelIndex current = tvPortList->selectionModel()->currentIndex(); - - if (current.isValid()) - plm->portGroup(current).disconnectFromHost(); -} -#if 0 -void PortsWindow::on_actionNew_Stream_triggered() -{ - qDebug("New Stream Action"); - - int row = 0; - - if (tvStreamList->currentIndex().isValid()) - row = tvStreamList->currentIndex().row(); - plm->getStreamModel()->insertRows(row, 1); -} - -void PortsWindow::on_actionDelete_Stream_triggered() -{ - qDebug("Delete Stream Action"); - if (tvStreamList->currentIndex().isValid()) - plm->getStreamModel()->removeRows(tvStreamList->currentIndex().row(), 1); -} -#endif - -void PortsWindow::on_actionNew_Stream_triggered() -{ - qDebug("New Stream Action"); - - // In case nothing is selected, insert 1 row at the top - int row = 0, count = 1; - - // In case we have a single range selected; insert as many rows as - // in the singe selected range before the top of the selected range - if (tvStreamList->selectionModel()->selection().size() == 1) - { - row = tvStreamList->selectionModel()->selection().at(0).top(); - count = tvStreamList->selectionModel()->selection().at(0).height(); - } - - plm->getStreamModel()->insertRows(row, count); -} - -void PortsWindow::on_actionEdit_Stream_triggered() -{ - qDebug("Edit Stream Action"); - - // Ensure we have only one range selected which contains only one row - if ((tvStreamList->selectionModel()->selection().size() == 1) && - (tvStreamList->selectionModel()->selection().at(0).height() == 1)) - { - on_tvStreamList_activated(tvStreamList->selectionModel()-> - selection().at(0).topLeft()); - } -} - -void PortsWindow::on_actionDelete_Stream_triggered() -{ - qDebug("Delete Stream Action"); - - QModelIndex index; - - if (tvStreamList->selectionModel()->hasSelection()) - { - qDebug("SelectedIndexes %d", - tvStreamList->selectionModel()->selectedRows().size()); - while(tvStreamList->selectionModel()->selectedRows().size()) - { - index = tvStreamList->selectionModel()->selectedRows().at(0); - plm->getStreamModel()->removeRows(index.row(), 1); - } - } - else - qDebug("No selection"); -} - - +#include "portswindow.h" +#include "streamlistdelegate.h" +#include "streamconfigdialog.h" +#include +#include + +PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent) +{ + StreamListDelegate *delegate = new StreamListDelegate; + //slm = new StreamListModel(); + //plm = new PortGroupList(); + plm = pgl; + + setupUi(this); + + tvStreamList->setItemDelegate(delegate); + + tvStreamList->verticalHeader()->setDefaultSectionSize( + tvStreamList->verticalHeader()->minimumSectionSize()); + + // Populate Context Menu Actions + tvPortList->addAction(actionNew_Port_Group); + tvPortList->addAction(actionDelete_Port_Group); + tvPortList->addAction(actionConnect_Port_Group); + tvPortList->addAction(actionDisconnect_Port_Group); + + tvStreamList->addAction(actionNew_Stream); + tvStreamList->addAction(actionEdit_Stream); + tvStreamList->addAction(actionDelete_Stream); + + tvStreamList->setModel(plm->getStreamModel()); + tvPortList->setModel(plm->getPortModel()); + + connect( plm->getPortModel(), + SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), + this, SLOT(when_portModel_dataChanged(const QModelIndex&, + const QModelIndex&))); + + connect(plm->getPortModel(), SIGNAL(modelReset()), + SLOT(when_portModel_reset())); + + connect( tvPortList->selectionModel(), + SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), + this, SLOT(when_portView_currentChanged(const QModelIndex&, + const QModelIndex&))); + + connect( tvStreamList->selectionModel(), + SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), + this, SLOT(when_streamView_currentChanged(const QModelIndex&, + const QModelIndex&))); + connect( tvStreamList->selectionModel(), + SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), + this, SLOT(when_streamView_selectionChanged())); + +#if 0 + connect( tvPortList->selectionModel(), + SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), + plm->getStreamModel(), SLOT(setCurrentPortIndex(const QModelIndex&))); +#endif + + tvStreamList->resizeColumnToContents(StreamModel::StreamIcon); + tvStreamList->resizeColumnToContents(StreamModel::StreamStatus); + + // Initially we don't have any ports/streams - so send signal triggers + when_portView_currentChanged(QModelIndex(), QModelIndex()); + when_streamView_currentChanged(QModelIndex(), QModelIndex()); + + //! \todo Hide the Aggregate Box till we add support + frAggregate->setHidden(true); +} + +PortsWindow::~PortsWindow() +{ +} + +void PortsWindow::on_tvStreamList_activated(const QModelIndex & index) +{ + StreamConfigDialog *scd; + + if (!index.isValid()) + { + qDebug("%s: invalid index", __FUNCTION__); + return; + } + scd = new StreamConfigDialog(plm->port(tvPortList->currentIndex()), + index.row(), this); + qDebug("stream list activated\n"); + scd->exec(); // TODO: chk retval + delete scd; +} + +void PortsWindow::when_portView_currentChanged(const QModelIndex& current, + const QModelIndex& previous) +{ + plm->getStreamModel()->setCurrentPortIndex(current); + updatePortViewActions(current); + updateStreamViewActions(); + + if (!current.isValid()) + { + qDebug("setting stacked widget to blank page"); + swDetail->setCurrentIndex(2); // blank page + } + else + { + if (plm->isPortGroup(current)) + { + swDetail->setCurrentIndex(1); // portGroup detail page + } + else if (plm->isPort(current)) + { + swDetail->setCurrentIndex(0); // port detail page + } + } +} + +void PortsWindow::when_streamView_currentChanged(const QModelIndex& current, + const QModelIndex& previous) +{ + qDebug("stream view current changed"); + updateStreamViewActions(); +} + +void PortsWindow::when_streamView_selectionChanged() +{ + qDebug("stream view selection changed"); + updateStreamViewActions(); +} + +void PortsWindow::when_portModel_dataChanged(const QModelIndex& topLeft, + const QModelIndex& bottomRight) +{ +#if 0 // not sure why the >= <= operators are not overloaded in QModelIndex + if ((tvPortList->currentIndex() >= topLeft) && + (tvPortList->currentIndex() <= bottomRight)) +#endif + if ((topLeft < tvPortList->currentIndex()) || + (topLeft == tvPortList->currentIndex()) && + ((tvPortList->currentIndex() < bottomRight)) || + (tvPortList->currentIndex() == bottomRight)) + { + updatePortViewActions(tvPortList->currentIndex()); + } +} + +void PortsWindow::when_portModel_reset() +{ + when_portView_currentChanged(QModelIndex(), tvPortList->currentIndex()); +} + +#if 0 +void PortsWindow::updateStreamViewActions(const QModelIndex& current) +{ + if (current.isValid()) + actionDelete_Stream->setEnabled(true); + else + actionDelete_Stream->setDisabled(true); +} +#endif + +void PortsWindow::updateStreamViewActions() +{ + // For some reason hasSelection() returns true even if selection size is 0 + // so additional check for size introduced + if (tvStreamList->selectionModel()->hasSelection() && + (tvStreamList->selectionModel()->selection().size() > 0)) + { + qDebug("Has selection %d", + tvStreamList->selectionModel()->selection().size()); + + // If more than one non-contiguous ranges selected, + // disable "New" and "Edit" + if (tvStreamList->selectionModel()->selection().size() > 1) + { + actionNew_Stream->setDisabled(true); + actionEdit_Stream->setDisabled(true); + } + else + { + actionNew_Stream->setEnabled(true); + + // Enable "Edit" only if the single range has a single row + if (tvStreamList->selectionModel()->selection().at(0).height() > 1) + actionEdit_Stream->setDisabled(true); + else + actionEdit_Stream->setEnabled(true); + } + + // Delete is always enabled as long as we have a selection + actionDelete_Stream->setEnabled(true); + } + else + { + qDebug("No selection"); + actionNew_Stream->setEnabled(true); + actionEdit_Stream->setDisabled(true); + actionDelete_Stream->setDisabled(true); + } +} + +void PortsWindow::updatePortViewActions(const QModelIndex& current) +{ + if (!current.isValid()) + { + qDebug("current is now invalid"); + actionDelete_Port_Group->setDisabled(true); + actionConnect_Port_Group->setDisabled(true); + actionDisconnect_Port_Group->setDisabled(true); + + goto _EXIT; + } + + qDebug("currentChanged %llx", current.internalId()); + + if (plm->isPortGroup(current)) + { + actionDelete_Port_Group->setEnabled(true); + switch(plm->portGroup(current).state()) + { + case QAbstractSocket::UnconnectedState: + case QAbstractSocket::ClosingState: + qDebug("state = unconnected|closing"); + actionConnect_Port_Group->setEnabled(true); + actionDisconnect_Port_Group->setDisabled(true); + break; + + case QAbstractSocket::HostLookupState: + case QAbstractSocket::ConnectingState: + case QAbstractSocket::ConnectedState: + qDebug("state = lookup|connecting|connected"); + actionConnect_Port_Group->setDisabled(true); + actionDisconnect_Port_Group->setEnabled(true); + break; + + + case QAbstractSocket::BoundState: + case QAbstractSocket::ListeningState: + default: + // FIXME(LOW): indicate error + qDebug("unexpected state"); + break; + } + } + else if (plm->isPort(current)) + { + actionDelete_Port_Group->setEnabled(false); + actionConnect_Port_Group->setEnabled(false); + actionDisconnect_Port_Group->setEnabled(false); + } + +_EXIT: + return; +} + +void PortsWindow::on_pbApply_clicked() +{ + QModelIndex curPort; + QModelIndex curPortGroup; + + curPort = tvPortList->selectionModel()->currentIndex(); + if (!curPort.isValid()) + { + qDebug("%s: curPort is invalid", __FUNCTION__); + goto _exit; + } + + if (!plm->isPort(curPort)) + { + qDebug("%s: curPort is not a port", __FUNCTION__); + goto _exit; + } + + curPortGroup = plm->getPortModel()->parent(curPort); + if (!curPortGroup.isValid()) + { + qDebug("%s: curPortGroup is invalid", __FUNCTION__); + goto _exit; + } + if (!plm->isPortGroup(curPortGroup)) + { + qDebug("%s: curPortGroup is not a portGroup", __FUNCTION__); + goto _exit; + } + + // FIXME(HI): shd this be a signal? + //portGroup.when_configApply(port); + // FIXME(MED): mixing port id and index!!! + plm->portGroup(curPortGroup).when_configApply(plm->port(curPort).id()); + +_exit: + return; + +#if 0 + // TODO (LOW): This block is for testing only + QModelIndex current = tvPortList->selectionModel()->currentIndex(); + + if (current.isValid()) + qDebug("current = %llx", current.internalId()); + else + qDebug("current is invalid"); +#endif +} + +void PortsWindow::on_actionNew_Port_Group_triggered() +{ + bool ok; + QString text = QInputDialog::getText(this, + "Add Port Group", "Port Group Address (IP[:Port])", + QLineEdit::Normal, lastNewPortGroup, &ok); + + if (ok) + { + QStringList addr = text.split(":"); + if (addr.size() == 1) // Port unspecified + addr.append(QString().setNum(DEFAULT_SERVER_PORT)); + PortGroup *pg = new PortGroup(QHostAddress(addr[0]),addr[1].toUShort()); + plm->addPortGroup(*pg); + lastNewPortGroup = text; + } +} + +void PortsWindow::on_actionDelete_Port_Group_triggered() +{ + QModelIndex current = tvPortList->selectionModel()->currentIndex(); + + if (current.isValid()) + plm->removePortGroup(plm->portGroup(current)); +} + +void PortsWindow::on_actionConnect_Port_Group_triggered() +{ + QModelIndex current = tvPortList->selectionModel()->currentIndex(); + + if (current.isValid()) + plm->portGroup(current).connectToHost(); +} + +void PortsWindow::on_actionDisconnect_Port_Group_triggered() +{ + QModelIndex current = tvPortList->selectionModel()->currentIndex(); + + if (current.isValid()) + plm->portGroup(current).disconnectFromHost(); +} +#if 0 +void PortsWindow::on_actionNew_Stream_triggered() +{ + qDebug("New Stream Action"); + + int row = 0; + + if (tvStreamList->currentIndex().isValid()) + row = tvStreamList->currentIndex().row(); + plm->getStreamModel()->insertRows(row, 1); +} + +void PortsWindow::on_actionDelete_Stream_triggered() +{ + qDebug("Delete Stream Action"); + if (tvStreamList->currentIndex().isValid()) + plm->getStreamModel()->removeRows(tvStreamList->currentIndex().row(), 1); +} +#endif + +void PortsWindow::on_actionNew_Stream_triggered() +{ + qDebug("New Stream Action"); + + // In case nothing is selected, insert 1 row at the top + int row = 0, count = 1; + + // In case we have a single range selected; insert as many rows as + // in the singe selected range before the top of the selected range + if (tvStreamList->selectionModel()->selection().size() == 1) + { + row = tvStreamList->selectionModel()->selection().at(0).top(); + count = tvStreamList->selectionModel()->selection().at(0).height(); + } + + plm->getStreamModel()->insertRows(row, count); +} + +void PortsWindow::on_actionEdit_Stream_triggered() +{ + qDebug("Edit Stream Action"); + + // Ensure we have only one range selected which contains only one row + if ((tvStreamList->selectionModel()->selection().size() == 1) && + (tvStreamList->selectionModel()->selection().at(0).height() == 1)) + { + on_tvStreamList_activated(tvStreamList->selectionModel()-> + selection().at(0).topLeft()); + } +} + +void PortsWindow::on_actionDelete_Stream_triggered() +{ + qDebug("Delete Stream Action"); + + QModelIndex index; + + if (tvStreamList->selectionModel()->hasSelection()) + { + qDebug("SelectedIndexes %d", + tvStreamList->selectionModel()->selectedRows().size()); + while(tvStreamList->selectionModel()->selectedRows().size()) + { + index = tvStreamList->selectionModel()->selectedRows().at(0); + plm->getStreamModel()->removeRows(index.row(), 1); + } + } + else + qDebug("No selection"); +} + + diff --git a/client/portswindow.h b/client/portswindow.h index aec7216..c6db222 100644 --- a/client/portswindow.h +++ b/client/portswindow.h @@ -1,58 +1,58 @@ -#ifndef _PORTS_WINDOW_H -#define _PORTS_WINDOW_H - -#include -#include -#include "ui_portswindow.h" -#include "portgrouplist.h" - -/* TODO -HIGH -MED -LOW -*/ - - -class PortsWindow : public QWidget, private Ui::PortsWindow -{ - Q_OBJECT - - //QAbstractItemModel *slm; // stream list model - PortGroupList *plm; - -public: - PortsWindow(PortGroupList *pgl, QWidget *parent = 0); - ~PortsWindow(); - -private: - QString lastNewPortGroup; - - void updatePortViewActions(const QModelIndex& current); - //void updateStreamViewActions(const QModelIndex& current); - void updateStreamViewActions(); - -private slots: - void on_tvStreamList_activated(const QModelIndex & index); - void when_portView_currentChanged(const QModelIndex& current, - const QModelIndex& previous); - void when_streamView_currentChanged(const QModelIndex& current, - const QModelIndex& previous); - void when_streamView_selectionChanged(); - void when_portModel_dataChanged(const QModelIndex& topLeft, - const QModelIndex& bottomRight); - void when_portModel_reset(); - - void on_pbApply_clicked(); - - void on_actionNew_Port_Group_triggered(); - void on_actionDelete_Port_Group_triggered(); - void on_actionConnect_Port_Group_triggered(); - void on_actionDisconnect_Port_Group_triggered(); - - void on_actionNew_Stream_triggered(); - void on_actionEdit_Stream_triggered(); - void on_actionDelete_Stream_triggered(); -}; - -#endif - +#ifndef _PORTS_WINDOW_H +#define _PORTS_WINDOW_H + +#include +#include +#include "ui_portswindow.h" +#include "portgrouplist.h" + +/* TODO +HIGH +MED +LOW +*/ + + +class PortsWindow : public QWidget, private Ui::PortsWindow +{ + Q_OBJECT + + //QAbstractItemModel *slm; // stream list model + PortGroupList *plm; + +public: + PortsWindow(PortGroupList *pgl, QWidget *parent = 0); + ~PortsWindow(); + +private: + QString lastNewPortGroup; + + void updatePortViewActions(const QModelIndex& current); + //void updateStreamViewActions(const QModelIndex& current); + void updateStreamViewActions(); + +private slots: + void on_tvStreamList_activated(const QModelIndex & index); + void when_portView_currentChanged(const QModelIndex& current, + const QModelIndex& previous); + void when_streamView_currentChanged(const QModelIndex& current, + const QModelIndex& previous); + void when_streamView_selectionChanged(); + void when_portModel_dataChanged(const QModelIndex& topLeft, + const QModelIndex& bottomRight); + void when_portModel_reset(); + + void on_pbApply_clicked(); + + void on_actionNew_Port_Group_triggered(); + void on_actionDelete_Port_Group_triggered(); + void on_actionConnect_Port_Group_triggered(); + void on_actionDisconnect_Port_Group_triggered(); + + void on_actionNew_Stream_triggered(); + void on_actionEdit_Stream_triggered(); + void on_actionDelete_Stream_triggered(); +}; + +#endif + diff --git a/client/stream.cpp b/client/stream.cpp index 049d554..7d21b14 100644 --- a/client/stream.cpp +++ b/client/stream.cpp @@ -1,60 +1,60 @@ -#include -#include - -#include "stream.h" -//#include "../common/protocollist.h" -#include "../common/protocollistiterator.h" -#include "../common/abstractprotocol.h" - -Stream::Stream() -{ - //mId = 0xFFFFFFFF; - setEnabled(true); -} - -Stream::~Stream() -{ -} - -void Stream::loadProtocolWidgets() -{ -#if 0 - //protocols.loadConfigWidgets(); - foreach(AbstractProtocol* proto, *currentFrameProtocols) - { - proto->loadConfigWidget(); - } -#else - ProtocolListIterator *iter; - - iter = createProtocolListIterator(); - while (iter->hasNext()) - { - AbstractProtocol* p = iter->next(); - p->loadConfigWidget(); - } - delete iter; -#endif -} - -void Stream::storeProtocolWidgets() -{ -#if 0 - //protocols.storeConfigWidgets(); - foreach(const AbstractProtocol* proto, frameProtocol()) - { - proto->storeConfigWidget(); - _iter->toFront(); - } -#else - ProtocolListIterator *iter; - - iter = createProtocolListIterator(); - while (iter->hasNext()) - { - AbstractProtocol* p = iter->next(); - p->storeConfigWidget(); - } - delete iter; -#endif -} +#include +#include + +#include "stream.h" +//#include "../common/protocollist.h" +#include "../common/protocollistiterator.h" +#include "../common/abstractprotocol.h" + +Stream::Stream() +{ + //mId = 0xFFFFFFFF; + setEnabled(true); +} + +Stream::~Stream() +{ +} + +void Stream::loadProtocolWidgets() +{ +#if 0 + //protocols.loadConfigWidgets(); + foreach(AbstractProtocol* proto, *currentFrameProtocols) + { + proto->loadConfigWidget(); + } +#else + ProtocolListIterator *iter; + + iter = createProtocolListIterator(); + while (iter->hasNext()) + { + AbstractProtocol* p = iter->next(); + p->loadConfigWidget(); + } + delete iter; +#endif +} + +void Stream::storeProtocolWidgets() +{ +#if 0 + //protocols.storeConfigWidgets(); + foreach(const AbstractProtocol* proto, frameProtocol()) + { + proto->storeConfigWidget(); + _iter->toFront(); + } +#else + ProtocolListIterator *iter; + + iter = createProtocolListIterator(); + while (iter->hasNext()) + { + AbstractProtocol* p = iter->next(); + p->storeConfigWidget(); + } + delete iter; +#endif +} diff --git a/client/stream.h b/client/stream.h index 1b4e756..de7508d 100644 --- a/client/stream.h +++ b/client/stream.h @@ -1,23 +1,23 @@ -#ifndef _STREAM_H -#define _STREAM_H - -#include -#include -#include - -#include "../common/protocol.pb.h" -#include "../common/streambase.h" - -class Stream : public StreamBase { - - //quint32 mId; - -public: - Stream(); - ~Stream(); - - void loadProtocolWidgets(); - void storeProtocolWidgets(); -}; - -#endif +#ifndef _STREAM_H +#define _STREAM_H + +#include +#include +#include + +#include "../common/protocol.pb.h" +#include "../common/streambase.h" + +class Stream : public StreamBase { + + //quint32 mId; + +public: + Stream(); + ~Stream(); + + void loadProtocolWidgets(); + void storeProtocolWidgets(); +}; + +#endif diff --git a/client/streamconfigdialog.cpp b/client/streamconfigdialog.cpp index c6a950d..eb3da50 100644 --- a/client/streamconfigdialog.cpp +++ b/client/streamconfigdialog.cpp @@ -1,925 +1,925 @@ -#include - -#include "streamconfigdialog.h" -#include "stream.h" -#include "abstractprotocol.h" -#include "protocollistiterator.h" - -#include "modeltest.h" - -// FIXME(HI) - remove -#include "../common/protocolmanager.h" -extern ProtocolManager OstProtocolManager; - -int StreamConfigDialog::lastTopLevelTabIndex = 0; - -StreamConfigDialog::StreamConfigDialog(Port &port, uint streamIndex, - QWidget *parent) : QDialog (parent), mPort(port) -{ - OstProto::Stream s; - mCurrentStreamIndex = streamIndex; - mpStream = new Stream; - mPort.streamByIndex(mCurrentStreamIndex)->protoDataCopyInto(s); - mpStream->protoDataCopyFrom(s); - _iter = mpStream->createProtocolListIterator(); - isUpdateInProgress = false; - - setupUi(this); - setupUiExtra(); - - for (int i = ProtoMin; i < ProtoMax; i++) - { - bgProto[i]->setProperty("ProtocolLevel", i); - bgProto[i]->setProperty("ProtocolId", ButtonIdNone); - connect(bgProto[i], SIGNAL(buttonClicked(int)), - this, SLOT(updateProtocol(int))); - } - - //! \todo causes a crash! -#if 0 - connect(lePktLen, SIGNAL(textEdited(QString)), - this, SLOT(updateContents())); -#endif - - // Time to play match the signals and slots! - - // If L1/L2(FT)/L3 = None, force subsequent protocol level(s) also to None - connect(rbL1None, SIGNAL(toggled(bool)), SLOT(forceProtocolNone(bool))); - connect(rbFtNone, SIGNAL(toggled(bool)), SLOT(forceProtocolNone(bool))); - connect(rbL3None, SIGNAL(toggled(bool)), SLOT(forceProtocolNone(bool))); - - // If L1/L2(FT)/L3/L4 = Other, force subsequent protocol to Other and - // disable the subsequent protocol group as well - connect(rbL1Other, SIGNAL(toggled(bool)), rbFtOther, SLOT(setChecked(bool))); - connect(rbL1Other, SIGNAL(toggled(bool)), gbFrameType, SLOT(setDisabled(bool))); - connect(rbFtOther, SIGNAL(toggled(bool)), rbL3Other, SLOT(setChecked(bool))); - connect(rbFtOther, SIGNAL(toggled(bool)), gbL3Proto, SLOT(setDisabled(bool))); - connect(rbL3Other, SIGNAL(toggled(bool)), rbL4Other, SLOT(setChecked(bool))); - connect(rbL3Other, SIGNAL(toggled(bool)), gbL4Proto, SLOT(setDisabled(bool))); - connect(rbL4Other, SIGNAL(toggled(bool)), rbPayloadOther, SLOT(setChecked(bool))); - connect(rbL4Other, SIGNAL(toggled(bool)), gbPayloadProto, SLOT(setDisabled(bool))); - - // Setup valid subsequent protocols for L2 and L3 protocols - for (int i = ProtoL2; i <= ProtoL3; i++) - { - foreach(QAbstractButton *btn1, bgProto[i]->buttons()) - { - int id1 = bgProto[i]->id(btn1); - - if (id1 != ButtonIdNone && id1 != ButtonIdOther) - { - int validProtocolCount = 0; - - foreach(QAbstractButton *btn2, bgProto[i+1]->buttons()) - { - int id2 = bgProto[i+1]->id(btn2); - - if (id2 != ButtonIdNone && id2 != ButtonIdOther) - { - if (OstProtocolManager.isValidNeighbour(id1, id2)) - { - connect(btn1, SIGNAL(toggled(bool)), - btn2, SLOT(setEnabled(bool))); - validProtocolCount++; - } - else - connect(btn1, SIGNAL(toggled(bool)), - btn2, SLOT(setDisabled(bool))); - } - } - - // If btn1 has no subsequent valid protocols, - // force subsequent Protocol to 'None' - if (validProtocolCount == 0) - connect(btn1, SIGNAL(clicked(bool)), - bgProto[i+1]->button(ButtonIdNone), SLOT(click())); - } - } - } - - mpAvailableProtocolsModel = new QStringListModel( - OstProtocolManager.protocolDatabase(), this); - lvAllProtocols->setModel(mpAvailableProtocolsModel); - mpSelectedProtocolsModel = new QStringListModel(this); - lvSelectedProtocols->setModel(mpSelectedProtocolsModel); - - - connect(lvAllProtocols->selectionModel(), - SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), - this, SLOT(when_lvAllProtocols_selectionChanged( - const QItemSelection&, const QItemSelection&))); - connect(lvSelectedProtocols->selectionModel(), - SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), - this, SLOT(when_lvSelectedProtocols_currentChanged(const QModelIndex&, - const QModelIndex&))); - - LoadCurrentStream(); - mpPacketModel = new PacketModel(this); - tvPacketTree->setModel(mpPacketModel); - mpPacketModelTester = new ModelTest(mpPacketModel); - tvPacketTree->header()->hide(); - vwPacketDump->setModel(mpPacketModel); - vwPacketDump->setSelectionModel(tvPacketTree->selectionModel()); - - // TODO(MED): - - //! \todo Implement then enable these protocols - ARP, IPv6, ICMP, IGMP - rbL3Arp->setHidden(true); - rbL3Ipv6->setHidden(true); - rbL4Icmp->setHidden(true); - rbL4Igmp->setHidden(true); - //! \todo Enable navigation of streams - pbPrev->setDisabled(true); - pbNext->setDisabled(true); - //! \todo Support Goto Stream Id - leStreamId->setDisabled(true); - disconnect(rbActionGotoStream, SIGNAL(toggled(bool)), leStreamId, SLOT(setEnabled(bool))); - //! \todo Support Continuous Mode - rbModeContinuous->setDisabled(true); - - // Finally, restore the saved last selected tab for the various tab widgets - twTopLevel->setCurrentIndex(lastTopLevelTabIndex); -} - -void StreamConfigDialog::setupUiExtra() -{ - QRegExp reHex2B("[0-9,a-f,A-F]{1,4}"); - QRegExp reHex4B("[0-9,a-f,A-F]{1,8}"); - QRegExp reMac("([0-9,a-f,A-F]{2,2}[:-]){5,5}[0-9,a-f,A-F]{2,2}"); - - // ---- Setup default stuff that cannot be done in designer ---- - bgProto[ProtoL1] = new QButtonGroup(); - bgProto[ProtoL1]->addButton(rbL1None, ButtonIdNone); - bgProto[ProtoL1]->addButton(rbL1Mac, OstProto::Protocol::kMacFieldNumber); - bgProto[ProtoL1]->addButton(rbL1Other, ButtonIdOther); - - bgProto[ProtoL2] = new QButtonGroup(); -#if 0 - foreach(QRadioButton *btn, gbFrameType->findChildren()) - bgL2Proto->addButton(btn); -#else - bgProto[ProtoL2]->addButton(rbFtNone, ButtonIdNone); - bgProto[ProtoL2]->addButton(rbFtEthernet2, OstProto::Protocol::kEth2FieldNumber); - bgProto[ProtoL2]->addButton(rbFt802Dot3Raw, OstProto::Protocol::kDot3FieldNumber); - bgProto[ProtoL2]->addButton(rbFt802Dot3Llc, OstProto::Protocol::kDot2LlcFieldNumber); - bgProto[ProtoL2]->addButton(rbFtLlcSnap, OstProto::Protocol::kDot2SnapFieldNumber); - bgProto[ProtoL2]->addButton(rbFtOther, ButtonIdOther); -#endif - - bgProto[ProtoVlan] = new QButtonGroup(); - bgProto[ProtoVlan]->addButton(rbVlanNone, ButtonIdNone); - bgProto[ProtoVlan]->addButton(rbVlanSingle, OstProto::Protocol::kVlanFieldNumber); - bgProto[ProtoVlan]->addButton(rbVlanDouble, OstProto::Protocol::kVlanStackFieldNumber); - - bgProto[ProtoL3] = new QButtonGroup(); -#if 0 - foreach(QRadioButton *btn, gbL3Proto->findChildren()) - bgProto[ProtoL3]->addButton(btn); -#else - bgProto[ProtoL3]->addButton(rbL3None, ButtonIdNone); - bgProto[ProtoL3]->addButton(rbL3Ipv4, OstProto::Protocol::kIp4FieldNumber); - bgProto[ProtoL3]->addButton(rbL3Ipv6, 0xFFFF); - bgProto[ProtoL3]->addButton(rbL3Arp, 0xFFFF); - bgProto[ProtoL3]->addButton(rbL3Other, ButtonIdOther); -#endif - - bgProto[ProtoL4] = new QButtonGroup(); -#if 0 - foreach(QRadioButton *btn, gbL4Proto->findChildren()) - bgProto[ProtoL4]->addButton(btn); -#else - bgProto[ProtoL4]->addButton(rbL4None, 0); - bgProto[ProtoL4]->addButton(rbL4Tcp, OstProto::Protocol::kTcpFieldNumber); - bgProto[ProtoL4]->addButton(rbL4Udp, OstProto::Protocol::kUdpFieldNumber); - bgProto[ProtoL4]->addButton(rbL4Icmp, 0xFFFF); - bgProto[ProtoL4]->addButton(rbL4Igmp, 0xFFFF); - bgProto[ProtoL4]->addButton(rbL4Other, ButtonIdOther); -#endif - - bgProto[ProtoPayload] = new QButtonGroup(); -#if 0 - foreach(QRadioButton *btn, gbPayloadProto->findChildren()) - bgProto[ProtoPayload]->addButton(btn); -#else - bgProto[ProtoPayload]->addButton(rbPayloadNone, ButtonIdNone); - bgProto[ProtoPayload]->addButton(rbPayloadPattern, OstProto::Protocol::kPayloadFieldNumber); - bgProto[ProtoPayload]->addButton(rbPayloadOther, ButtonIdOther); -#endif - /* - ** Setup Validators - */ - // Meta Data - //! \todo - doesn't seem to work - range validator needs a spinbox? - //lePktLen->setValidator(new QIntValidator(MIN_PKT_LEN, MAX_PKT_LEN, this)); - - /* - ** Setup Connections - */ - connect(rbSendPackets, SIGNAL(toggled(bool)), - this, SLOT(update_NumPacketsAndNumBursts())); - connect(rbSendBursts, SIGNAL(toggled(bool)), - this, SLOT(update_NumPacketsAndNumBursts())); - connect(rbModeFixed, SIGNAL(toggled(bool)), - this, SLOT(update_NumPacketsAndNumBursts())); - connect(rbModeContinuous, SIGNAL(toggled(bool)), - this, SLOT(update_NumPacketsAndNumBursts())); - -} - -StreamConfigDialog::~StreamConfigDialog() -{ - delete mpPacketModelTester; - delete mpPacketModel; - - for (int i = ProtoMin; i < ProtoMax; i++) - delete bgProto[i]; - - delete _iter; - delete mpStream; -} - -void StreamConfigDialog::on_cmbPktLenMode_currentIndexChanged(QString mode) -{ - if (mode == "Fixed") - { - lePktLen->setEnabled(true); - lePktLenMin->setDisabled(true); - lePktLenMax->setDisabled(true); - } - else if (mode == "Increment") - { - lePktLen->setDisabled(true); - lePktLenMin->setEnabled(true); - lePktLenMax->setEnabled(true); - } - else if (mode == "Decrement") - { - lePktLen->setDisabled(true); - lePktLenMin->setEnabled(true); - lePktLenMax->setEnabled(true); - } - else if (mode == "Random") - { - lePktLen->setDisabled(true); - lePktLenMin->setEnabled(true); - lePktLenMax->setEnabled(true); - } - else - { - qWarning("Unhandled/Unknown PktLenMode = %s", mode.toAscii().data()); - } -} - -void StreamConfigDialog::on_pbPrev_clicked() -{ -#if 0 - StoreCurrentStream(currStreamIdx); - currStreamIdx--; - LoadCurrentStream(currStreamIdx); - - pbPrev->setDisabled((currStreamIdx == 0)); - pbNext->setDisabled((currStreamIdx == 2)); -#endif -} - -void StreamConfigDialog::on_pbNext_clicked() -{ -#if 0 - StoreCurrentStream(currStreamIdx); - currStreamIdx++; - LoadCurrentStream(currStreamIdx); - - pbPrev->setDisabled((currStreamIdx == 0)); - pbNext->setDisabled((currStreamIdx == 2)); -#endif -} - -void StreamConfigDialog::on_tbSelectProtocols_currentChanged(int index) -{ - qDebug("%s, index = %d", __FUNCTION__, index); - switch (index) - { - case 0: - updateSelectProtocolsSimpleWidget(); - break; - case 1: - updateSelectProtocolsAdvancedWidget(); - break; - default: - qFatal("%s: unexpected index = %d", __FUNCTION__, index); - } -} - -void StreamConfigDialog::when_lvAllProtocols_selectionChanged( - const QItemSelection &selected, const QItemSelection &deselected) -{ - int size = lvAllProtocols->selectionModel()->selectedIndexes().size(); - - qDebug("%s: selected.indexes().size = %d\n", __FUNCTION__, size); - - tbAdd->setEnabled(size > 0); -} - -void StreamConfigDialog::when_lvSelectedProtocols_currentChanged( - const QModelIndex ¤t, const QModelIndex &previous) -{ - qDebug("%s: currentRow = %d\n", __FUNCTION__, current.row()); - - tbDelete->setEnabled(current.isValid()); - tbUp->setEnabled(current.isValid() && (current.row() != 0)); - tbDown->setEnabled(current.isValid() && - (current.row() != (current.model()->rowCount() - 1))); -} - -void StreamConfigDialog::on_tbAdd_clicked() -{ - int n = 0; - QModelIndex idx2; - AbstractProtocol *p; - QModelIndexList selection; - - selection = lvAllProtocols->selectionModel()->selectedIndexes(); - - // Validation - if (selection.size() == 0) - return; - - idx2 = lvSelectedProtocols->currentIndex(); - if (idx2.isValid()) - n = idx2.row(); - - _iter->toFront(); - while (n--) - { - if (!_iter->hasNext()) - return; - - p = _iter->next(); - } - - foreach(QModelIndex idx, selection) - _iter->insert(OstProtocolManager.createProtocol( - mpAvailableProtocolsModel->stringList().at(idx.row()), mpStream)); - - updateSelectProtocolsAdvancedWidget(); - lvSelectedProtocols->setCurrentIndex(idx2); -} - -void StreamConfigDialog::on_tbDelete_clicked() -{ - int n; - QModelIndex idx; - AbstractProtocol *p; - - idx = lvSelectedProtocols->currentIndex(); - - // Validation - if (!idx.isValid()) - return; - - n = idx.row() + 1; - - _iter->toFront(); - while (n--) - { - if (!_iter->hasNext()) - return; - - p = _iter->next(); - } - - _iter->remove(); - delete p; - - updateSelectProtocolsAdvancedWidget(); - lvSelectedProtocols->setCurrentIndex(idx); -} - -void StreamConfigDialog::on_tbUp_clicked() -{ - int m, n; - QModelIndex idx; - AbstractProtocol *p; - - idx = lvSelectedProtocols->currentIndex(); - - // Validation - if (!idx.isValid() || idx.row() == 0) - return; - - m = n = idx.row() + 1; - - _iter->toFront(); - while (n--) - { - if (!_iter->hasNext()) - return; - - p = _iter->next(); - } - - _iter->remove(); - _iter->previous(); - _iter->insert(p); - - updateSelectProtocolsAdvancedWidget(); - lvSelectedProtocols->setCurrentIndex(idx.sibling(m-2, 0)); -} - -void StreamConfigDialog::on_tbDown_clicked() -{ - int m, n; - QModelIndex idx; - AbstractProtocol *p; - - idx = lvSelectedProtocols->currentIndex(); - - // Validation - if (!idx.isValid() || idx.row() == idx.model()->rowCount()) - return; - - m = n = idx.row() + 1; - - _iter->toFront(); - while (n--) - { - if (!_iter->hasNext()) - return; - - p = _iter->next(); - } - - _iter->remove(); - _iter->next(); - _iter->insert(p); - - updateSelectProtocolsAdvancedWidget(); - lvSelectedProtocols->setCurrentIndex(idx.sibling(m,0)); -} - -void StreamConfigDialog::updateSelectProtocolsAdvancedWidget() -{ - QStringList selProtoList; - - qDebug("%s", __FUNCTION__); - - _iter->toFront(); - while(_iter->hasNext()) - { - AbstractProtocol* p = _iter->next(); - qDebug("%p -- %d", p, p->protocolNumber()); - selProtoList.append(p->shortName()); - } - mpSelectedProtocolsModel->setStringList(selProtoList); -} - -void StreamConfigDialog::on_twTopLevel_currentChanged(int index) -{ - switch (index) - { - // Protocol Data - case 1: - { - QWidget *selWidget; - - // Hide the ToolBox before modifying it - else we have a crash !!! - tbProtocolData->hide(); - - selWidget = tbProtocolData->currentWidget(); - - // Remove all existing protocol widgets - while (tbProtocolData->count() > 0) - { - QWidget* w = tbProtocolData->widget(0); - tbProtocolData->removeItem(0); - w->setParent(0); - } - - // Repopulate the widgets - _iter->toFront(); - while (_iter->hasNext()) - { - AbstractProtocol* p = _iter->next(); - tbProtocolData->addItem(p->configWidget(), p->name()); - } - - tbProtocolData->setCurrentWidget(selWidget); - - tbProtocolData->show(); - break; - } - - // Packet View - case 3: - { - StoreCurrentStream(); - mpPacketModel->setSelectedProtocols(*_iter); - break; - } - - default: - break; - } -} - -void StreamConfigDialog::update_NumPacketsAndNumBursts() -{ - if (rbSendPackets->isChecked() && rbModeFixed->isChecked()) - leNumPackets->setEnabled(true); - else - leNumPackets->setEnabled(false); - - if (rbSendBursts->isChecked() && rbModeFixed->isChecked()) - leNumBursts->setEnabled(true); - else - leNumBursts->setEnabled(false); -} - -#if 0 -void StreamConfigDialog::on_lePattern_editingFinished() -{ - ulong num = 0; - bool isOk; - QString str; - - num = lePattern->text().remove(QChar(' ')).toULong(&isOk, 16); - qDebug("editfinished (%s | %x)\n", lePattern->text().toAscii().data(), num); - lePattern->setText(uintToHexStr(num, str, 4)); - qDebug("editfinished (%s | %x)\n", lePattern->text().toAscii().data(), num); -} -#endif - -/*! -Skip protocols upto and including the layer specified. -*/ -bool StreamConfigDialog::skipProtocols(int layer) -{ - _iter->toFront(); - - for (int i = ProtoMin; i <= layer; i++) - { - if(_iter->hasNext()) - { - int id; - QAbstractButton *btn; - - id = _iter->peekNext()->protocolNumber(); - btn = bgProto[i]->button(id); - if (btn) - _iter->next(); - } - } - - return true; -} - -/*! -Protocol choices (except "None" and "Other") for a protocol button group are disabled if checked is true, else they are enabled -*/ -void StreamConfigDialog::disableProtocols(QButtonGroup *protocolGroup, bool checked) -{ - qDebug("%s: btnGrp = %p, chk? = %d", __FUNCTION__, protocolGroup, checked); - foreach(QAbstractButton *btn, protocolGroup->buttons()) - { - int id = protocolGroup->id(btn); - - if ((id != ButtonIdNone) && (id != ButtonIdOther)) - btn->setDisabled(checked); - } -} - -void StreamConfigDialog::forceProtocolNone(bool checked) -{ - QObject *btn; - - btn = sender(); - Q_ASSERT(btn != NULL); - - qDebug("%s: chk? = %d, btn = %p, L1 = %p, L2 = %p, L3 = %p", __FUNCTION__, - checked, btn, rbL1None, rbFtNone, rbL3None); - - if (btn == rbL1None) - { - if (checked) - { - bgProto[ProtoVlan]->button(ButtonIdNone)->click(); - bgProto[ProtoL2]->button(ButtonIdNone)->click(); - bgProto[ProtoPayload]->button(ButtonIdNone)->click(); - } - - disableProtocols(bgProto[ProtoVlan], checked); - disableProtocols(bgProto[ProtoL2], checked); - disableProtocols(bgProto[ProtoPayload], checked); - } - else if (btn == rbFtNone) - { - if (checked) - bgProto[ProtoL3]->button(ButtonIdNone)->click(); - disableProtocols(bgProto[ProtoL3], checked); - } - else if (btn == rbL3None) - { - if (checked) - bgProto[ProtoL4]->button(ButtonIdNone)->click(); - disableProtocols(bgProto[ProtoL4], checked); - } - else - { - Q_ASSERT(1 == 0); // Unreachable code! - } -} - -void StreamConfigDialog::updateProtocol(int newId) -{ - int level; - QButtonGroup *btnGrp; - - btnGrp = static_cast(sender()); - Q_ASSERT(btnGrp != NULL); - - level = btnGrp->property("ProtocolLevel").toInt(); - Q_ASSERT(btnGrp == bgProto[level]); - - __updateProtocol(level, newId); -} - -void StreamConfigDialog::__updateProtocol(int level, int newId) -{ - int oldId; - QButtonGroup *btnGrp; - - Q_ASSERT((level >= ProtoMin) && (level <= ProtoMax)); - btnGrp = bgProto[level]; - oldId = btnGrp->property("ProtocolId").toInt(); - - qDebug("%s: level = %d old id = %d new id = %d upd? = %d", __FUNCTION__, - level, oldId, newId, isUpdateInProgress); - - if (newId == oldId) - return; - - if (!isUpdateInProgress) - { - int ret; - AbstractProtocol *p; - - ret = skipProtocols(level-1); - Q_ASSERT(ret == true); - - Q_ASSERT(oldId != newId); - Q_ASSERT(newId != ButtonIdOther); - - switch (oldId) - { - case ButtonIdNone: - _iter->insert(OstProtocolManager.createProtocol( - newId, mpStream)); - break; - - case ButtonIdOther: - default: - Q_ASSERT(_iter->hasNext()); - p =_iter->next(); - - if (newId) - _iter->setValue(OstProtocolManager.createProtocol( - newId, mpStream)); - else - _iter->remove(); - delete p; - if (level == ProtoPayload) - { - while (_iter->hasNext()) - { - p = _iter->next(); - _iter->remove(); - delete p; - } - } - break; - } - } - - btnGrp->setProperty("ProtocolId", newId); - return; -} - -void StreamConfigDialog::updateSelectProtocolsSimpleWidget() -{ - int i; - quint32 id; - QAbstractButton *btn; - - qDebug("%s", __FUNCTION__); - - isUpdateInProgress = true; - - // Reset to default state ... - for (i = ProtoMin; i < ProtoMax; i++) - bgProto[i]->button(ButtonIdNone)->click(); - - // ... now iterate and update - _iter->toFront(); - - for (i = ProtoMin; i < ProtoMax; i++) - { - if (!_iter->hasNext()) - goto _done; - - id = _iter->next()->protocolNumber(); - btn = bgProto[i]->button(id); - - if (btn) - { - if (btn->isEnabled()) - btn->click(); - else - { - btn->setChecked(true); - __updateProtocol(i, id); - } - } - else - { - switch (i) - { - case ProtoVlan: - _iter->previous(); - break; - - case ProtoPayload: - goto _other; - - default: - btn = bgProto[ProtoPayload]->button(id); - if (btn && btn->isEnabled()) - { - btn->click(); - break; - } - else - goto _other; - } - } - } - - // If more protocol(s) beyond payload ... - if (_iter->hasNext()) - { - i = ProtoPayload; - goto _other; - } - - goto _done; - -_other: - for (int j = i; j < ProtoMax; j++) - { - // VLAN doesn't have a "Other" button - if (j == ProtoVlan) - continue; - - bgProto[j]->button(ButtonIdOther)->setChecked(true); - __updateProtocol(j, ButtonIdOther); - } - -_done: - isUpdateInProgress = false; -} - -void StreamConfigDialog::LoadCurrentStream() -{ - QString str; - - qDebug("loading mpStream %p", mpStream); - - // Meta Data - { - cmbPktLenMode->setCurrentIndex(mpStream->lenMode()); - lePktLen->setText(str.setNum(mpStream->frameLen())); - lePktLenMin->setText(str.setNum(mpStream->frameLenMin())); - lePktLenMax->setText(str.setNum(mpStream->frameLenMax())); - } - - // Protocols - { - updateSelectProtocolsSimpleWidget(); - updateSelectProtocolsAdvancedWidget(); - - mpStream->loadProtocolWidgets(); - } - - // Stream Control - { - switch (mpStream->sendUnit()) - { - case Stream::e_su_packets: - rbSendPackets->setChecked(true); - break; - case Stream::e_su_bursts: - rbSendBursts->setChecked(true); - break; - default: - qWarning("Unhandled sendUnit = %d\n", mpStream->sendUnit()); - } - - switch (mpStream->sendMode()) - { - case Stream::e_sm_fixed: - rbModeFixed->setChecked(true); - break; - case Stream::e_sm_continuous: - rbModeContinuous->setChecked(true); - break; - default: - qWarning("Unhandled sendMode = %d\n", mpStream->sendMode()); - } - - switch(mpStream->nextWhat()) - { - case Stream::e_nw_stop: - rbActionStop->setChecked(true); - break; - case Stream::e_nw_goto_next: - rbActionGotoNext->setChecked(true); - break; - case Stream::e_nw_goto_id: - rbActionGotoStream->setChecked(true); - break; - default: - qWarning("Unhandled nextAction = %d\n", mpStream->nextWhat()); - } - - leNumPackets->setText(QString().setNum(mpStream->numPackets())); - leNumBursts->setText(QString().setNum(mpStream->numBursts())); - lePacketsPerBurst->setText(QString().setNum(mpStream->burstSize())); - lePacketsPerSec->setText(QString().setNum(mpStream->packetRate())); - leBurstsPerSec->setText(QString().setNum(mpStream->burstRate())); - // TODO(MED): Change this when we support goto to specific stream - leStreamId->setText(QString("0")); - } - qDebug("loading stream done"); -} - -void StreamConfigDialog::StoreCurrentStream() -{ - QString str; - bool isOk; - Stream *pStream = mpStream; - - qDebug("storing pStream %p", pStream); - - // Meta Data - pStream->setLenMode((Stream::FrameLengthMode) cmbPktLenMode->currentIndex()); - pStream->setFrameLen(lePktLen->text().toULong(&isOk)); - pStream->setFrameLenMin(lePktLenMin->text().toULong(&isOk)); - pStream->setFrameLenMax(lePktLenMax->text().toULong(&isOk)); - - // Protocols - { - pStream->storeProtocolWidgets(); - } - - // Stream Control - { - if (rbSendPackets->isChecked()) - pStream->setSendUnit(Stream::e_su_packets); - if (rbSendBursts->isChecked()) - pStream->setSendUnit(Stream::e_su_bursts); - - if (rbModeFixed->isChecked()) - pStream->setSendMode(Stream::e_sm_fixed); - if (rbModeContinuous->isChecked()) - pStream->setSendMode(Stream::e_sm_continuous); - - if (rbActionStop->isChecked()) - pStream->setNextWhat(Stream::e_nw_stop); - if (rbActionGotoNext->isChecked()) - pStream->setNextWhat(Stream::e_nw_goto_next); - if (rbActionGotoStream->isChecked()) - pStream->setNextWhat(Stream::e_nw_goto_id); - - pStream->setNumPackets(leNumPackets->text().toULong(&isOk)); - pStream->setNumBursts(leNumBursts->text().toULong(&isOk)); - pStream->setBurstSize(lePacketsPerBurst->text().toULong(&isOk)); - pStream->setPacketRate(lePacketsPerSec->text().toULong(&isOk)); - pStream->setBurstRate(leBurstsPerSec->text().toULong(&isOk)); - } -} - -void StreamConfigDialog::on_pbOk_clicked() -{ - OstProto::Stream s; - - // Store dialog contents into stream - StoreCurrentStream(); - - // Copy the data from the "local working copy of stream" to "actual stream" - mpStream->protoDataCopyInto(s); - mPort.streamByIndex(mCurrentStreamIndex)->protoDataCopyFrom(s); - - qDebug("stream stored"); - - lastTopLevelTabIndex = twTopLevel->currentIndex(); -} - +#include + +#include "streamconfigdialog.h" +#include "stream.h" +#include "abstractprotocol.h" +#include "protocollistiterator.h" + +#include "modeltest.h" + +// FIXME(HI) - remove +#include "../common/protocolmanager.h" +extern ProtocolManager OstProtocolManager; + +int StreamConfigDialog::lastTopLevelTabIndex = 0; + +StreamConfigDialog::StreamConfigDialog(Port &port, uint streamIndex, + QWidget *parent) : QDialog (parent), mPort(port) +{ + OstProto::Stream s; + mCurrentStreamIndex = streamIndex; + mpStream = new Stream; + mPort.streamByIndex(mCurrentStreamIndex)->protoDataCopyInto(s); + mpStream->protoDataCopyFrom(s); + _iter = mpStream->createProtocolListIterator(); + isUpdateInProgress = false; + + setupUi(this); + setupUiExtra(); + + for (int i = ProtoMin; i < ProtoMax; i++) + { + bgProto[i]->setProperty("ProtocolLevel", i); + bgProto[i]->setProperty("ProtocolId", ButtonIdNone); + connect(bgProto[i], SIGNAL(buttonClicked(int)), + this, SLOT(updateProtocol(int))); + } + + //! \todo causes a crash! +#if 0 + connect(lePktLen, SIGNAL(textEdited(QString)), + this, SLOT(updateContents())); +#endif + + // Time to play match the signals and slots! + + // If L1/L2(FT)/L3 = None, force subsequent protocol level(s) also to None + connect(rbL1None, SIGNAL(toggled(bool)), SLOT(forceProtocolNone(bool))); + connect(rbFtNone, SIGNAL(toggled(bool)), SLOT(forceProtocolNone(bool))); + connect(rbL3None, SIGNAL(toggled(bool)), SLOT(forceProtocolNone(bool))); + + // If L1/L2(FT)/L3/L4 = Other, force subsequent protocol to Other and + // disable the subsequent protocol group as well + connect(rbL1Other, SIGNAL(toggled(bool)), rbFtOther, SLOT(setChecked(bool))); + connect(rbL1Other, SIGNAL(toggled(bool)), gbFrameType, SLOT(setDisabled(bool))); + connect(rbFtOther, SIGNAL(toggled(bool)), rbL3Other, SLOT(setChecked(bool))); + connect(rbFtOther, SIGNAL(toggled(bool)), gbL3Proto, SLOT(setDisabled(bool))); + connect(rbL3Other, SIGNAL(toggled(bool)), rbL4Other, SLOT(setChecked(bool))); + connect(rbL3Other, SIGNAL(toggled(bool)), gbL4Proto, SLOT(setDisabled(bool))); + connect(rbL4Other, SIGNAL(toggled(bool)), rbPayloadOther, SLOT(setChecked(bool))); + connect(rbL4Other, SIGNAL(toggled(bool)), gbPayloadProto, SLOT(setDisabled(bool))); + + // Setup valid subsequent protocols for L2 and L3 protocols + for (int i = ProtoL2; i <= ProtoL3; i++) + { + foreach(QAbstractButton *btn1, bgProto[i]->buttons()) + { + int id1 = bgProto[i]->id(btn1); + + if (id1 != ButtonIdNone && id1 != ButtonIdOther) + { + int validProtocolCount = 0; + + foreach(QAbstractButton *btn2, bgProto[i+1]->buttons()) + { + int id2 = bgProto[i+1]->id(btn2); + + if (id2 != ButtonIdNone && id2 != ButtonIdOther) + { + if (OstProtocolManager.isValidNeighbour(id1, id2)) + { + connect(btn1, SIGNAL(toggled(bool)), + btn2, SLOT(setEnabled(bool))); + validProtocolCount++; + } + else + connect(btn1, SIGNAL(toggled(bool)), + btn2, SLOT(setDisabled(bool))); + } + } + + // If btn1 has no subsequent valid protocols, + // force subsequent Protocol to 'None' + if (validProtocolCount == 0) + connect(btn1, SIGNAL(clicked(bool)), + bgProto[i+1]->button(ButtonIdNone), SLOT(click())); + } + } + } + + mpAvailableProtocolsModel = new QStringListModel( + OstProtocolManager.protocolDatabase(), this); + lvAllProtocols->setModel(mpAvailableProtocolsModel); + mpSelectedProtocolsModel = new QStringListModel(this); + lvSelectedProtocols->setModel(mpSelectedProtocolsModel); + + + connect(lvAllProtocols->selectionModel(), + SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), + this, SLOT(when_lvAllProtocols_selectionChanged( + const QItemSelection&, const QItemSelection&))); + connect(lvSelectedProtocols->selectionModel(), + SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)), + this, SLOT(when_lvSelectedProtocols_currentChanged(const QModelIndex&, + const QModelIndex&))); + + LoadCurrentStream(); + mpPacketModel = new PacketModel(this); + tvPacketTree->setModel(mpPacketModel); + mpPacketModelTester = new ModelTest(mpPacketModel); + tvPacketTree->header()->hide(); + vwPacketDump->setModel(mpPacketModel); + vwPacketDump->setSelectionModel(tvPacketTree->selectionModel()); + + // TODO(MED): + + //! \todo Implement then enable these protocols - ARP, IPv6, ICMP, IGMP + rbL3Arp->setHidden(true); + rbL3Ipv6->setHidden(true); + rbL4Icmp->setHidden(true); + rbL4Igmp->setHidden(true); + //! \todo Enable navigation of streams + pbPrev->setDisabled(true); + pbNext->setDisabled(true); + //! \todo Support Goto Stream Id + leStreamId->setDisabled(true); + disconnect(rbActionGotoStream, SIGNAL(toggled(bool)), leStreamId, SLOT(setEnabled(bool))); + //! \todo Support Continuous Mode + rbModeContinuous->setDisabled(true); + + // Finally, restore the saved last selected tab for the various tab widgets + twTopLevel->setCurrentIndex(lastTopLevelTabIndex); +} + +void StreamConfigDialog::setupUiExtra() +{ + QRegExp reHex2B("[0-9,a-f,A-F]{1,4}"); + QRegExp reHex4B("[0-9,a-f,A-F]{1,8}"); + QRegExp reMac("([0-9,a-f,A-F]{2,2}[:-]){5,5}[0-9,a-f,A-F]{2,2}"); + + // ---- Setup default stuff that cannot be done in designer ---- + bgProto[ProtoL1] = new QButtonGroup(); + bgProto[ProtoL1]->addButton(rbL1None, ButtonIdNone); + bgProto[ProtoL1]->addButton(rbL1Mac, OstProto::Protocol::kMacFieldNumber); + bgProto[ProtoL1]->addButton(rbL1Other, ButtonIdOther); + + bgProto[ProtoL2] = new QButtonGroup(); +#if 0 + foreach(QRadioButton *btn, gbFrameType->findChildren()) + bgL2Proto->addButton(btn); +#else + bgProto[ProtoL2]->addButton(rbFtNone, ButtonIdNone); + bgProto[ProtoL2]->addButton(rbFtEthernet2, OstProto::Protocol::kEth2FieldNumber); + bgProto[ProtoL2]->addButton(rbFt802Dot3Raw, OstProto::Protocol::kDot3FieldNumber); + bgProto[ProtoL2]->addButton(rbFt802Dot3Llc, OstProto::Protocol::kDot2LlcFieldNumber); + bgProto[ProtoL2]->addButton(rbFtLlcSnap, OstProto::Protocol::kDot2SnapFieldNumber); + bgProto[ProtoL2]->addButton(rbFtOther, ButtonIdOther); +#endif + + bgProto[ProtoVlan] = new QButtonGroup(); + bgProto[ProtoVlan]->addButton(rbVlanNone, ButtonIdNone); + bgProto[ProtoVlan]->addButton(rbVlanSingle, OstProto::Protocol::kVlanFieldNumber); + bgProto[ProtoVlan]->addButton(rbVlanDouble, OstProto::Protocol::kVlanStackFieldNumber); + + bgProto[ProtoL3] = new QButtonGroup(); +#if 0 + foreach(QRadioButton *btn, gbL3Proto->findChildren()) + bgProto[ProtoL3]->addButton(btn); +#else + bgProto[ProtoL3]->addButton(rbL3None, ButtonIdNone); + bgProto[ProtoL3]->addButton(rbL3Ipv4, OstProto::Protocol::kIp4FieldNumber); + bgProto[ProtoL3]->addButton(rbL3Ipv6, 0xFFFF); + bgProto[ProtoL3]->addButton(rbL3Arp, 0xFFFF); + bgProto[ProtoL3]->addButton(rbL3Other, ButtonIdOther); +#endif + + bgProto[ProtoL4] = new QButtonGroup(); +#if 0 + foreach(QRadioButton *btn, gbL4Proto->findChildren()) + bgProto[ProtoL4]->addButton(btn); +#else + bgProto[ProtoL4]->addButton(rbL4None, 0); + bgProto[ProtoL4]->addButton(rbL4Tcp, OstProto::Protocol::kTcpFieldNumber); + bgProto[ProtoL4]->addButton(rbL4Udp, OstProto::Protocol::kUdpFieldNumber); + bgProto[ProtoL4]->addButton(rbL4Icmp, 0xFFFF); + bgProto[ProtoL4]->addButton(rbL4Igmp, 0xFFFF); + bgProto[ProtoL4]->addButton(rbL4Other, ButtonIdOther); +#endif + + bgProto[ProtoPayload] = new QButtonGroup(); +#if 0 + foreach(QRadioButton *btn, gbPayloadProto->findChildren()) + bgProto[ProtoPayload]->addButton(btn); +#else + bgProto[ProtoPayload]->addButton(rbPayloadNone, ButtonIdNone); + bgProto[ProtoPayload]->addButton(rbPayloadPattern, OstProto::Protocol::kPayloadFieldNumber); + bgProto[ProtoPayload]->addButton(rbPayloadOther, ButtonIdOther); +#endif + /* + ** Setup Validators + */ + // Meta Data + //! \todo - doesn't seem to work - range validator needs a spinbox? + //lePktLen->setValidator(new QIntValidator(MIN_PKT_LEN, MAX_PKT_LEN, this)); + + /* + ** Setup Connections + */ + connect(rbSendPackets, SIGNAL(toggled(bool)), + this, SLOT(update_NumPacketsAndNumBursts())); + connect(rbSendBursts, SIGNAL(toggled(bool)), + this, SLOT(update_NumPacketsAndNumBursts())); + connect(rbModeFixed, SIGNAL(toggled(bool)), + this, SLOT(update_NumPacketsAndNumBursts())); + connect(rbModeContinuous, SIGNAL(toggled(bool)), + this, SLOT(update_NumPacketsAndNumBursts())); + +} + +StreamConfigDialog::~StreamConfigDialog() +{ + delete mpPacketModelTester; + delete mpPacketModel; + + for (int i = ProtoMin; i < ProtoMax; i++) + delete bgProto[i]; + + delete _iter; + delete mpStream; +} + +void StreamConfigDialog::on_cmbPktLenMode_currentIndexChanged(QString mode) +{ + if (mode == "Fixed") + { + lePktLen->setEnabled(true); + lePktLenMin->setDisabled(true); + lePktLenMax->setDisabled(true); + } + else if (mode == "Increment") + { + lePktLen->setDisabled(true); + lePktLenMin->setEnabled(true); + lePktLenMax->setEnabled(true); + } + else if (mode == "Decrement") + { + lePktLen->setDisabled(true); + lePktLenMin->setEnabled(true); + lePktLenMax->setEnabled(true); + } + else if (mode == "Random") + { + lePktLen->setDisabled(true); + lePktLenMin->setEnabled(true); + lePktLenMax->setEnabled(true); + } + else + { + qWarning("Unhandled/Unknown PktLenMode = %s", mode.toAscii().data()); + } +} + +void StreamConfigDialog::on_pbPrev_clicked() +{ +#if 0 + StoreCurrentStream(currStreamIdx); + currStreamIdx--; + LoadCurrentStream(currStreamIdx); + + pbPrev->setDisabled((currStreamIdx == 0)); + pbNext->setDisabled((currStreamIdx == 2)); +#endif +} + +void StreamConfigDialog::on_pbNext_clicked() +{ +#if 0 + StoreCurrentStream(currStreamIdx); + currStreamIdx++; + LoadCurrentStream(currStreamIdx); + + pbPrev->setDisabled((currStreamIdx == 0)); + pbNext->setDisabled((currStreamIdx == 2)); +#endif +} + +void StreamConfigDialog::on_tbSelectProtocols_currentChanged(int index) +{ + qDebug("%s, index = %d", __FUNCTION__, index); + switch (index) + { + case 0: + updateSelectProtocolsSimpleWidget(); + break; + case 1: + updateSelectProtocolsAdvancedWidget(); + break; + default: + qFatal("%s: unexpected index = %d", __FUNCTION__, index); + } +} + +void StreamConfigDialog::when_lvAllProtocols_selectionChanged( + const QItemSelection &selected, const QItemSelection &deselected) +{ + int size = lvAllProtocols->selectionModel()->selectedIndexes().size(); + + qDebug("%s: selected.indexes().size = %d\n", __FUNCTION__, size); + + tbAdd->setEnabled(size > 0); +} + +void StreamConfigDialog::when_lvSelectedProtocols_currentChanged( + const QModelIndex ¤t, const QModelIndex &previous) +{ + qDebug("%s: currentRow = %d\n", __FUNCTION__, current.row()); + + tbDelete->setEnabled(current.isValid()); + tbUp->setEnabled(current.isValid() && (current.row() != 0)); + tbDown->setEnabled(current.isValid() && + (current.row() != (current.model()->rowCount() - 1))); +} + +void StreamConfigDialog::on_tbAdd_clicked() +{ + int n = 0; + QModelIndex idx2; + AbstractProtocol *p; + QModelIndexList selection; + + selection = lvAllProtocols->selectionModel()->selectedIndexes(); + + // Validation + if (selection.size() == 0) + return; + + idx2 = lvSelectedProtocols->currentIndex(); + if (idx2.isValid()) + n = idx2.row(); + + _iter->toFront(); + while (n--) + { + if (!_iter->hasNext()) + return; + + p = _iter->next(); + } + + foreach(QModelIndex idx, selection) + _iter->insert(OstProtocolManager.createProtocol( + mpAvailableProtocolsModel->stringList().at(idx.row()), mpStream)); + + updateSelectProtocolsAdvancedWidget(); + lvSelectedProtocols->setCurrentIndex(idx2); +} + +void StreamConfigDialog::on_tbDelete_clicked() +{ + int n; + QModelIndex idx; + AbstractProtocol *p; + + idx = lvSelectedProtocols->currentIndex(); + + // Validation + if (!idx.isValid()) + return; + + n = idx.row() + 1; + + _iter->toFront(); + while (n--) + { + if (!_iter->hasNext()) + return; + + p = _iter->next(); + } + + _iter->remove(); + delete p; + + updateSelectProtocolsAdvancedWidget(); + lvSelectedProtocols->setCurrentIndex(idx); +} + +void StreamConfigDialog::on_tbUp_clicked() +{ + int m, n; + QModelIndex idx; + AbstractProtocol *p; + + idx = lvSelectedProtocols->currentIndex(); + + // Validation + if (!idx.isValid() || idx.row() == 0) + return; + + m = n = idx.row() + 1; + + _iter->toFront(); + while (n--) + { + if (!_iter->hasNext()) + return; + + p = _iter->next(); + } + + _iter->remove(); + _iter->previous(); + _iter->insert(p); + + updateSelectProtocolsAdvancedWidget(); + lvSelectedProtocols->setCurrentIndex(idx.sibling(m-2, 0)); +} + +void StreamConfigDialog::on_tbDown_clicked() +{ + int m, n; + QModelIndex idx; + AbstractProtocol *p; + + idx = lvSelectedProtocols->currentIndex(); + + // Validation + if (!idx.isValid() || idx.row() == idx.model()->rowCount()) + return; + + m = n = idx.row() + 1; + + _iter->toFront(); + while (n--) + { + if (!_iter->hasNext()) + return; + + p = _iter->next(); + } + + _iter->remove(); + _iter->next(); + _iter->insert(p); + + updateSelectProtocolsAdvancedWidget(); + lvSelectedProtocols->setCurrentIndex(idx.sibling(m,0)); +} + +void StreamConfigDialog::updateSelectProtocolsAdvancedWidget() +{ + QStringList selProtoList; + + qDebug("%s", __FUNCTION__); + + _iter->toFront(); + while(_iter->hasNext()) + { + AbstractProtocol* p = _iter->next(); + qDebug("%p -- %d", p, p->protocolNumber()); + selProtoList.append(p->shortName()); + } + mpSelectedProtocolsModel->setStringList(selProtoList); +} + +void StreamConfigDialog::on_twTopLevel_currentChanged(int index) +{ + switch (index) + { + // Protocol Data + case 1: + { + QWidget *selWidget; + + // Hide the ToolBox before modifying it - else we have a crash !!! + tbProtocolData->hide(); + + selWidget = tbProtocolData->currentWidget(); + + // Remove all existing protocol widgets + while (tbProtocolData->count() > 0) + { + QWidget* w = tbProtocolData->widget(0); + tbProtocolData->removeItem(0); + w->setParent(0); + } + + // Repopulate the widgets + _iter->toFront(); + while (_iter->hasNext()) + { + AbstractProtocol* p = _iter->next(); + tbProtocolData->addItem(p->configWidget(), p->name()); + } + + tbProtocolData->setCurrentWidget(selWidget); + + tbProtocolData->show(); + break; + } + + // Packet View + case 3: + { + StoreCurrentStream(); + mpPacketModel->setSelectedProtocols(*_iter); + break; + } + + default: + break; + } +} + +void StreamConfigDialog::update_NumPacketsAndNumBursts() +{ + if (rbSendPackets->isChecked() && rbModeFixed->isChecked()) + leNumPackets->setEnabled(true); + else + leNumPackets->setEnabled(false); + + if (rbSendBursts->isChecked() && rbModeFixed->isChecked()) + leNumBursts->setEnabled(true); + else + leNumBursts->setEnabled(false); +} + +#if 0 +void StreamConfigDialog::on_lePattern_editingFinished() +{ + ulong num = 0; + bool isOk; + QString str; + + num = lePattern->text().remove(QChar(' ')).toULong(&isOk, 16); + qDebug("editfinished (%s | %x)\n", lePattern->text().toAscii().data(), num); + lePattern->setText(uintToHexStr(num, str, 4)); + qDebug("editfinished (%s | %x)\n", lePattern->text().toAscii().data(), num); +} +#endif + +/*! +Skip protocols upto and including the layer specified. +*/ +bool StreamConfigDialog::skipProtocols(int layer) +{ + _iter->toFront(); + + for (int i = ProtoMin; i <= layer; i++) + { + if(_iter->hasNext()) + { + int id; + QAbstractButton *btn; + + id = _iter->peekNext()->protocolNumber(); + btn = bgProto[i]->button(id); + if (btn) + _iter->next(); + } + } + + return true; +} + +/*! +Protocol choices (except "None" and "Other") for a protocol button group are disabled if checked is true, else they are enabled +*/ +void StreamConfigDialog::disableProtocols(QButtonGroup *protocolGroup, bool checked) +{ + qDebug("%s: btnGrp = %p, chk? = %d", __FUNCTION__, protocolGroup, checked); + foreach(QAbstractButton *btn, protocolGroup->buttons()) + { + int id = protocolGroup->id(btn); + + if ((id != ButtonIdNone) && (id != ButtonIdOther)) + btn->setDisabled(checked); + } +} + +void StreamConfigDialog::forceProtocolNone(bool checked) +{ + QObject *btn; + + btn = sender(); + Q_ASSERT(btn != NULL); + + qDebug("%s: chk? = %d, btn = %p, L1 = %p, L2 = %p, L3 = %p", __FUNCTION__, + checked, btn, rbL1None, rbFtNone, rbL3None); + + if (btn == rbL1None) + { + if (checked) + { + bgProto[ProtoVlan]->button(ButtonIdNone)->click(); + bgProto[ProtoL2]->button(ButtonIdNone)->click(); + bgProto[ProtoPayload]->button(ButtonIdNone)->click(); + } + + disableProtocols(bgProto[ProtoVlan], checked); + disableProtocols(bgProto[ProtoL2], checked); + disableProtocols(bgProto[ProtoPayload], checked); + } + else if (btn == rbFtNone) + { + if (checked) + bgProto[ProtoL3]->button(ButtonIdNone)->click(); + disableProtocols(bgProto[ProtoL3], checked); + } + else if (btn == rbL3None) + { + if (checked) + bgProto[ProtoL4]->button(ButtonIdNone)->click(); + disableProtocols(bgProto[ProtoL4], checked); + } + else + { + Q_ASSERT(1 == 0); // Unreachable code! + } +} + +void StreamConfigDialog::updateProtocol(int newId) +{ + int level; + QButtonGroup *btnGrp; + + btnGrp = static_cast(sender()); + Q_ASSERT(btnGrp != NULL); + + level = btnGrp->property("ProtocolLevel").toInt(); + Q_ASSERT(btnGrp == bgProto[level]); + + __updateProtocol(level, newId); +} + +void StreamConfigDialog::__updateProtocol(int level, int newId) +{ + int oldId; + QButtonGroup *btnGrp; + + Q_ASSERT((level >= ProtoMin) && (level <= ProtoMax)); + btnGrp = bgProto[level]; + oldId = btnGrp->property("ProtocolId").toInt(); + + qDebug("%s: level = %d old id = %d new id = %d upd? = %d", __FUNCTION__, + level, oldId, newId, isUpdateInProgress); + + if (newId == oldId) + return; + + if (!isUpdateInProgress) + { + int ret; + AbstractProtocol *p; + + ret = skipProtocols(level-1); + Q_ASSERT(ret == true); + + Q_ASSERT(oldId != newId); + Q_ASSERT(newId != ButtonIdOther); + + switch (oldId) + { + case ButtonIdNone: + _iter->insert(OstProtocolManager.createProtocol( + newId, mpStream)); + break; + + case ButtonIdOther: + default: + Q_ASSERT(_iter->hasNext()); + p =_iter->next(); + + if (newId) + _iter->setValue(OstProtocolManager.createProtocol( + newId, mpStream)); + else + _iter->remove(); + delete p; + if (level == ProtoPayload) + { + while (_iter->hasNext()) + { + p = _iter->next(); + _iter->remove(); + delete p; + } + } + break; + } + } + + btnGrp->setProperty("ProtocolId", newId); + return; +} + +void StreamConfigDialog::updateSelectProtocolsSimpleWidget() +{ + int i; + quint32 id; + QAbstractButton *btn; + + qDebug("%s", __FUNCTION__); + + isUpdateInProgress = true; + + // Reset to default state ... + for (i = ProtoMin; i < ProtoMax; i++) + bgProto[i]->button(ButtonIdNone)->click(); + + // ... now iterate and update + _iter->toFront(); + + for (i = ProtoMin; i < ProtoMax; i++) + { + if (!_iter->hasNext()) + goto _done; + + id = _iter->next()->protocolNumber(); + btn = bgProto[i]->button(id); + + if (btn) + { + if (btn->isEnabled()) + btn->click(); + else + { + btn->setChecked(true); + __updateProtocol(i, id); + } + } + else + { + switch (i) + { + case ProtoVlan: + _iter->previous(); + break; + + case ProtoPayload: + goto _other; + + default: + btn = bgProto[ProtoPayload]->button(id); + if (btn && btn->isEnabled()) + { + btn->click(); + break; + } + else + goto _other; + } + } + } + + // If more protocol(s) beyond payload ... + if (_iter->hasNext()) + { + i = ProtoPayload; + goto _other; + } + + goto _done; + +_other: + for (int j = i; j < ProtoMax; j++) + { + // VLAN doesn't have a "Other" button + if (j == ProtoVlan) + continue; + + bgProto[j]->button(ButtonIdOther)->setChecked(true); + __updateProtocol(j, ButtonIdOther); + } + +_done: + isUpdateInProgress = false; +} + +void StreamConfigDialog::LoadCurrentStream() +{ + QString str; + + qDebug("loading mpStream %p", mpStream); + + // Meta Data + { + cmbPktLenMode->setCurrentIndex(mpStream->lenMode()); + lePktLen->setText(str.setNum(mpStream->frameLen())); + lePktLenMin->setText(str.setNum(mpStream->frameLenMin())); + lePktLenMax->setText(str.setNum(mpStream->frameLenMax())); + } + + // Protocols + { + updateSelectProtocolsSimpleWidget(); + updateSelectProtocolsAdvancedWidget(); + + mpStream->loadProtocolWidgets(); + } + + // Stream Control + { + switch (mpStream->sendUnit()) + { + case Stream::e_su_packets: + rbSendPackets->setChecked(true); + break; + case Stream::e_su_bursts: + rbSendBursts->setChecked(true); + break; + default: + qWarning("Unhandled sendUnit = %d\n", mpStream->sendUnit()); + } + + switch (mpStream->sendMode()) + { + case Stream::e_sm_fixed: + rbModeFixed->setChecked(true); + break; + case Stream::e_sm_continuous: + rbModeContinuous->setChecked(true); + break; + default: + qWarning("Unhandled sendMode = %d\n", mpStream->sendMode()); + } + + switch(mpStream->nextWhat()) + { + case Stream::e_nw_stop: + rbActionStop->setChecked(true); + break; + case Stream::e_nw_goto_next: + rbActionGotoNext->setChecked(true); + break; + case Stream::e_nw_goto_id: + rbActionGotoStream->setChecked(true); + break; + default: + qWarning("Unhandled nextAction = %d\n", mpStream->nextWhat()); + } + + leNumPackets->setText(QString().setNum(mpStream->numPackets())); + leNumBursts->setText(QString().setNum(mpStream->numBursts())); + lePacketsPerBurst->setText(QString().setNum(mpStream->burstSize())); + lePacketsPerSec->setText(QString().setNum(mpStream->packetRate())); + leBurstsPerSec->setText(QString().setNum(mpStream->burstRate())); + // TODO(MED): Change this when we support goto to specific stream + leStreamId->setText(QString("0")); + } + qDebug("loading stream done"); +} + +void StreamConfigDialog::StoreCurrentStream() +{ + QString str; + bool isOk; + Stream *pStream = mpStream; + + qDebug("storing pStream %p", pStream); + + // Meta Data + pStream->setLenMode((Stream::FrameLengthMode) cmbPktLenMode->currentIndex()); + pStream->setFrameLen(lePktLen->text().toULong(&isOk)); + pStream->setFrameLenMin(lePktLenMin->text().toULong(&isOk)); + pStream->setFrameLenMax(lePktLenMax->text().toULong(&isOk)); + + // Protocols + { + pStream->storeProtocolWidgets(); + } + + // Stream Control + { + if (rbSendPackets->isChecked()) + pStream->setSendUnit(Stream::e_su_packets); + if (rbSendBursts->isChecked()) + pStream->setSendUnit(Stream::e_su_bursts); + + if (rbModeFixed->isChecked()) + pStream->setSendMode(Stream::e_sm_fixed); + if (rbModeContinuous->isChecked()) + pStream->setSendMode(Stream::e_sm_continuous); + + if (rbActionStop->isChecked()) + pStream->setNextWhat(Stream::e_nw_stop); + if (rbActionGotoNext->isChecked()) + pStream->setNextWhat(Stream::e_nw_goto_next); + if (rbActionGotoStream->isChecked()) + pStream->setNextWhat(Stream::e_nw_goto_id); + + pStream->setNumPackets(leNumPackets->text().toULong(&isOk)); + pStream->setNumBursts(leNumBursts->text().toULong(&isOk)); + pStream->setBurstSize(lePacketsPerBurst->text().toULong(&isOk)); + pStream->setPacketRate(lePacketsPerSec->text().toULong(&isOk)); + pStream->setBurstRate(leBurstsPerSec->text().toULong(&isOk)); + } +} + +void StreamConfigDialog::on_pbOk_clicked() +{ + OstProto::Stream s; + + // Store dialog contents into stream + StoreCurrentStream(); + + // Copy the data from the "local working copy of stream" to "actual stream" + mpStream->protoDataCopyInto(s); + mPort.streamByIndex(mCurrentStreamIndex)->protoDataCopyFrom(s); + + qDebug("stream stored"); + + lastTopLevelTabIndex = twTopLevel->currentIndex(); +} + diff --git a/client/streamconfigdialog.h b/client/streamconfigdialog.h index fcc3f40..0961767 100644 --- a/client/streamconfigdialog.h +++ b/client/streamconfigdialog.h @@ -1,113 +1,113 @@ -#ifndef _STREAM_CONFIG_DIALOG_H -#define _STREAM_CONFIG_DIALOG_H - -#include -#include "ui_streamconfigdialog.h" -#include "port.h" -#include "stream.h" -#include "packetmodel.h" -#include "modeltest.h" - -#define MAX_MAC_ITER_COUNT 256 -#define MIN_PKT_LEN 64 -#define MAX_PKT_LEN 1522 - -/* -** TODO -** \todo Improve HexStr handling -** -*/ - - -class StreamConfigDialog : public QDialog, public Ui::StreamConfigDialog -{ - Q_OBJECT -public: - StreamConfigDialog(Port &port, uint streamIndex, QWidget *parent = 0); - ~StreamConfigDialog(); - -private: - - enum ButtonId - { - ButtonIdNone = 0, - ButtonIdOther = -2 - }; - - enum ProtoButtonGroup - { - ProtoMin, - ProtoL1 = 0, - ProtoVlan = 1, - ProtoL2 = 2, - ProtoL3 = 3, - ProtoL4 = 4, - ProtoPayload = 5, - ProtoMax - }; - - QButtonGroup *bgProto[ProtoMax]; - - QStringListModel *mpAvailableProtocolsModel; - QStringListModel *mpSelectedProtocolsModel; - - Port& mPort; - uint mCurrentStreamIndex; - - Stream *mpStream; - ProtocolListIterator *_iter; - - bool isUpdateInProgress; - - PacketModel *mpPacketModel; - ModelTest *mpPacketModelTester; - - // The following static variables are used to track the "selected" tab - // for the various tab widgets so that it can be restored when the dialog - // is opened the next time - static int lastTopLevelTabIndex; - - void setupUiExtra(); - void updateSelectedProtocols(); - void LoadCurrentStream(); - void StoreCurrentStream(); - -private slots: - void on_cmbPktLenMode_currentIndexChanged(QString mode); - void update_NumPacketsAndNumBursts(); - - void on_twTopLevel_currentChanged(int index); - void on_tbSelectProtocols_currentChanged(int index); - - // "Simple" Protocol Selection related - bool skipProtocols(int layer); - - void disableProtocols(QButtonGroup *protocolGroup, bool checked); - void forceProtocolNone(bool checked); - - void updateProtocol(int newId); - void __updateProtocol(int level, int newId); - - void updateSelectProtocolsSimpleWidget(); - - // "Advanced" Protocol Selection related - void when_lvAllProtocols_selectionChanged( - const QItemSelection &selected, const QItemSelection &deselected); - void when_lvSelectedProtocols_currentChanged( - const QModelIndex ¤t, const QModelIndex &previous); - - void on_tbAdd_clicked(); - void on_tbDelete_clicked(); - void on_tbUp_clicked(); - void on_tbDown_clicked(); - - void updateSelectProtocolsAdvancedWidget(); - - void on_pbPrev_clicked(); - void on_pbNext_clicked(); - - void on_pbOk_clicked(); -}; - -#endif - +#ifndef _STREAM_CONFIG_DIALOG_H +#define _STREAM_CONFIG_DIALOG_H + +#include +#include "ui_streamconfigdialog.h" +#include "port.h" +#include "stream.h" +#include "packetmodel.h" +#include "modeltest.h" + +#define MAX_MAC_ITER_COUNT 256 +#define MIN_PKT_LEN 64 +#define MAX_PKT_LEN 1522 + +/* +** TODO +** \todo Improve HexStr handling +** +*/ + + +class StreamConfigDialog : public QDialog, public Ui::StreamConfigDialog +{ + Q_OBJECT +public: + StreamConfigDialog(Port &port, uint streamIndex, QWidget *parent = 0); + ~StreamConfigDialog(); + +private: + + enum ButtonId + { + ButtonIdNone = 0, + ButtonIdOther = -2 + }; + + enum ProtoButtonGroup + { + ProtoMin, + ProtoL1 = 0, + ProtoVlan = 1, + ProtoL2 = 2, + ProtoL3 = 3, + ProtoL4 = 4, + ProtoPayload = 5, + ProtoMax + }; + + QButtonGroup *bgProto[ProtoMax]; + + QStringListModel *mpAvailableProtocolsModel; + QStringListModel *mpSelectedProtocolsModel; + + Port& mPort; + uint mCurrentStreamIndex; + + Stream *mpStream; + ProtocolListIterator *_iter; + + bool isUpdateInProgress; + + PacketModel *mpPacketModel; + ModelTest *mpPacketModelTester; + + // The following static variables are used to track the "selected" tab + // for the various tab widgets so that it can be restored when the dialog + // is opened the next time + static int lastTopLevelTabIndex; + + void setupUiExtra(); + void updateSelectedProtocols(); + void LoadCurrentStream(); + void StoreCurrentStream(); + +private slots: + void on_cmbPktLenMode_currentIndexChanged(QString mode); + void update_NumPacketsAndNumBursts(); + + void on_twTopLevel_currentChanged(int index); + void on_tbSelectProtocols_currentChanged(int index); + + // "Simple" Protocol Selection related + bool skipProtocols(int layer); + + void disableProtocols(QButtonGroup *protocolGroup, bool checked); + void forceProtocolNone(bool checked); + + void updateProtocol(int newId); + void __updateProtocol(int level, int newId); + + void updateSelectProtocolsSimpleWidget(); + + // "Advanced" Protocol Selection related + void when_lvAllProtocols_selectionChanged( + const QItemSelection &selected, const QItemSelection &deselected); + void when_lvSelectedProtocols_currentChanged( + const QModelIndex ¤t, const QModelIndex &previous); + + void on_tbAdd_clicked(); + void on_tbDelete_clicked(); + void on_tbUp_clicked(); + void on_tbDown_clicked(); + + void updateSelectProtocolsAdvancedWidget(); + + void on_pbPrev_clicked(); + void on_pbNext_clicked(); + + void on_pbOk_clicked(); +}; + +#endif + diff --git a/client/streammodel.cpp b/client/streammodel.cpp index 925be4b..c58d25b 100644 --- a/client/streammodel.cpp +++ b/client/streammodel.cpp @@ -1,242 +1,242 @@ -#include "stream.h" -#include "streammodel.h" -#include "portgrouplist.h" -#include "qicon.h" - -StreamModel::StreamModel(PortGroupList *p, QObject *parent) - : QAbstractTableModel(parent) -{ - pgl = p; - mCurrentPort = NULL; -} - -int StreamModel::rowCount(const QModelIndex &parent) const -{ - if (parent.isValid()) - return 0; - - if (mCurrentPort) - return mCurrentPort->numStreams(); - else - return 0; -} - -int StreamModel::columnCount(const QModelIndex &parent ) const -{ - return (int) StreamMaxFields; -} - -Qt::ItemFlags StreamModel::flags(const QModelIndex &index) const -{ - Qt::ItemFlags flags = QAbstractTableModel::flags(index); - - - switch (index.column()) - { - case StreamIcon: - break; - case StreamName: - flags |= Qt::ItemIsEditable; - break; - case StreamStatus: - flags |= Qt::ItemIsUserCheckable; - break; - case StreamNextWhat: - flags |= Qt::ItemIsEditable; - break; - default: - //qFatal("Missed case in switch!"); - break; - } - - return flags; -} - -QVariant StreamModel::data(const QModelIndex &index, int role) const -{ - // Check for a valid index - if (!index.isValid()) - return QVariant(); - - // Check for row/column limits - if (index.row() >= mCurrentPort->numStreams()) - return QVariant(); - - if (index.column() >= StreamMaxFields) - return QVariant(); - - if (mCurrentPort == NULL) - return QVariant(); - - // Return data based on field and role - switch(index.column()) - { - case StreamIcon: - { - if (role == Qt::DecorationRole) - return QIcon(":/icons/stream_edit.png"); - else - return QVariant(); - break; - } - case StreamName: - { - if ((role == Qt::DisplayRole) || (role == Qt::EditRole)) - return mCurrentPort->streamByIndex(index.row())->name(); - else - return QVariant(); - break; - } - case StreamStatus: - { - if ((role == Qt::CheckStateRole)) - { - if (mCurrentPort->streamByIndex(index.row())->isEnabled()) - return Qt::Checked; - else - return Qt::Unchecked; - } - else - return QVariant(); - break; - } - case StreamNextWhat: - { - int val = mCurrentPort->streamByIndex(index.row())->nextWhat(); - - if (role == Qt::DisplayRole) - return nextWhatOptionList().at(val); - else if (role == Qt::EditRole) - return val; - else - return QVariant(); - - break; - } - default: - qFatal("-------------UNHANDLED STREAM FIELD----------------"); - } - - return QVariant(); -} - -bool StreamModel::setData(const QModelIndex &index, const QVariant &value, int role) -{ - if (mCurrentPort == NULL) - return false; - - if (index.isValid()) - { - switch (index.column()) - { - // Edit Supported Fields - case StreamName: - mCurrentPort->streamByIndex(index.row())->setName(value.toString()); - emit(dataChanged(index, index)); - return true; - - case StreamStatus: - mCurrentPort->streamByIndex(index.row())->setEnabled(value.toBool()); - emit(dataChanged(index, index)); - return true; - - case StreamNextWhat: - if (role == Qt::EditRole) - { - mCurrentPort->streamByIndex(index.row())->setNextWhat( - (Stream::NextWhat)value.toInt()); - emit(dataChanged(index, index)); - return true; - } - else - return false; - - // Edit Not Supported Fields - case StreamIcon: - return false; - - // Unhandled Stream Field - default: - qDebug("-------------UNHANDLED STREAM FIELD----------------"); - break; - } - } - - return false; -} - -QVariant StreamModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - if (role != Qt::DisplayRole) - return QVariant(); - - if (orientation == Qt::Horizontal) - { - switch(section) - { - case StreamIcon: - return QString(""); - break; - case StreamName: - return QString("Name"); - break; - case StreamStatus: - return QString(""); - break; - case StreamNextWhat: - return QString("Goto"); - break; - default: - qDebug("-------------UNHANDLED STREAM FIELD----------------"); - break; - } - } - else - return QString("%1").arg(section+1); - - return QVariant(); -} - -bool StreamModel::insertRows(int row, int count, const QModelIndex &parent) -{ - qDebug("insertRows() row = %d", row); - qDebug("insertRows() count = %d", count); - beginInsertRows(QModelIndex(), row, row+count-1); - for (int i = 0; i < count; i++) - mCurrentPort->newStreamAt(row); - endInsertRows(); - - return true; -} - -bool StreamModel::removeRows(int row, int count, const QModelIndex &parent) -{ - qDebug("removeRows() row = %d", row); - qDebug("removeRows() count = %d", count); - beginRemoveRows(QModelIndex(), row, row+count-1); - for (int i = 0; i < count; i++) - { - mCurrentPort->deleteStreamAt(row); - } - endRemoveRows(); - - return true; -} - -// --------------------- SLOTS ------------------------ - -void StreamModel::setCurrentPortIndex(const QModelIndex ¤t) -{ - if (!current.isValid() || !pgl->isPort(current)) - { - qDebug("current is either invalid or not a port"); - mCurrentPort = NULL; - } - else - { - qDebug("change to valid port"); - quint16 pg = current.internalId() >> 16; - mCurrentPort = pgl->mPortGroups[pgl->indexOfPortGroup(pg)]->mPorts[current.row()]; - } - reset(); -} +#include "stream.h" +#include "streammodel.h" +#include "portgrouplist.h" +#include "qicon.h" + +StreamModel::StreamModel(PortGroupList *p, QObject *parent) + : QAbstractTableModel(parent) +{ + pgl = p; + mCurrentPort = NULL; +} + +int StreamModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) + return 0; + + if (mCurrentPort) + return mCurrentPort->numStreams(); + else + return 0; +} + +int StreamModel::columnCount(const QModelIndex &parent ) const +{ + return (int) StreamMaxFields; +} + +Qt::ItemFlags StreamModel::flags(const QModelIndex &index) const +{ + Qt::ItemFlags flags = QAbstractTableModel::flags(index); + + + switch (index.column()) + { + case StreamIcon: + break; + case StreamName: + flags |= Qt::ItemIsEditable; + break; + case StreamStatus: + flags |= Qt::ItemIsUserCheckable; + break; + case StreamNextWhat: + flags |= Qt::ItemIsEditable; + break; + default: + //qFatal("Missed case in switch!"); + break; + } + + return flags; +} + +QVariant StreamModel::data(const QModelIndex &index, int role) const +{ + // Check for a valid index + if (!index.isValid()) + return QVariant(); + + // Check for row/column limits + if (index.row() >= mCurrentPort->numStreams()) + return QVariant(); + + if (index.column() >= StreamMaxFields) + return QVariant(); + + if (mCurrentPort == NULL) + return QVariant(); + + // Return data based on field and role + switch(index.column()) + { + case StreamIcon: + { + if (role == Qt::DecorationRole) + return QIcon(":/icons/stream_edit.png"); + else + return QVariant(); + break; + } + case StreamName: + { + if ((role == Qt::DisplayRole) || (role == Qt::EditRole)) + return mCurrentPort->streamByIndex(index.row())->name(); + else + return QVariant(); + break; + } + case StreamStatus: + { + if ((role == Qt::CheckStateRole)) + { + if (mCurrentPort->streamByIndex(index.row())->isEnabled()) + return Qt::Checked; + else + return Qt::Unchecked; + } + else + return QVariant(); + break; + } + case StreamNextWhat: + { + int val = mCurrentPort->streamByIndex(index.row())->nextWhat(); + + if (role == Qt::DisplayRole) + return nextWhatOptionList().at(val); + else if (role == Qt::EditRole) + return val; + else + return QVariant(); + + break; + } + default: + qFatal("-------------UNHANDLED STREAM FIELD----------------"); + } + + return QVariant(); +} + +bool StreamModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (mCurrentPort == NULL) + return false; + + if (index.isValid()) + { + switch (index.column()) + { + // Edit Supported Fields + case StreamName: + mCurrentPort->streamByIndex(index.row())->setName(value.toString()); + emit(dataChanged(index, index)); + return true; + + case StreamStatus: + mCurrentPort->streamByIndex(index.row())->setEnabled(value.toBool()); + emit(dataChanged(index, index)); + return true; + + case StreamNextWhat: + if (role == Qt::EditRole) + { + mCurrentPort->streamByIndex(index.row())->setNextWhat( + (Stream::NextWhat)value.toInt()); + emit(dataChanged(index, index)); + return true; + } + else + return false; + + // Edit Not Supported Fields + case StreamIcon: + return false; + + // Unhandled Stream Field + default: + qDebug("-------------UNHANDLED STREAM FIELD----------------"); + break; + } + } + + return false; +} + +QVariant StreamModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (role != Qt::DisplayRole) + return QVariant(); + + if (orientation == Qt::Horizontal) + { + switch(section) + { + case StreamIcon: + return QString(""); + break; + case StreamName: + return QString("Name"); + break; + case StreamStatus: + return QString(""); + break; + case StreamNextWhat: + return QString("Goto"); + break; + default: + qDebug("-------------UNHANDLED STREAM FIELD----------------"); + break; + } + } + else + return QString("%1").arg(section+1); + + return QVariant(); +} + +bool StreamModel::insertRows(int row, int count, const QModelIndex &parent) +{ + qDebug("insertRows() row = %d", row); + qDebug("insertRows() count = %d", count); + beginInsertRows(QModelIndex(), row, row+count-1); + for (int i = 0; i < count; i++) + mCurrentPort->newStreamAt(row); + endInsertRows(); + + return true; +} + +bool StreamModel::removeRows(int row, int count, const QModelIndex &parent) +{ + qDebug("removeRows() row = %d", row); + qDebug("removeRows() count = %d", count); + beginRemoveRows(QModelIndex(), row, row+count-1); + for (int i = 0; i < count; i++) + { + mCurrentPort->deleteStreamAt(row); + } + endRemoveRows(); + + return true; +} + +// --------------------- SLOTS ------------------------ + +void StreamModel::setCurrentPortIndex(const QModelIndex ¤t) +{ + if (!current.isValid() || !pgl->isPort(current)) + { + qDebug("current is either invalid or not a port"); + mCurrentPort = NULL; + } + else + { + qDebug("change to valid port"); + quint16 pg = current.internalId() >> 16; + mCurrentPort = pgl->mPortGroups[pgl->indexOfPortGroup(pg)]->mPorts[current.row()]; + } + reset(); +} diff --git a/client/streammodel.h b/client/streammodel.h index c65b4d9..e73bb18 100644 --- a/client/streammodel.h +++ b/client/streammodel.h @@ -1,57 +1,57 @@ -#ifndef _STREAM_MODEL_H -#define _STREAM_MODEL_H - -#include -#include -#include "port.h" - -class PortGroupList; - -class StreamModel : public QAbstractTableModel -{ - Q_OBJECT - - Port *mCurrentPort; - PortGroupList *pgl; - - public: - StreamModel(PortGroupList *p, QObject *parent = 0); - - int rowCount(const QModelIndex &parent = QModelIndex()) const; - int columnCount(const QModelIndex &parent = QModelIndex()) const; - Qt::ItemFlags flags(const QModelIndex &index) const; - QVariant data(const QModelIndex &index, int role) const; - bool setData(const QModelIndex &index, const QVariant &value, - int role = Qt::EditRole); - QVariant headerData(int section, Qt::Orientation orientation, - int role = Qt::DisplayRole) const; - bool insertRows (int row, int count, - const QModelIndex & parent = QModelIndex()); - bool removeRows (int row, int count, - const QModelIndex & parent = QModelIndex()); - -#if 0 // CleanedUp! - // FIXME(HIGH): This *is* like a kludge - QList* currentPortStreamList() - { return &mCurrentPort->mStreams; } -#endif - - public: - enum StreamFields { - StreamIcon = 0, - StreamName, - StreamStatus, - StreamNextWhat, - - StreamMaxFields - }; - - static QStringList nextWhatOptionList() - { return QStringList() << "Stop" << "Next" << "Goto first"; } - - public slots: - void setCurrentPortIndex(const QModelIndex ¤t); - -}; - -#endif +#ifndef _STREAM_MODEL_H +#define _STREAM_MODEL_H + +#include +#include +#include "port.h" + +class PortGroupList; + +class StreamModel : public QAbstractTableModel +{ + Q_OBJECT + + Port *mCurrentPort; + PortGroupList *pgl; + + public: + StreamModel(PortGroupList *p, QObject *parent = 0); + + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + QVariant data(const QModelIndex &index, int role) const; + bool setData(const QModelIndex &index, const QVariant &value, + int role = Qt::EditRole); + QVariant headerData(int section, Qt::Orientation orientation, + int role = Qt::DisplayRole) const; + bool insertRows (int row, int count, + const QModelIndex & parent = QModelIndex()); + bool removeRows (int row, int count, + const QModelIndex & parent = QModelIndex()); + +#if 0 // CleanedUp! + // FIXME(HIGH): This *is* like a kludge + QList* currentPortStreamList() + { return &mCurrentPort->mStreams; } +#endif + + public: + enum StreamFields { + StreamIcon = 0, + StreamName, + StreamStatus, + StreamNextWhat, + + StreamMaxFields + }; + + static QStringList nextWhatOptionList() + { return QStringList() << "Stop" << "Next" << "Goto first"; } + + public slots: + void setCurrentPortIndex(const QModelIndex ¤t); + +}; + +#endif diff --git a/common/protocol.proto b/common/protocol.proto index c8bdc05..42caff1 100644 --- a/common/protocol.proto +++ b/common/protocol.proto @@ -1,210 +1,210 @@ -// stream.proto - -package OstProto; - -message StreamId { - required uint32 id = 1; -} - -message StreamCore { - enum FrameLengthMode { - e_fl_fixed = 0; - e_fl_inc = 1; - e_fl_dec = 2; - e_fl_random = 3; - } - - // Basics - optional string name = 1; - optional bool is_enabled = 2; - optional uint32 ordinal = 3; - - // Frame Length (includes CRC) - optional FrameLengthMode len_mode = 14 [default = e_fl_fixed]; - optional uint32 frame_len = 15 [default = 64]; - optional uint32 frame_len_min = 16 [default = 64]; - optional uint32 frame_len_max = 17 [default = 1518]; - - // Currently Selected Protocols - //repeated uint32 frame_proto = 20; -} - -message StreamControl { - enum SendUnit { - e_su_packets = 0; - e_su_bursts = 1; - } - - enum SendMode { - e_sm_fixed = 0; - e_sm_continuous = 1; - } - - enum NextWhat { - e_nw_stop = 0; - e_nw_goto_next = 1; - e_nw_goto_id = 2; - } - - optional SendUnit unit = 1 [default = e_su_packets]; - optional SendMode mode = 2 [default = e_sm_fixed]; - optional uint32 num_packets = 3 [default = 1]; - optional uint32 num_bursts = 4 [default = 1]; - optional uint32 packets_per_burst = 5 [default = 10]; - optional NextWhat next = 6 [default = e_nw_goto_next]; - optional uint32 packets_per_sec = 7 [default = 1]; - optional uint32 bursts_per_sec = 8 [default = 1]; -} - -message ProtocolId { - required uint32 id = 1; -} - -message Protocol { - - required ProtocolId protocol_id = 1; - - extensions 51 to 100; // Reserved for Ostinato Use - extensions 101 to 200; // Available for use by protocols - - enum k { - kMacFieldNumber = 51; - kPayloadFieldNumber = 52; - kSampleFieldNumber = 53; - kUserScriptFieldNumber = 54; - - kEth2FieldNumber = 121; - kDot3FieldNumber = 122; - kLlcFieldNumber = 123; - kSnapFieldNumber = 124; - - kSvlanFieldNumber = 125; - kVlanFieldNumber = 126; - - kDot2LlcFieldNumber = 127; - kDot2SnapFieldNumber = 128; - kVlanStackFieldNumber = 129; - - kIp4FieldNumber = 130; - kArpFieldNumber = 131; - - kTcpFieldNumber = 140; - kUdpFieldNumber = 141; - kIcmpFieldNumber = 142; - kIgmpFieldNumber = 143; - } -} - -message Stream { - - required StreamId stream_id = 1; - optional StreamCore core = 2; - optional StreamControl control = 3; - - repeated Protocol protocol = 4; -} - -message Void { - // nothing! -} - -message Ack { - //! \todo (LOW) do we need any fields in 'Ack' -} - -message PortId { - required uint32 id = 1; -} - -message PortIdList { - repeated PortId port_id = 1; -} - -message StreamIdList { - required PortId port_id = 1; - repeated StreamId stream_id = 2; -} - -message Port { - required PortId port_id = 1; - optional string name = 2; - optional string description = 3; - optional bool is_enabled = 4; - optional bool is_exclusive_control = 6; -} - -message PortConfigList { - repeated Port port = 1; -} - -message StreamConfigList { - required PortId port_id = 1; - repeated Stream stream = 2; -} - -message CaptureBuffer { - //! \todo (HIGH) define CaptureBuffer -} - -message CaptureBufferList { - repeated CaptureBuffer list = 1; -} - -enum LinkState { - LinkStateUnknown = 0; - LinkStateDown = 1; - LinkStateUp = 2; -} - -message PortState { - optional LinkState link_state = 1 [default = LinkStateUnknown]; - optional bool is_transmit_on = 2 [default = false]; - optional bool is_capture_on = 3 [default = false]; -} - -message PortStats { - - required PortId port_id = 1; - - optional PortState state = 2; - - optional uint64 rx_pkts = 11; - optional uint64 rx_bytes = 12; - optional uint64 rx_pkts_nic = 13; - optional uint64 rx_bytes_nic = 14; - optional uint64 rx_pps = 15; - optional uint64 rx_bps = 16; - - optional uint64 tx_pkts = 21; - optional uint64 tx_bytes = 22; - optional uint64 tx_pkts_nic = 23; - optional uint64 tx_bytes_nic = 24; - optional uint64 tx_pps = 25; - optional uint64 tx_bps = 26; -} - -message PortStatsList { - repeated PortStats port_stats = 1; -} - -service OstService { - rpc getPortIdList(Void) returns (PortIdList); - rpc getPortConfig(PortIdList) returns (PortConfigList); - - rpc getStreamIdList(PortId) returns (StreamIdList); - rpc getStreamConfig(StreamIdList) returns (StreamConfigList); - rpc addStream(StreamIdList) returns (Ack); - rpc deleteStream(StreamIdList) returns (Ack); - rpc modifyStream(StreamConfigList) returns (Ack); - - rpc startTx(PortIdList) returns (Ack); - rpc stopTx(PortIdList) returns (Ack); - - rpc startCapture(PortIdList) returns (Ack); - rpc stopCapture(PortIdList) returns (Ack); - rpc getCaptureBuffer(PortId) returns (CaptureBuffer); - - rpc getStats(PortIdList) returns (PortStatsList); - rpc clearStats(PortIdList) returns (Ack); -} - +// stream.proto + +package OstProto; + +message StreamId { + required uint32 id = 1; +} + +message StreamCore { + enum FrameLengthMode { + e_fl_fixed = 0; + e_fl_inc = 1; + e_fl_dec = 2; + e_fl_random = 3; + } + + // Basics + optional string name = 1; + optional bool is_enabled = 2; + optional uint32 ordinal = 3; + + // Frame Length (includes CRC) + optional FrameLengthMode len_mode = 14 [default = e_fl_fixed]; + optional uint32 frame_len = 15 [default = 64]; + optional uint32 frame_len_min = 16 [default = 64]; + optional uint32 frame_len_max = 17 [default = 1518]; + + // Currently Selected Protocols + //repeated uint32 frame_proto = 20; +} + +message StreamControl { + enum SendUnit { + e_su_packets = 0; + e_su_bursts = 1; + } + + enum SendMode { + e_sm_fixed = 0; + e_sm_continuous = 1; + } + + enum NextWhat { + e_nw_stop = 0; + e_nw_goto_next = 1; + e_nw_goto_id = 2; + } + + optional SendUnit unit = 1 [default = e_su_packets]; + optional SendMode mode = 2 [default = e_sm_fixed]; + optional uint32 num_packets = 3 [default = 1]; + optional uint32 num_bursts = 4 [default = 1]; + optional uint32 packets_per_burst = 5 [default = 10]; + optional NextWhat next = 6 [default = e_nw_goto_next]; + optional uint32 packets_per_sec = 7 [default = 1]; + optional uint32 bursts_per_sec = 8 [default = 1]; +} + +message ProtocolId { + required uint32 id = 1; +} + +message Protocol { + + required ProtocolId protocol_id = 1; + + extensions 51 to 100; // Reserved for Ostinato Use + extensions 101 to 200; // Available for use by protocols + + enum k { + kMacFieldNumber = 51; + kPayloadFieldNumber = 52; + kSampleFieldNumber = 53; + kUserScriptFieldNumber = 54; + + kEth2FieldNumber = 121; + kDot3FieldNumber = 122; + kLlcFieldNumber = 123; + kSnapFieldNumber = 124; + + kSvlanFieldNumber = 125; + kVlanFieldNumber = 126; + + kDot2LlcFieldNumber = 127; + kDot2SnapFieldNumber = 128; + kVlanStackFieldNumber = 129; + + kIp4FieldNumber = 130; + kArpFieldNumber = 131; + + kTcpFieldNumber = 140; + kUdpFieldNumber = 141; + kIcmpFieldNumber = 142; + kIgmpFieldNumber = 143; + } +} + +message Stream { + + required StreamId stream_id = 1; + optional StreamCore core = 2; + optional StreamControl control = 3; + + repeated Protocol protocol = 4; +} + +message Void { + // nothing! +} + +message Ack { + //! \todo (LOW) do we need any fields in 'Ack' +} + +message PortId { + required uint32 id = 1; +} + +message PortIdList { + repeated PortId port_id = 1; +} + +message StreamIdList { + required PortId port_id = 1; + repeated StreamId stream_id = 2; +} + +message Port { + required PortId port_id = 1; + optional string name = 2; + optional string description = 3; + optional bool is_enabled = 4; + optional bool is_exclusive_control = 6; +} + +message PortConfigList { + repeated Port port = 1; +} + +message StreamConfigList { + required PortId port_id = 1; + repeated Stream stream = 2; +} + +message CaptureBuffer { + //! \todo (HIGH) define CaptureBuffer +} + +message CaptureBufferList { + repeated CaptureBuffer list = 1; +} + +enum LinkState { + LinkStateUnknown = 0; + LinkStateDown = 1; + LinkStateUp = 2; +} + +message PortState { + optional LinkState link_state = 1 [default = LinkStateUnknown]; + optional bool is_transmit_on = 2 [default = false]; + optional bool is_capture_on = 3 [default = false]; +} + +message PortStats { + + required PortId port_id = 1; + + optional PortState state = 2; + + optional uint64 rx_pkts = 11; + optional uint64 rx_bytes = 12; + optional uint64 rx_pkts_nic = 13; + optional uint64 rx_bytes_nic = 14; + optional uint64 rx_pps = 15; + optional uint64 rx_bps = 16; + + optional uint64 tx_pkts = 21; + optional uint64 tx_bytes = 22; + optional uint64 tx_pkts_nic = 23; + optional uint64 tx_bytes_nic = 24; + optional uint64 tx_pps = 25; + optional uint64 tx_bps = 26; +} + +message PortStatsList { + repeated PortStats port_stats = 1; +} + +service OstService { + rpc getPortIdList(Void) returns (PortIdList); + rpc getPortConfig(PortIdList) returns (PortConfigList); + + rpc getStreamIdList(PortId) returns (StreamIdList); + rpc getStreamConfig(StreamIdList) returns (StreamConfigList); + rpc addStream(StreamIdList) returns (Ack); + rpc deleteStream(StreamIdList) returns (Ack); + rpc modifyStream(StreamConfigList) returns (Ack); + + rpc startTx(PortIdList) returns (Ack); + rpc stopTx(PortIdList) returns (Ack); + + rpc startCapture(PortIdList) returns (Ack); + rpc stopCapture(PortIdList) returns (Ack); + rpc getCaptureBuffer(PortId) returns (CaptureBuffer); + + rpc getStats(PortIdList) returns (PortStatsList); + rpc clearStats(PortIdList) returns (Ack); +} + diff --git a/rpc/pbhelper.h b/rpc/pbhelper.h index ba2b5fe..e87d4ca 100644 --- a/rpc/pbhelper.h +++ b/rpc/pbhelper.h @@ -1,151 +1,151 @@ -#ifndef _PB_HELPER_H -#define _PB_HELPER_H - -#include -#include - -#include - -#if 0 // not reqd. any longer? -class PbHelper -{ -public: - - // FIXME: Change msg from * to & - void ForceSetSingularDefault(::google::protobuf::Message *msg) - { - const ::google::protobuf::Descriptor *desc; - ::google::protobuf::Message::Reflection *refl; - - qDebug("In %s", __FUNCTION__); - - desc = msg->GetDescriptor(); - refl = msg->GetReflection(); - - for (int i=0; i < desc->field_count(); i++) - { - const ::google::protobuf::FieldDescriptor *f; - - f = desc->field(i); - - // Ensure field is singular and not already set - if (f->label() == - ::google::protobuf::FieldDescriptor::LABEL_REPEATED) - continue; - if (refl->HasField(f)) - continue; - - switch(f->type()) - { - case ::google::protobuf::FieldDescriptor::TYPE_DOUBLE: - refl->SetDouble(f, refl->GetDouble(f)); - break; - - case ::google::protobuf::FieldDescriptor::TYPE_FLOAT: - refl->SetFloat(f, refl->GetFloat(f)); - break; - - case ::google::protobuf::FieldDescriptor::TYPE_INT32: - case ::google::protobuf::FieldDescriptor::TYPE_SINT32: - case ::google::protobuf::FieldDescriptor::TYPE_SFIXED32: - refl->SetInt32(f, refl->GetInt32(f)); - break; - - case ::google::protobuf::FieldDescriptor::TYPE_INT64: - case ::google::protobuf::FieldDescriptor::TYPE_SINT64: - case ::google::protobuf::FieldDescriptor::TYPE_SFIXED64: - refl->SetInt64(f, refl->GetInt64(f)); - break; - - case ::google::protobuf::FieldDescriptor::TYPE_UINT32: - case ::google::protobuf::FieldDescriptor::TYPE_FIXED32: - refl->SetUInt32(f, refl->GetUInt32(f)); - break; - - case ::google::protobuf::FieldDescriptor::TYPE_UINT64: - case ::google::protobuf::FieldDescriptor::TYPE_FIXED64: - refl->SetUInt64(f, refl->GetUInt64(f)); - break; - - case ::google::protobuf::FieldDescriptor::TYPE_BOOL: - refl->SetBool(f, refl->GetBool(f)); - break; - - case ::google::protobuf::FieldDescriptor::TYPE_ENUM: - refl->SetEnum(f, refl->GetEnum(f)); - break; - - case ::google::protobuf::FieldDescriptor::TYPE_STRING: - case ::google::protobuf::FieldDescriptor::TYPE_BYTES: - refl->SetString(f, refl->GetString(f)); - break; - - case ::google::protobuf::FieldDescriptor::TYPE_MESSAGE: - case ::google::protobuf::FieldDescriptor::TYPE_GROUP: - ForceSetSingularDefault(refl->MutableMessage(f)); // recursion! - break; - - default: - qDebug("unhandled Field Type"); - break; - } - } - } - - bool update( - ::google::protobuf::Message *target, - ::google::protobuf::Message *source) - { - // FIXME(HI): Depracate: use MergeFrom() directly - qDebug("In %s", __FUNCTION__); - target->MergeFrom(*source); - return true; -#if 0 - ::google::protobuf::Message::Reflection *sourceRef; - ::google::protobuf::Message::Reflection *targetRef; - std::vector srcFieldList; - - - if (source->GetDescriptor()->full_name() != - target->GetDescriptor()->full_name()) - goto _error_exit; - - sourceRef = source->GetReflection(); - targetRef = target->GetReflection(); - - sourceRef->ListFields(&srcFieldList); - for (uint i=0; i < srcFieldList.size(); i++) - { - const ::google::protobuf::FieldDescriptor *srcField, *targetField; - - srcField = srcFieldList[i]; - targetField = target->GetDescriptor()->FindFieldByName( - srcField->name()); - - switch(targetField->type()) - { - case ::google::protobuf::FieldDescriptor::TYPE_UINT32: - targetRef->SetUInt32(targetField, - sourceRef->GetUInt32(srcField)); - break; - case ::google::protobuf::FieldDescriptor::TYPE_BOOL: - targetRef->SetBool(targetField, - sourceRef->GetBool(srcField)); - break; - case ::google::protobuf::FieldDescriptor::TYPE_STRING: - targetRef->SetString(targetField, - sourceRef->GetString(srcField)); - break; - default: - qDebug("unhandled Field Type"); - break; - } - } - _error_exit: - qDebug("%s: error!", __FUNCTION__); - return false; -#endif - } -}; -#endif -#endif +#ifndef _PB_HELPER_H +#define _PB_HELPER_H + +#include +#include + +#include + +#if 0 // not reqd. any longer? +class PbHelper +{ +public: + + // FIXME: Change msg from * to & + void ForceSetSingularDefault(::google::protobuf::Message *msg) + { + const ::google::protobuf::Descriptor *desc; + ::google::protobuf::Message::Reflection *refl; + + qDebug("In %s", __FUNCTION__); + + desc = msg->GetDescriptor(); + refl = msg->GetReflection(); + + for (int i=0; i < desc->field_count(); i++) + { + const ::google::protobuf::FieldDescriptor *f; + + f = desc->field(i); + + // Ensure field is singular and not already set + if (f->label() == + ::google::protobuf::FieldDescriptor::LABEL_REPEATED) + continue; + if (refl->HasField(f)) + continue; + + switch(f->type()) + { + case ::google::protobuf::FieldDescriptor::TYPE_DOUBLE: + refl->SetDouble(f, refl->GetDouble(f)); + break; + + case ::google::protobuf::FieldDescriptor::TYPE_FLOAT: + refl->SetFloat(f, refl->GetFloat(f)); + break; + + case ::google::protobuf::FieldDescriptor::TYPE_INT32: + case ::google::protobuf::FieldDescriptor::TYPE_SINT32: + case ::google::protobuf::FieldDescriptor::TYPE_SFIXED32: + refl->SetInt32(f, refl->GetInt32(f)); + break; + + case ::google::protobuf::FieldDescriptor::TYPE_INT64: + case ::google::protobuf::FieldDescriptor::TYPE_SINT64: + case ::google::protobuf::FieldDescriptor::TYPE_SFIXED64: + refl->SetInt64(f, refl->GetInt64(f)); + break; + + case ::google::protobuf::FieldDescriptor::TYPE_UINT32: + case ::google::protobuf::FieldDescriptor::TYPE_FIXED32: + refl->SetUInt32(f, refl->GetUInt32(f)); + break; + + case ::google::protobuf::FieldDescriptor::TYPE_UINT64: + case ::google::protobuf::FieldDescriptor::TYPE_FIXED64: + refl->SetUInt64(f, refl->GetUInt64(f)); + break; + + case ::google::protobuf::FieldDescriptor::TYPE_BOOL: + refl->SetBool(f, refl->GetBool(f)); + break; + + case ::google::protobuf::FieldDescriptor::TYPE_ENUM: + refl->SetEnum(f, refl->GetEnum(f)); + break; + + case ::google::protobuf::FieldDescriptor::TYPE_STRING: + case ::google::protobuf::FieldDescriptor::TYPE_BYTES: + refl->SetString(f, refl->GetString(f)); + break; + + case ::google::protobuf::FieldDescriptor::TYPE_MESSAGE: + case ::google::protobuf::FieldDescriptor::TYPE_GROUP: + ForceSetSingularDefault(refl->MutableMessage(f)); // recursion! + break; + + default: + qDebug("unhandled Field Type"); + break; + } + } + } + + bool update( + ::google::protobuf::Message *target, + ::google::protobuf::Message *source) + { + // FIXME(HI): Depracate: use MergeFrom() directly + qDebug("In %s", __FUNCTION__); + target->MergeFrom(*source); + return true; +#if 0 + ::google::protobuf::Message::Reflection *sourceRef; + ::google::protobuf::Message::Reflection *targetRef; + std::vector srcFieldList; + + + if (source->GetDescriptor()->full_name() != + target->GetDescriptor()->full_name()) + goto _error_exit; + + sourceRef = source->GetReflection(); + targetRef = target->GetReflection(); + + sourceRef->ListFields(&srcFieldList); + for (uint i=0; i < srcFieldList.size(); i++) + { + const ::google::protobuf::FieldDescriptor *srcField, *targetField; + + srcField = srcFieldList[i]; + targetField = target->GetDescriptor()->FindFieldByName( + srcField->name()); + + switch(targetField->type()) + { + case ::google::protobuf::FieldDescriptor::TYPE_UINT32: + targetRef->SetUInt32(targetField, + sourceRef->GetUInt32(srcField)); + break; + case ::google::protobuf::FieldDescriptor::TYPE_BOOL: + targetRef->SetBool(targetField, + sourceRef->GetBool(srcField)); + break; + case ::google::protobuf::FieldDescriptor::TYPE_STRING: + targetRef->SetString(targetField, + sourceRef->GetString(srcField)); + break; + default: + qDebug("unhandled Field Type"); + break; + } + } + _error_exit: + qDebug("%s: error!", __FUNCTION__); + return false; +#endif + } +}; +#endif +#endif diff --git a/rpc/pbrpc.pro b/rpc/pbrpc.pro index 3465da3..bcd5b8d 100644 --- a/rpc/pbrpc.pro +++ b/rpc/pbrpc.pro @@ -1,8 +1,8 @@ -TEMPLATE = lib -CONFIG += qt staticlib -QT += network -DEFINES += HAVE_REMOTE -INCLUDEPATH += "c:\msys\1.0\local\include" -LIBS += -L"C:\msys\1.0\local\lib" -lprotobuf -HEADERS += rpcserver.h pbrpccontroller.h pbrpcchannel.h -SOURCES += rpcserver.cpp pbrpcchannel.cpp +TEMPLATE = lib +CONFIG += qt staticlib +QT += network +DEFINES += HAVE_REMOTE +INCLUDEPATH += "c:\msys\1.0\local\include" +LIBS += -L"C:\msys\1.0\local\lib" -lprotobuf +HEADERS += rpcserver.h pbrpccontroller.h pbrpcchannel.h +SOURCES += rpcserver.cpp pbrpcchannel.cpp diff --git a/rpc/pbrpcchannel.cpp b/rpc/pbrpcchannel.cpp index 5c3626e..a06d14e 100644 --- a/rpc/pbrpcchannel.cpp +++ b/rpc/pbrpcchannel.cpp @@ -1,310 +1,310 @@ -#include "pbrpcchannel.h" - -PbRpcChannel::PbRpcChannel(QHostAddress ip, quint16 port) -{ - isPending = false; - pendingMethodId = -1; // don't care as long as isPending is false - - controller = NULL; - done = NULL; - response = NULL; - - mServerAddress = ip; - mServerPort = port; - mpSocket = new QTcpSocket(this); - - // FIXME: Not quite sure why this ain't working! - // QMetaObject::connectSlotsByName(this); - - connect(mpSocket, SIGNAL(connected()), - this, SLOT(on_mpSocket_connected())); - connect(mpSocket, SIGNAL(disconnected()), - this, SLOT(on_mpSocket_disconnected())); - connect(mpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), - this, SLOT(on_mpSocket_stateChanged(QAbstractSocket::SocketState))); - connect(mpSocket, SIGNAL(error(QAbstractSocket::SocketError)), - this, SLOT(on_mpSocket_error(QAbstractSocket::SocketError))); - - connect(mpSocket, SIGNAL(readyRead()), - this, SLOT(on_mpSocket_readyRead())); - -} - -PbRpcChannel::~PbRpcChannel() -{ - delete mpSocket; -} - -void PbRpcChannel::establish() -{ - qDebug("In %s", __FUNCTION__); - - mpSocket->connectToHost(mServerAddress, mServerPort); -} - -void PbRpcChannel::establish(QHostAddress ip, quint16 port) -{ - mServerAddress = ip; - mServerPort = port; - establish(); -} - -void PbRpcChannel::tearDown() -{ - qDebug("In %s", __FUNCTION__); - - mpSocket->disconnectFromHost(); -} - -void PbRpcChannel::CallMethod( - const ::google::protobuf::MethodDescriptor *method, - ::google::protobuf::RpcController *controller, - const ::google::protobuf::Message *req, - ::google::protobuf::Message *response, - ::google::protobuf::Closure* done) -{ - char msg[MSGBUF_SIZE]; - int len; - bool ret; - - if (isPending) - { - RpcCall call; - qDebug("RpcChannel: queueing method %d since %d is pending", - method->index(), pendingMethodId); - - call.method = method; - call.controller = controller; - call.request = req; - call.response = response; - call.done = done; - - pendingCallList.append(call); - - Q_ASSERT(pendingCallList.size() < 100); - - return; - } - - if (!req->IsInitialized()) - { - qWarning("RpcChannel: missing required fields in request"); - qDebug(req->InitializationErrorString().c_str()); - - qFatal("exiting"); - - controller->SetFailed("Required fields missing"); - done->Run(); - return; - } - - pendingMethodId = method->index(); - this->controller=controller; - this->done=done; - this->response=response; - isPending = true; - - ret = req->SerializeToArray((void*) (&msg[PB_HDR_SIZE]), sizeof(msg)); - Q_ASSERT(ret == true); - - len = req->ByteSize(); - *((quint16*)(&msg[0])) = HTONS(PB_MSG_TYPE_REQUEST); // type - *((quint16*)(&msg[2])) = HTONS(method->index()); // method id - *((quint32*)(&msg[4])) = HTONL(len); // len - - // Avoid printing stats since it happens every couple of seconds - if (pendingMethodId != 12) - { - qDebug("client(%s) sending %d bytes encoding <%s>", __FUNCTION__, - PB_HDR_SIZE + len, req->DebugString().c_str()); - BUFDUMP(msg, PB_HDR_SIZE + len); - } - - mpSocket->write(msg, PB_HDR_SIZE + len); -} - -void PbRpcChannel::on_mpSocket_readyRead() -{ - char msg[MSGBUF_SIZE]; - char *p = (char*)&msg; - int msgLen; - static bool parsing = false; - static quint16 type, method; - static quint32 len; - - //qDebug("%s: bytesAvail = %d", __FUNCTION__, mpSocket->bytesAvailable()); - - if (!parsing) - { - // Do we have an entire header? If not, we'll wait ... - if (mpSocket->bytesAvailable() < PB_HDR_SIZE) - { - qDebug("client: not enough data available for a complete header"); - return; - } - - msgLen = mpSocket->read(msg, PB_HDR_SIZE); - - Q_ASSERT(msgLen == PB_HDR_SIZE); - - type = NTOHS(GET16(p+0)); - method = NTOHS(GET16(p+2)); - len = NTOHL(GET32(p+4)); - - //BUFDUMP(msg, PB_HDR_SIZE); - //qDebug("type = %hu, method = %hu, len = %u", type, method, len); - - parsing = true; - } - - switch (type) - { - case PB_MSG_TYPE_BINBLOB: - { - static quint32 cumLen = 0; - QIODevice *blob; - - blob = static_cast(controller)->binaryBlob(); - Q_ASSERT(blob != NULL); - - while ((cumLen < len) && mpSocket->bytesAvailable()) - { - int l; - - l = mpSocket->read(msg, sizeof(msg)); - blob->write(msg, l); - cumLen += l; - } - - qDebug("%s: bin blob rcvd %d/%d", __PRETTY_FUNCTION__, cumLen, len); - - if (cumLen < len) - return; - - cumLen = 0; - - if (!isPending) - { - qDebug("not waiting for response"); - goto _error_exit; - } - - if (pendingMethodId != method) - { - qDebug("invalid method id %d (expected = %d)", method, - pendingMethodId); - goto _error_exit; - } - - break; - } - - case PB_MSG_TYPE_RESPONSE: - // Wait till we have the entire message - if (mpSocket->bytesAvailable() < len) - { - qDebug("client: not enough data available for a complete msg"); - return; - } - - msgLen = mpSocket->read(msg, sizeof(msg)); - - Q_ASSERT((unsigned) msgLen == len); - - //qDebug("client(%s) rcvd %d bytes", __FUNCTION__, msgLen); - //BUFDUMP(msg, msgLen); - - if (!isPending) - { - qDebug("not waiting for response"); - goto _error_exit; - } - - if (pendingMethodId != method) - { - qDebug("invalid method id %d (expected = %d)", method, - pendingMethodId); - goto _error_exit; - } - - response->ParseFromArray((void*) msg, len); - - // Avoid printing stats - if (method != 12) - { - qDebug("client(%s): Parsed as %s", __FUNCTION__, - response->DebugString().c_str()); - } - - if (!response->IsInitialized()) - { - qWarning("RpcChannel: missing required fields in response"); - qDebug(response->InitializationErrorString().c_str()); - - controller->SetFailed("Required fields missing"); - } - break; - - default: - qFatal("%s: unexpected type %d", __PRETTY_FUNCTION__, type); - goto _error_exit; - - } - - pendingMethodId = -1; - controller = NULL; - response = NULL; - isPending = false; - parsing = false; - - done->Run(); - - if (pendingCallList.size()) - { - RpcCall call = pendingCallList.takeFirst(); - CallMethod(call.method, call.controller, call.request, call.response, - call.done); - } - - return; - -_error_exit: - parsing = false; - qDebug("client(%s) discarding received msg", __FUNCTION__); - return; -} - -void PbRpcChannel::on_mpSocket_stateChanged( - QAbstractSocket::SocketState socketState) -{ - qDebug("In %s", __FUNCTION__); - emit stateChanged(socketState); -} - -void PbRpcChannel::on_mpSocket_connected() -{ - qDebug("In %s", __FUNCTION__); - emit connected(); -} - -void PbRpcChannel::on_mpSocket_disconnected() -{ - qDebug("In %s", __FUNCTION__); - - pendingMethodId = -1; - controller = NULL; - response = NULL; - isPending = false; - // \todo convert parsing from static to data member - //parsing = false - pendingCallList.clear(); - - emit disconnected(); -} - -void PbRpcChannel::on_mpSocket_error(QAbstractSocket::SocketError socketError) -{ - qDebug("In %s", __FUNCTION__); - emit error(socketError); -} - +#include "pbrpcchannel.h" + +PbRpcChannel::PbRpcChannel(QHostAddress ip, quint16 port) +{ + isPending = false; + pendingMethodId = -1; // don't care as long as isPending is false + + controller = NULL; + done = NULL; + response = NULL; + + mServerAddress = ip; + mServerPort = port; + mpSocket = new QTcpSocket(this); + + // FIXME: Not quite sure why this ain't working! + // QMetaObject::connectSlotsByName(this); + + connect(mpSocket, SIGNAL(connected()), + this, SLOT(on_mpSocket_connected())); + connect(mpSocket, SIGNAL(disconnected()), + this, SLOT(on_mpSocket_disconnected())); + connect(mpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), + this, SLOT(on_mpSocket_stateChanged(QAbstractSocket::SocketState))); + connect(mpSocket, SIGNAL(error(QAbstractSocket::SocketError)), + this, SLOT(on_mpSocket_error(QAbstractSocket::SocketError))); + + connect(mpSocket, SIGNAL(readyRead()), + this, SLOT(on_mpSocket_readyRead())); + +} + +PbRpcChannel::~PbRpcChannel() +{ + delete mpSocket; +} + +void PbRpcChannel::establish() +{ + qDebug("In %s", __FUNCTION__); + + mpSocket->connectToHost(mServerAddress, mServerPort); +} + +void PbRpcChannel::establish(QHostAddress ip, quint16 port) +{ + mServerAddress = ip; + mServerPort = port; + establish(); +} + +void PbRpcChannel::tearDown() +{ + qDebug("In %s", __FUNCTION__); + + mpSocket->disconnectFromHost(); +} + +void PbRpcChannel::CallMethod( + const ::google::protobuf::MethodDescriptor *method, + ::google::protobuf::RpcController *controller, + const ::google::protobuf::Message *req, + ::google::protobuf::Message *response, + ::google::protobuf::Closure* done) +{ + char msg[MSGBUF_SIZE]; + int len; + bool ret; + + if (isPending) + { + RpcCall call; + qDebug("RpcChannel: queueing method %d since %d is pending", + method->index(), pendingMethodId); + + call.method = method; + call.controller = controller; + call.request = req; + call.response = response; + call.done = done; + + pendingCallList.append(call); + + Q_ASSERT(pendingCallList.size() < 100); + + return; + } + + if (!req->IsInitialized()) + { + qWarning("RpcChannel: missing required fields in request"); + qDebug(req->InitializationErrorString().c_str()); + + qFatal("exiting"); + + controller->SetFailed("Required fields missing"); + done->Run(); + return; + } + + pendingMethodId = method->index(); + this->controller=controller; + this->done=done; + this->response=response; + isPending = true; + + ret = req->SerializeToArray((void*) (&msg[PB_HDR_SIZE]), sizeof(msg)); + Q_ASSERT(ret == true); + + len = req->ByteSize(); + *((quint16*)(&msg[0])) = HTONS(PB_MSG_TYPE_REQUEST); // type + *((quint16*)(&msg[2])) = HTONS(method->index()); // method id + *((quint32*)(&msg[4])) = HTONL(len); // len + + // Avoid printing stats since it happens every couple of seconds + if (pendingMethodId != 12) + { + qDebug("client(%s) sending %d bytes encoding <%s>", __FUNCTION__, + PB_HDR_SIZE + len, req->DebugString().c_str()); + BUFDUMP(msg, PB_HDR_SIZE + len); + } + + mpSocket->write(msg, PB_HDR_SIZE + len); +} + +void PbRpcChannel::on_mpSocket_readyRead() +{ + char msg[MSGBUF_SIZE]; + char *p = (char*)&msg; + int msgLen; + static bool parsing = false; + static quint16 type, method; + static quint32 len; + + //qDebug("%s: bytesAvail = %d", __FUNCTION__, mpSocket->bytesAvailable()); + + if (!parsing) + { + // Do we have an entire header? If not, we'll wait ... + if (mpSocket->bytesAvailable() < PB_HDR_SIZE) + { + qDebug("client: not enough data available for a complete header"); + return; + } + + msgLen = mpSocket->read(msg, PB_HDR_SIZE); + + Q_ASSERT(msgLen == PB_HDR_SIZE); + + type = NTOHS(GET16(p+0)); + method = NTOHS(GET16(p+2)); + len = NTOHL(GET32(p+4)); + + //BUFDUMP(msg, PB_HDR_SIZE); + //qDebug("type = %hu, method = %hu, len = %u", type, method, len); + + parsing = true; + } + + switch (type) + { + case PB_MSG_TYPE_BINBLOB: + { + static quint32 cumLen = 0; + QIODevice *blob; + + blob = static_cast(controller)->binaryBlob(); + Q_ASSERT(blob != NULL); + + while ((cumLen < len) && mpSocket->bytesAvailable()) + { + int l; + + l = mpSocket->read(msg, sizeof(msg)); + blob->write(msg, l); + cumLen += l; + } + + qDebug("%s: bin blob rcvd %d/%d", __PRETTY_FUNCTION__, cumLen, len); + + if (cumLen < len) + return; + + cumLen = 0; + + if (!isPending) + { + qDebug("not waiting for response"); + goto _error_exit; + } + + if (pendingMethodId != method) + { + qDebug("invalid method id %d (expected = %d)", method, + pendingMethodId); + goto _error_exit; + } + + break; + } + + case PB_MSG_TYPE_RESPONSE: + // Wait till we have the entire message + if (mpSocket->bytesAvailable() < len) + { + qDebug("client: not enough data available for a complete msg"); + return; + } + + msgLen = mpSocket->read(msg, sizeof(msg)); + + Q_ASSERT((unsigned) msgLen == len); + + //qDebug("client(%s) rcvd %d bytes", __FUNCTION__, msgLen); + //BUFDUMP(msg, msgLen); + + if (!isPending) + { + qDebug("not waiting for response"); + goto _error_exit; + } + + if (pendingMethodId != method) + { + qDebug("invalid method id %d (expected = %d)", method, + pendingMethodId); + goto _error_exit; + } + + response->ParseFromArray((void*) msg, len); + + // Avoid printing stats + if (method != 12) + { + qDebug("client(%s): Parsed as %s", __FUNCTION__, + response->DebugString().c_str()); + } + + if (!response->IsInitialized()) + { + qWarning("RpcChannel: missing required fields in response"); + qDebug(response->InitializationErrorString().c_str()); + + controller->SetFailed("Required fields missing"); + } + break; + + default: + qFatal("%s: unexpected type %d", __PRETTY_FUNCTION__, type); + goto _error_exit; + + } + + pendingMethodId = -1; + controller = NULL; + response = NULL; + isPending = false; + parsing = false; + + done->Run(); + + if (pendingCallList.size()) + { + RpcCall call = pendingCallList.takeFirst(); + CallMethod(call.method, call.controller, call.request, call.response, + call.done); + } + + return; + +_error_exit: + parsing = false; + qDebug("client(%s) discarding received msg", __FUNCTION__); + return; +} + +void PbRpcChannel::on_mpSocket_stateChanged( + QAbstractSocket::SocketState socketState) +{ + qDebug("In %s", __FUNCTION__); + emit stateChanged(socketState); +} + +void PbRpcChannel::on_mpSocket_connected() +{ + qDebug("In %s", __FUNCTION__); + emit connected(); +} + +void PbRpcChannel::on_mpSocket_disconnected() +{ + qDebug("In %s", __FUNCTION__); + + pendingMethodId = -1; + controller = NULL; + response = NULL; + isPending = false; + // \todo convert parsing from static to data member + //parsing = false + pendingCallList.clear(); + + emit disconnected(); +} + +void PbRpcChannel::on_mpSocket_error(QAbstractSocket::SocketError socketError) +{ + qDebug("In %s", __FUNCTION__); + emit error(socketError); +} + diff --git a/rpc/pbrpcchannel.h b/rpc/pbrpcchannel.h index e467781..8c2efbc 100644 --- a/rpc/pbrpcchannel.h +++ b/rpc/pbrpcchannel.h @@ -1,83 +1,83 @@ -#ifndef _PB_RPC_CHANNEL_H -#define _PB_RPC_CHANNEL_H - -#include -#include - -#include -#include -#include - -#include "pbrpccommon.h" -#include "pbrpccontroller.h" - -class PbRpcChannel : public QObject, public ::google::protobuf::RpcChannel -{ - Q_OBJECT - - // If isPending is TRUE, then controller, done, response - // and pendingMethodId correspond to the last method called by - // the service stub - bool isPending; - int pendingMethodId; - - // controller, done, response are set to the corresponding values - // passed by the stub to CallMethod(). They are reset to NULL when - // we get a response back from the server in on_mpSocket_readyRead() - // after calling done->Run(). - - /*! \todo (MED) : change controller, done and response to references - instead of pointers? */ - ::google::protobuf::RpcController *controller; - ::google::protobuf::Closure *done; - ::google::protobuf::Message *response; - - typedef struct _RpcCall { - const ::google::protobuf::MethodDescriptor *method; - ::google::protobuf::RpcController *controller; - const ::google::protobuf::Message *request; - ::google::protobuf::Message *response; - ::google::protobuf::Closure *done; - } RpcCall; - QList pendingCallList; - - QHostAddress mServerAddress; - quint16 mServerPort; - QTcpSocket *mpSocket; - -public: - PbRpcChannel(QHostAddress ip, quint16 port); - ~PbRpcChannel(); - - void establish(); - void establish(QHostAddress ip, quint16 port); - void tearDown(); - - const QHostAddress& serverAddress() const { return mServerAddress; } - quint16 serverPort() const { return mServerPort; } - - QAbstractSocket::SocketState state() const - { return mpSocket->state(); } - - void CallMethod(const ::google::protobuf::MethodDescriptor *method, - ::google::protobuf::RpcController *controller, - const ::google::protobuf::Message *req, - ::google::protobuf::Message *response, - ::google::protobuf::Closure* done); - -signals: - void connected(); - void disconnected(); - void error(QAbstractSocket::SocketError socketError); - void stateChanged(QAbstractSocket::SocketState socketState); - -private slots: - void on_mpSocket_connected(); - void on_mpSocket_disconnected(); - void on_mpSocket_stateChanged(QAbstractSocket::SocketState socketState); - void on_mpSocket_error(QAbstractSocket::SocketError socketError); - - void on_mpSocket_readyRead(); -}; - -#endif +#ifndef _PB_RPC_CHANNEL_H +#define _PB_RPC_CHANNEL_H + +#include +#include + +#include +#include +#include + +#include "pbrpccommon.h" +#include "pbrpccontroller.h" + +class PbRpcChannel : public QObject, public ::google::protobuf::RpcChannel +{ + Q_OBJECT + + // If isPending is TRUE, then controller, done, response + // and pendingMethodId correspond to the last method called by + // the service stub + bool isPending; + int pendingMethodId; + + // controller, done, response are set to the corresponding values + // passed by the stub to CallMethod(). They are reset to NULL when + // we get a response back from the server in on_mpSocket_readyRead() + // after calling done->Run(). + + /*! \todo (MED) : change controller, done and response to references + instead of pointers? */ + ::google::protobuf::RpcController *controller; + ::google::protobuf::Closure *done; + ::google::protobuf::Message *response; + + typedef struct _RpcCall { + const ::google::protobuf::MethodDescriptor *method; + ::google::protobuf::RpcController *controller; + const ::google::protobuf::Message *request; + ::google::protobuf::Message *response; + ::google::protobuf::Closure *done; + } RpcCall; + QList pendingCallList; + + QHostAddress mServerAddress; + quint16 mServerPort; + QTcpSocket *mpSocket; + +public: + PbRpcChannel(QHostAddress ip, quint16 port); + ~PbRpcChannel(); + + void establish(); + void establish(QHostAddress ip, quint16 port); + void tearDown(); + + const QHostAddress& serverAddress() const { return mServerAddress; } + quint16 serverPort() const { return mServerPort; } + + QAbstractSocket::SocketState state() const + { return mpSocket->state(); } + + void CallMethod(const ::google::protobuf::MethodDescriptor *method, + ::google::protobuf::RpcController *controller, + const ::google::protobuf::Message *req, + ::google::protobuf::Message *response, + ::google::protobuf::Closure* done); + +signals: + void connected(); + void disconnected(); + void error(QAbstractSocket::SocketError socketError); + void stateChanged(QAbstractSocket::SocketState socketState); + +private slots: + void on_mpSocket_connected(); + void on_mpSocket_disconnected(); + void on_mpSocket_stateChanged(QAbstractSocket::SocketState socketState); + void on_mpSocket_error(QAbstractSocket::SocketError socketError); + + void on_mpSocket_readyRead(); +}; + +#endif diff --git a/rpc/pbrpccommon.h b/rpc/pbrpccommon.h index 4ea1281..12040ee 100644 --- a/rpc/pbrpccommon.h +++ b/rpc/pbrpccommon.h @@ -1,61 +1,61 @@ -#ifndef _PB_RPC_COMMON_H -#define _PB_RPC_COMMON_H - -//! \todo (LOW) check which one is right - wrong one seems to be working!!!!! -#if 0 -#define GET16(p) (quint16)( \ - (*((quint8*)(p)+0) << 8 ) \ - | (*((quint8*)(p)+1))) -#else -#define GET16(p) (quint16)( \ - (*((quint8*)(p)+1) << 8 ) \ - | (*((quint8*)(p)+0))) -#define GET32(p) (quint32)( \ - (*((quint8*)(p)+3) << 24) \ - | (*((quint8*)(p)+2) << 16) \ - | (*((quint8*)(p)+1) << 8 ) \ - | (*((quint8*)(p)+0))) -#endif - -#define BYTESWAP4(x) \ - (((x & 0xFF000000) >> 24) | \ - ((x & 0x00FF0000) >> 8) | \ - ((x & 0x0000FF00) << 8) | \ - ((x & 0x000000FF) << 24)) - -#define BYTESWAP2(x) \ - (((x & 0xFF00) >> 8) | \ - ((x & 0x00FF) << 8)) - -//! \todo (LOW) : portability -#if 1 -#define HTONL(x) BYTESWAP4(x) -#define NTOHL(x) BYTESWAP4(x) -#define HTONS(x) BYTESWAP2(x) -#define NTOHS(x) BYTESWAP2(x) -#else -#define HTONL(x) (x) -#define NTOHL(x) (x) -#define HTONS(x) (x) -#define NTOHS(x) (x) -#endif - -// Print a HexDump -#define BUFDUMP(ptr, len) qDebug("%s", QString(QByteArray((char*)(ptr), \ - (len)).toHex()).toAscii().data()); - -/* -** RPC Header (8) -** - MSG_TYPE (2) -** - METHOD_ID (2) -** - LEN (4) [not including this header] -*/ -#define PB_HDR_SIZE 8 - -#define PB_MSG_TYPE_REQUEST 1 -#define PB_MSG_TYPE_RESPONSE 2 -#define PB_MSG_TYPE_BINBLOB 3 - -#define MSGBUF_SIZE 4096 - -#endif +#ifndef _PB_RPC_COMMON_H +#define _PB_RPC_COMMON_H + +//! \todo (LOW) check which one is right - wrong one seems to be working!!!!! +#if 0 +#define GET16(p) (quint16)( \ + (*((quint8*)(p)+0) << 8 ) \ + | (*((quint8*)(p)+1))) +#else +#define GET16(p) (quint16)( \ + (*((quint8*)(p)+1) << 8 ) \ + | (*((quint8*)(p)+0))) +#define GET32(p) (quint32)( \ + (*((quint8*)(p)+3) << 24) \ + | (*((quint8*)(p)+2) << 16) \ + | (*((quint8*)(p)+1) << 8 ) \ + | (*((quint8*)(p)+0))) +#endif + +#define BYTESWAP4(x) \ + (((x & 0xFF000000) >> 24) | \ + ((x & 0x00FF0000) >> 8) | \ + ((x & 0x0000FF00) << 8) | \ + ((x & 0x000000FF) << 24)) + +#define BYTESWAP2(x) \ + (((x & 0xFF00) >> 8) | \ + ((x & 0x00FF) << 8)) + +//! \todo (LOW) : portability +#if 1 +#define HTONL(x) BYTESWAP4(x) +#define NTOHL(x) BYTESWAP4(x) +#define HTONS(x) BYTESWAP2(x) +#define NTOHS(x) BYTESWAP2(x) +#else +#define HTONL(x) (x) +#define NTOHL(x) (x) +#define HTONS(x) (x) +#define NTOHS(x) (x) +#endif + +// Print a HexDump +#define BUFDUMP(ptr, len) qDebug("%s", QString(QByteArray((char*)(ptr), \ + (len)).toHex()).toAscii().data()); + +/* +** RPC Header (8) +** - MSG_TYPE (2) +** - METHOD_ID (2) +** - LEN (4) [not including this header] +*/ +#define PB_HDR_SIZE 8 + +#define PB_MSG_TYPE_REQUEST 1 +#define PB_MSG_TYPE_RESPONSE 2 +#define PB_MSG_TYPE_BINBLOB 3 + +#define MSGBUF_SIZE 4096 + +#endif diff --git a/rpc/pbrpccontroller.h b/rpc/pbrpccontroller.h index b446c73..99acc5a 100644 --- a/rpc/pbrpccontroller.h +++ b/rpc/pbrpccontroller.h @@ -1,34 +1,34 @@ -#ifndef _PB_RPC_CONTROLLER_H -#define _PB_RPC_CONTROLLER_H - -#include - -class QIODevice; - -class PbRpcController : public ::google::protobuf::RpcController -{ - bool failed; - QIODevice *blob; - std::string errStr; - -public: - PbRpcController() { Reset(); } - - // Client Side Methods - void Reset() { failed=false; blob = NULL; } - bool Failed() const { return failed; } - void StartCancel() { /*! \todo (MED) */} - std::string ErrorText() const { return errStr; } - - // Server Side Methods - void SetFailed(const std::string &reason) - { failed = true; errStr = reason; } - bool IsCanceled() const { return false; }; - void NotifyOnCancel(::google::protobuf::Closure *callback) { /*! \todo (MED) */ } - - // srivatsp added - QIODevice* binaryBlob() { return blob; }; - void setBinaryBlob(QIODevice *binaryBlob) { blob = binaryBlob; }; -}; - -#endif +#ifndef _PB_RPC_CONTROLLER_H +#define _PB_RPC_CONTROLLER_H + +#include + +class QIODevice; + +class PbRpcController : public ::google::protobuf::RpcController +{ + bool failed; + QIODevice *blob; + std::string errStr; + +public: + PbRpcController() { Reset(); } + + // Client Side Methods + void Reset() { failed=false; blob = NULL; } + bool Failed() const { return failed; } + void StartCancel() { /*! \todo (MED) */} + std::string ErrorText() const { return errStr; } + + // Server Side Methods + void SetFailed(const std::string &reason) + { failed = true; errStr = reason; } + bool IsCanceled() const { return false; }; + void NotifyOnCancel(::google::protobuf::Closure *callback) { /*! \todo (MED) */ } + + // srivatsp added + QIODevice* binaryBlob() { return blob; }; + void setBinaryBlob(QIODevice *binaryBlob) { blob = binaryBlob; }; +}; + +#endif diff --git a/rpc/rpcserver.cpp b/rpc/rpcserver.cpp index 804c4ee..d85c753 100644 --- a/rpc/rpcserver.cpp +++ b/rpc/rpcserver.cpp @@ -1,256 +1,256 @@ -//#include "pbhelper.h" -#include "rpcserver.h" - -RpcServer::RpcServer() -{ - server = NULL; - clientSock = NULL; - - service = NULL; - - isPending = false; - pendingMethodId = -1; // don't care as long as isPending is false -} - -RpcServer::~RpcServer() -{ - if (server) - delete server; -} - -bool RpcServer::registerService(::google::protobuf::Service *service, - quint16 tcpPortNum) -{ - this->service = service; - - server = new QTcpServer(); - connect(server, SIGNAL(newConnection()), this, SLOT(when_newConnection())); - if (!server->listen(QHostAddress::Any, tcpPortNum)) - { - qDebug("Unable to start the server: %s", - server->errorString().toAscii().constData()); - errorString_ = QString("Error starting Ostinato server: %1").arg( - server->errorString()); - return false; - } - - qDebug("The server is running on %s: %d", - server->serverAddress().toString().toAscii().constData(), - server->serverPort()); - errorString_ = QString(); - return true; -} - -QString RpcServer::errorString() -{ - return errorString_; -} - -void RpcServer::done(::google::protobuf::Message *resp, PbRpcController *PbRpcController) -{ - QIODevice *blob; - char msg[MSGBUF_SIZE]; - int len; - - //qDebug("In RpcServer::done"); - - if (PbRpcController->Failed()) - { - qDebug("rpc failed"); - goto _exit; - } - - blob = PbRpcController->binaryBlob(); - if (blob) - { - len = blob->size(); - qDebug("is binary blob of len %d", len); - - *((quint16*)(&msg[0])) = HTONS(PB_MSG_TYPE_BINBLOB); // type - *((quint16*)(&msg[2])) = HTONS(pendingMethodId); // method - (*(quint32*)(&msg[4])) = HTONL(len); // len - - clientSock->write(msg, PB_HDR_SIZE); - - blob->seek(0); - while (!blob->atEnd()) - { - int l; - - len = blob->read(msg, sizeof(msg)); - l = clientSock->write(msg, len); - Q_ASSERT(l == len); - } - - goto _exit; - } - - if (!resp->IsInitialized()) - { - qWarning("response missing required fields!!"); - qDebug(resp->InitializationErrorString().c_str()); - qFatal("exiting"); - goto _exit; - } - - resp->SerializeToArray((void*) &msg[PB_HDR_SIZE], sizeof(msg)); - - len = resp->ByteSize(); - - *((quint16*)(&msg[0])) = HTONS(PB_MSG_TYPE_RESPONSE); // type - *((quint16*)(&msg[2])) = HTONS(pendingMethodId); // method - *((quint32*)(&msg[4])) = HTONL(len); // len - - // Avoid printing stats since it happens once every couple of seconds - if (pendingMethodId != 12) - { - qDebug("Server(%s): sending %d bytes to client encoding <%s>", - __FUNCTION__, len + PB_HDR_SIZE, resp->DebugString().c_str()); - //BUFDUMP(msg, len + 8); - } - - clientSock->write(msg, PB_HDR_SIZE + len); - -_exit: - delete PbRpcController; - isPending = false; -} - -void RpcServer::when_newConnection() -{ - if (clientSock) - { - QTcpSocket *sock; - - qDebug("already connected, no new connections will be accepted"); - - // Accept and close connection - //! \todo (MED) Send reason msg to client - sock = server->nextPendingConnection(); - sock->disconnectFromHost(); - sock->deleteLater(); - goto _exit; - } - - clientSock = server->nextPendingConnection(); - qDebug("accepting new connection from %s: %d", - clientSock->peerAddress().toString().toAscii().constData(), - clientSock->peerPort()); - - connect(clientSock, SIGNAL(readyRead()), - this, SLOT(when_dataAvail())); - connect(clientSock, SIGNAL(disconnected()), - this, SLOT(when_disconnected())); - connect(clientSock, SIGNAL(error(QAbstractSocket::SocketError)), - this, SLOT(when_error(QAbstractSocket::SocketError))); - -_exit: - return; -} - -void RpcServer::when_disconnected() -{ - qDebug("connection closed from %s: %d", - clientSock->peerAddress().toString().toAscii().constData(), - clientSock->peerPort()); - - clientSock->deleteLater(); - clientSock = NULL; -} - -void RpcServer::when_error(QAbstractSocket::SocketError socketError) -{ - qDebug("%s", clientSock->errorString().toAscii().constData()); -} - -void RpcServer::when_dataAvail() -{ - char msg[MSGBUF_SIZE]; - int msgLen; - static bool parsing = false; - static quint16 type, method; - static quint32 len; - const ::google::protobuf::MethodDescriptor *methodDesc; - ::google::protobuf::Message *req, *resp; - PbRpcController *controller; - - if (!parsing) - { - if (clientSock->bytesAvailable() < PB_HDR_SIZE) - return; - - msgLen = clientSock->read(msg, PB_HDR_SIZE); - - Q_ASSERT(msgLen == PB_HDR_SIZE); - - type = NTOHS(GET16(&msg[0])); - method = NTOHS(GET16(&msg[2])); - len = NTOHL(GET32(&msg[4])); - //qDebug("type = %d, method = %d, len = %d", type, method, len); - - parsing = true; - } - - if (clientSock->bytesAvailable() < len) - return; - - msgLen = clientSock->read(msg, sizeof(msg)); - Q_ASSERT((unsigned) msgLen == len); - - if (type != PB_MSG_TYPE_REQUEST) - { - qDebug("server(%s): unexpected msg type %d (expected %d)", __FUNCTION__, - type, PB_MSG_TYPE_REQUEST); - goto _error_exit; - } - - methodDesc = service->GetDescriptor()->method(method); - if (!methodDesc) - { - qDebug("server(%s): invalid method id %d", __FUNCTION__, method); - goto _error_exit; //! \todo Return Error to client - } - - if (isPending) - { - qDebug("server(%s): rpc pending, try again", __FUNCTION__); - goto _error_exit; //! \todo Return Error to client - } - - pendingMethodId = method; - isPending = true; - - req = service->GetRequestPrototype(methodDesc).New(); - resp = service->GetResponsePrototype(methodDesc).New(); - - req->ParseFromArray((void*)msg, len); - if (!req->IsInitialized()) - { - qWarning("Missing required fields in request"); - qDebug(req->InitializationErrorString().c_str()); - qFatal("exiting"); - delete req; - delete resp; - - goto _error_exit; - } - //qDebug("Server(%s): successfully parsed as <%s>", __FUNCTION__, - //resp->DebugString().c_str()); - - controller = new PbRpcController; - - //qDebug("before service->callmethod()"); - - service->CallMethod(methodDesc, controller, req, resp, - NewCallback(this, &RpcServer::done, resp, controller)); - - parsing = false; - - return; - -_error_exit: - parsing = false; - qDebug("server(%s): discarding msg from client", __FUNCTION__); - return; -} - +//#include "pbhelper.h" +#include "rpcserver.h" + +RpcServer::RpcServer() +{ + server = NULL; + clientSock = NULL; + + service = NULL; + + isPending = false; + pendingMethodId = -1; // don't care as long as isPending is false +} + +RpcServer::~RpcServer() +{ + if (server) + delete server; +} + +bool RpcServer::registerService(::google::protobuf::Service *service, + quint16 tcpPortNum) +{ + this->service = service; + + server = new QTcpServer(); + connect(server, SIGNAL(newConnection()), this, SLOT(when_newConnection())); + if (!server->listen(QHostAddress::Any, tcpPortNum)) + { + qDebug("Unable to start the server: %s", + server->errorString().toAscii().constData()); + errorString_ = QString("Error starting Ostinato server: %1").arg( + server->errorString()); + return false; + } + + qDebug("The server is running on %s: %d", + server->serverAddress().toString().toAscii().constData(), + server->serverPort()); + errorString_ = QString(); + return true; +} + +QString RpcServer::errorString() +{ + return errorString_; +} + +void RpcServer::done(::google::protobuf::Message *resp, PbRpcController *PbRpcController) +{ + QIODevice *blob; + char msg[MSGBUF_SIZE]; + int len; + + //qDebug("In RpcServer::done"); + + if (PbRpcController->Failed()) + { + qDebug("rpc failed"); + goto _exit; + } + + blob = PbRpcController->binaryBlob(); + if (blob) + { + len = blob->size(); + qDebug("is binary blob of len %d", len); + + *((quint16*)(&msg[0])) = HTONS(PB_MSG_TYPE_BINBLOB); // type + *((quint16*)(&msg[2])) = HTONS(pendingMethodId); // method + (*(quint32*)(&msg[4])) = HTONL(len); // len + + clientSock->write(msg, PB_HDR_SIZE); + + blob->seek(0); + while (!blob->atEnd()) + { + int l; + + len = blob->read(msg, sizeof(msg)); + l = clientSock->write(msg, len); + Q_ASSERT(l == len); + } + + goto _exit; + } + + if (!resp->IsInitialized()) + { + qWarning("response missing required fields!!"); + qDebug(resp->InitializationErrorString().c_str()); + qFatal("exiting"); + goto _exit; + } + + resp->SerializeToArray((void*) &msg[PB_HDR_SIZE], sizeof(msg)); + + len = resp->ByteSize(); + + *((quint16*)(&msg[0])) = HTONS(PB_MSG_TYPE_RESPONSE); // type + *((quint16*)(&msg[2])) = HTONS(pendingMethodId); // method + *((quint32*)(&msg[4])) = HTONL(len); // len + + // Avoid printing stats since it happens once every couple of seconds + if (pendingMethodId != 12) + { + qDebug("Server(%s): sending %d bytes to client encoding <%s>", + __FUNCTION__, len + PB_HDR_SIZE, resp->DebugString().c_str()); + //BUFDUMP(msg, len + 8); + } + + clientSock->write(msg, PB_HDR_SIZE + len); + +_exit: + delete PbRpcController; + isPending = false; +} + +void RpcServer::when_newConnection() +{ + if (clientSock) + { + QTcpSocket *sock; + + qDebug("already connected, no new connections will be accepted"); + + // Accept and close connection + //! \todo (MED) Send reason msg to client + sock = server->nextPendingConnection(); + sock->disconnectFromHost(); + sock->deleteLater(); + goto _exit; + } + + clientSock = server->nextPendingConnection(); + qDebug("accepting new connection from %s: %d", + clientSock->peerAddress().toString().toAscii().constData(), + clientSock->peerPort()); + + connect(clientSock, SIGNAL(readyRead()), + this, SLOT(when_dataAvail())); + connect(clientSock, SIGNAL(disconnected()), + this, SLOT(when_disconnected())); + connect(clientSock, SIGNAL(error(QAbstractSocket::SocketError)), + this, SLOT(when_error(QAbstractSocket::SocketError))); + +_exit: + return; +} + +void RpcServer::when_disconnected() +{ + qDebug("connection closed from %s: %d", + clientSock->peerAddress().toString().toAscii().constData(), + clientSock->peerPort()); + + clientSock->deleteLater(); + clientSock = NULL; +} + +void RpcServer::when_error(QAbstractSocket::SocketError socketError) +{ + qDebug("%s", clientSock->errorString().toAscii().constData()); +} + +void RpcServer::when_dataAvail() +{ + char msg[MSGBUF_SIZE]; + int msgLen; + static bool parsing = false; + static quint16 type, method; + static quint32 len; + const ::google::protobuf::MethodDescriptor *methodDesc; + ::google::protobuf::Message *req, *resp; + PbRpcController *controller; + + if (!parsing) + { + if (clientSock->bytesAvailable() < PB_HDR_SIZE) + return; + + msgLen = clientSock->read(msg, PB_HDR_SIZE); + + Q_ASSERT(msgLen == PB_HDR_SIZE); + + type = NTOHS(GET16(&msg[0])); + method = NTOHS(GET16(&msg[2])); + len = NTOHL(GET32(&msg[4])); + //qDebug("type = %d, method = %d, len = %d", type, method, len); + + parsing = true; + } + + if (clientSock->bytesAvailable() < len) + return; + + msgLen = clientSock->read(msg, sizeof(msg)); + Q_ASSERT((unsigned) msgLen == len); + + if (type != PB_MSG_TYPE_REQUEST) + { + qDebug("server(%s): unexpected msg type %d (expected %d)", __FUNCTION__, + type, PB_MSG_TYPE_REQUEST); + goto _error_exit; + } + + methodDesc = service->GetDescriptor()->method(method); + if (!methodDesc) + { + qDebug("server(%s): invalid method id %d", __FUNCTION__, method); + goto _error_exit; //! \todo Return Error to client + } + + if (isPending) + { + qDebug("server(%s): rpc pending, try again", __FUNCTION__); + goto _error_exit; //! \todo Return Error to client + } + + pendingMethodId = method; + isPending = true; + + req = service->GetRequestPrototype(methodDesc).New(); + resp = service->GetResponsePrototype(methodDesc).New(); + + req->ParseFromArray((void*)msg, len); + if (!req->IsInitialized()) + { + qWarning("Missing required fields in request"); + qDebug(req->InitializationErrorString().c_str()); + qFatal("exiting"); + delete req; + delete resp; + + goto _error_exit; + } + //qDebug("Server(%s): successfully parsed as <%s>", __FUNCTION__, + //resp->DebugString().c_str()); + + controller = new PbRpcController; + + //qDebug("before service->callmethod()"); + + service->CallMethod(methodDesc, controller, req, resp, + NewCallback(this, &RpcServer::done, resp, controller)); + + parsing = false; + + return; + +_error_exit: + parsing = false; + qDebug("server(%s): discarding msg from client", __FUNCTION__); + return; +} + diff --git a/rpc/rpcserver.h b/rpc/rpcserver.h index e353628..f4be419 100644 --- a/rpc/rpcserver.h +++ b/rpc/rpcserver.h @@ -1,44 +1,44 @@ -#ifndef _RPC_SERVER_H -#define _RPC_SERVER_H - -#include -#include -#include - -#include -#include - -#include "pbrpccommon.h" -#include "pbrpccontroller.h" - - -class RpcServer : public QObject -{ - Q_OBJECT - - QTcpServer *server; - QTcpSocket *clientSock; - - ::google::protobuf::Service *service; - - bool isPending; - int pendingMethodId; - QString errorString_; - -public: - RpcServer(); //! \todo (LOW) use 'parent' param - virtual ~RpcServer(); - - bool registerService(::google::protobuf::Service *service, - quint16 tcpPortNum); - QString errorString(); - void done(::google::protobuf::Message *resp, PbRpcController *controller); - -private slots: - void when_newConnection(); - void when_disconnected(); - void when_dataAvail(); - void when_error(QAbstractSocket::SocketError socketError); -}; - -#endif +#ifndef _RPC_SERVER_H +#define _RPC_SERVER_H + +#include +#include +#include + +#include +#include + +#include "pbrpccommon.h" +#include "pbrpccontroller.h" + + +class RpcServer : public QObject +{ + Q_OBJECT + + QTcpServer *server; + QTcpSocket *clientSock; + + ::google::protobuf::Service *service; + + bool isPending; + int pendingMethodId; + QString errorString_; + +public: + RpcServer(); //! \todo (LOW) use 'parent' param + virtual ~RpcServer(); + + bool registerService(::google::protobuf::Service *service, + quint16 tcpPortNum); + QString errorString(); + void done(::google::protobuf::Message *resp, PbRpcController *controller); + +private slots: + void when_newConnection(); + void when_disconnected(); + void when_dataAvail(); + void when_error(QAbstractSocket::SocketError socketError); +}; + +#endif diff --git a/server/drone.cpp b/server/drone.cpp index d7609de..9dcccc8 100644 --- a/server/drone.cpp +++ b/server/drone.cpp @@ -1,76 +1,76 @@ -#include "drone.h" - -#include "rpcserver.h" -#include "myservice.h" - -#include -#include - -extern int myport; - -Drone::Drone(QWidget *parent) - : QWidget(parent) -{ - setupUi(this); - - rpcServer = new RpcServer(); - service = new MyService(); -} - -Drone::~Drone() -{ - trayIcon_->hide(); - delete rpcServer; - delete service; -} - -bool Drone::init() -{ - Q_ASSERT(rpcServer); - - if (!rpcServer->registerService(service, myport ? myport : 7878)) - { - QMessageBox::critical(0, qApp->applicationName(), - rpcServer->errorString()); - return false; - } - - trayIconMenu_ = new QMenu(this); - - trayIconMenu_->addAction(actionShow); - trayIconMenu_->addAction(actionExit); - trayIconMenu_->setDefaultAction(actionShow); - trayIcon_ = new QSystemTrayIcon(); - trayIcon_->setIcon(QIcon(":/icons/portgroup.png")); - trayIcon_->setToolTip(qApp->applicationName()); - trayIcon_->setContextMenu(trayIconMenu_); - trayIcon_->show(); - - connect(trayIcon_, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), - this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason))); - connect(this, SIGNAL(hideMe(bool)), this, SLOT(setHidden(bool)), - Qt::QueuedConnection); - - return true; -} - -void Drone::changeEvent(QEvent *event) -{ - if (event->type() == QEvent::WindowStateChange && isMinimized()) - { - emit hideMe(true); - event->ignore(); - return; - } - - QWidget::changeEvent(event); -} - -void Drone::trayIconActivated(QSystemTrayIcon::ActivationReason reason) -{ - if (reason == QSystemTrayIcon::DoubleClick) - { - showNormal(); - activateWindow(); - } -} +#include "drone.h" + +#include "rpcserver.h" +#include "myservice.h" + +#include +#include + +extern int myport; + +Drone::Drone(QWidget *parent) + : QWidget(parent) +{ + setupUi(this); + + rpcServer = new RpcServer(); + service = new MyService(); +} + +Drone::~Drone() +{ + trayIcon_->hide(); + delete rpcServer; + delete service; +} + +bool Drone::init() +{ + Q_ASSERT(rpcServer); + + if (!rpcServer->registerService(service, myport ? myport : 7878)) + { + QMessageBox::critical(0, qApp->applicationName(), + rpcServer->errorString()); + return false; + } + + trayIconMenu_ = new QMenu(this); + + trayIconMenu_->addAction(actionShow); + trayIconMenu_->addAction(actionExit); + trayIconMenu_->setDefaultAction(actionShow); + trayIcon_ = new QSystemTrayIcon(); + trayIcon_->setIcon(QIcon(":/icons/portgroup.png")); + trayIcon_->setToolTip(qApp->applicationName()); + trayIcon_->setContextMenu(trayIconMenu_); + trayIcon_->show(); + + connect(trayIcon_, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), + this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason))); + connect(this, SIGNAL(hideMe(bool)), this, SLOT(setHidden(bool)), + Qt::QueuedConnection); + + return true; +} + +void Drone::changeEvent(QEvent *event) +{ + if (event->type() == QEvent::WindowStateChange && isMinimized()) + { + emit hideMe(true); + event->ignore(); + return; + } + + QWidget::changeEvent(event); +} + +void Drone::trayIconActivated(QSystemTrayIcon::ActivationReason reason) +{ + if (reason == QSystemTrayIcon::DoubleClick) + { + showNormal(); + activateWindow(); + } +} diff --git a/server/drone.h b/server/drone.h index c441af7..c8d9ff2 100644 --- a/server/drone.h +++ b/server/drone.h @@ -1,37 +1,37 @@ -#ifndef _DRONE_H -#define _DRONE_H - -#include "ui_drone.h" - -#include -#include - -class RpcServer; -namespace OstProto { class OstService; } - -class Drone : public QWidget, Ui::Drone -{ - Q_OBJECT - -public: - Drone(QWidget *parent = 0); - ~Drone(); - bool init(); - -signals: - void hideMe(bool hidden); - -protected: - void changeEvent(QEvent *event); - -private: - QSystemTrayIcon *trayIcon_; - QMenu *trayIconMenu_; - RpcServer *rpcServer; - OstProto::OstService *service; - -private slots: - void trayIconActivated(QSystemTrayIcon::ActivationReason reason); - -}; -#endif +#ifndef _DRONE_H +#define _DRONE_H + +#include "ui_drone.h" + +#include +#include + +class RpcServer; +namespace OstProto { class OstService; } + +class Drone : public QWidget, Ui::Drone +{ + Q_OBJECT + +public: + Drone(QWidget *parent = 0); + ~Drone(); + bool init(); + +signals: + void hideMe(bool hidden); + +protected: + void changeEvent(QEvent *event); + +private: + QSystemTrayIcon *trayIcon_; + QMenu *trayIconMenu_; + RpcServer *rpcServer; + OstProto::OstService *service; + +private slots: + void trayIconActivated(QSystemTrayIcon::ActivationReason reason); + +}; +#endif diff --git a/server/drone.pro b/server/drone.pro index a402b4c..e33bb5c 100644 --- a/server/drone.pro +++ b/server/drone.pro @@ -1,26 +1,26 @@ -TEMPLATE = app -CONFIG += qt debug -QT += network script -DEFINES += HAVE_REMOTE WPCAP -INCLUDEPATH += "../rpc" -win32:LIBS += -lwpcap -lpacket -unix:LIBS += -lpcap -win32:LIBS += -L"../common/debug" -lostproto -unix:LIBS += -L"../common" -lostproto -win32:LIBS += -L"../rpc/debug" -lpbrpc -unix:LIBS += -L"../rpc" -lpbrpc -LIBS += -lprotobuf -POST_TARGETDEPS += "../common/debug/libostproto.a" "../rpc/debug/libpbrpc.a" -RESOURCES += drone.qrc -HEADERS += drone.h -FORMS += drone.ui -SOURCES += \ - drone_main.cpp \ - drone.cpp \ - portmanager.cpp \ - abstractport.cpp \ - pcapport.cpp \ - winpcapport.cpp -SOURCES += myservice.cpp -SOURCES += pcapextra.cpp - +TEMPLATE = app +CONFIG += qt debug +QT += network script +DEFINES += HAVE_REMOTE WPCAP +INCLUDEPATH += "../rpc" +win32:LIBS += -lwpcap -lpacket +unix:LIBS += -lpcap +win32:LIBS += -L"../common/debug" -lostproto +unix:LIBS += -L"../common" -lostproto +win32:LIBS += -L"../rpc/debug" -lpbrpc +unix:LIBS += -L"../rpc" -lpbrpc +LIBS += -lprotobuf +POST_TARGETDEPS += "../common/debug/libostproto.a" "../rpc/debug/libpbrpc.a" +RESOURCES += drone.qrc +HEADERS += drone.h +FORMS += drone.ui +SOURCES += \ + drone_main.cpp \ + drone.cpp \ + portmanager.cpp \ + abstractport.cpp \ + pcapport.cpp \ + winpcapport.cpp +SOURCES += myservice.cpp +SOURCES += pcapextra.cpp + diff --git a/server/drone_main.cpp b/server/drone_main.cpp index f6baad2..0bac7c1 100644 --- a/server/drone_main.cpp +++ b/server/drone_main.cpp @@ -1,25 +1,25 @@ -#include "drone.h" - -int myport; - -int main(int argc, char *argv[]) -{ - QApplication app(argc, argv); - Drone drone; - - app.setApplicationName(drone.objectName()); - - if (argc > 1) - myport = atoi(argv[1]); - - if (!drone.init()) - exit(-1); - - drone.setWindowFlags(drone.windowFlags() - | Qt::WindowMaximizeButtonHint - | Qt::WindowMinimizeButtonHint); - drone.showMinimized(); - app.exec(); - return 0; -} - +#include "drone.h" + +int myport; + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + Drone drone; + + app.setApplicationName(drone.objectName()); + + if (argc > 1) + myport = atoi(argv[1]); + + if (!drone.init()) + exit(-1); + + drone.setWindowFlags(drone.windowFlags() + | Qt::WindowMaximizeButtonHint + | Qt::WindowMinimizeButtonHint); + drone.showMinimized(); + app.exec(); + return 0; +} + diff --git a/server/myservice.cpp b/server/myservice.cpp index 4da9b7e..d043df9 100644 --- a/server/myservice.cpp +++ b/server/myservice.cpp @@ -1,421 +1,421 @@ - -#include "myservice.h" - -#if 0 -#include -#include -#include "qdebug.h" - -#include "../common/protocollistiterator.h" -#include "../common/abstractprotocol.h" -#endif - -#include "../common/streambase.h" -#include "../rpc/pbrpccontroller.h" -#include "portmanager.h" - -MyService::MyService() -{ - PortManager *portManager = PortManager::instance(); - int n = portManager->portCount(); - - for (int i = 0; i < n; i++) - portInfo.append(portManager->port(i)); -} - -MyService::~MyService() -{ -} - -void MyService::getPortIdList(::google::protobuf::RpcController* controller, - const ::OstProto::Void* request, - ::OstProto::PortIdList* response, - ::google::protobuf::Closure* done) -{ - qDebug("In %s", __PRETTY_FUNCTION__); - - for (int i = 0; i < portInfo.size(); i++) - { - ::OstProto::PortId *p; - - p = response->add_port_id(); - p->set_id(portInfo[i]->id()); - } - - done->Run(); -} - -void MyService::getPortConfig(::google::protobuf::RpcController* controller, - const ::OstProto::PortIdList* request, - ::OstProto::PortConfigList* response, - ::google::protobuf::Closure* done) -{ - qDebug("In %s", __PRETTY_FUNCTION__); - - for (int i = 0; i < request->port_id_size(); i++) - { - int id; - - id = request->port_id(i).id(); - if (id < portInfo.size()) - { - OstProto::Port *p; - - p = response->add_port(); - portInfo[id]->protoDataCopyInto(p); - } - } - - done->Run(); -} - -void MyService::getStreamIdList(::google::protobuf::RpcController* controller, - const ::OstProto::PortId* request, - ::OstProto::StreamIdList* response, - ::google::protobuf::Closure* done) -{ - int portId; - - qDebug("In %s", __PRETTY_FUNCTION__); - - portId = request->id(); - if ((portId < 0) || (portId >= portInfo.size())) - goto _invalid_port; - - response->mutable_port_id()->set_id(portId); - for (int i = 0; i < portInfo[portId]->streamCount(); i++) - { - OstProto::StreamId *s; - - s = response->add_stream_id(); - s->set_id(portInfo[portId]->stream(i)->id()); - } - done->Run(); - return; - -_invalid_port: - controller->SetFailed("Invalid Port Id"); - done->Run(); -} - -void MyService::getStreamConfig(::google::protobuf::RpcController* controller, - const ::OstProto::StreamIdList* request, - ::OstProto::StreamConfigList* response, - ::google::protobuf::Closure* done) -{ - int portId; - - qDebug("In %s", __PRETTY_FUNCTION__); - - portId = request->port_id().id(); - if ((portId < 0) || (portId >= portInfo.size())) - goto _invalid_port; - - response->mutable_port_id()->set_id(portId); - for (int i = 0; i < request->stream_id_size(); i++) - { - StreamBase *stream; - OstProto::Stream *s; - - stream = portInfo[portId]->stream(request->stream_id(i).id()); - if (!stream) - continue; //! \todo(LOW): Partial status of RPC - - s = response->add_stream(); - stream->protoDataCopyInto(*s); - } - done->Run(); - return; - -_invalid_port: - controller->SetFailed("invalid portid"); - done->Run(); -} - -void MyService::addStream(::google::protobuf::RpcController* controller, - const ::OstProto::StreamIdList* request, - ::OstProto::Ack* response, - ::google::protobuf::Closure* done) -{ - int portId; - - qDebug("In %s", __PRETTY_FUNCTION__); - - portId = request->port_id().id(); - if ((portId < 0) || (portId >= portInfo.size())) - goto _invalid_port; - - for (int i = 0; i < request->stream_id_size(); i++) - { - StreamBase *stream; - - // If stream with same id as in request exists already ==> error!! - stream = portInfo[portId]->stream(request->stream_id(i).id()); - if (stream) - continue; //! \todo (LOW): Partial status of RPC - - // Append a new "default" stream - actual contents of the new stream is - // expected in a subsequent "modifyStream" request - set the stream id - // now itself however!!! - stream = new StreamBase; - stream->setId(request->stream_id(i).id()); - portInfo[portId]->addStream(stream); - - } - - //! \todo (LOW): fill-in response "Ack"???? - - done->Run(); - return; - -_invalid_port: - controller->SetFailed("invalid portid"); - done->Run(); -} - -void MyService::deleteStream(::google::protobuf::RpcController* controller, - const ::OstProto::StreamIdList* request, - ::OstProto::Ack* response, - ::google::protobuf::Closure* done) -{ - int portId; - - qDebug("In %s", __PRETTY_FUNCTION__); - - portId = request->port_id().id(); - if ((portId < 0) || (portId >= portInfo.size())) - goto _invalid_port; - - for (int i = 0; i < request->stream_id_size(); i++) - portInfo[portId]->deleteStream(request->stream_id(i).id()); - - //! \todo (LOW): fill-in response "Ack"???? - - done->Run(); - return; - -_invalid_port: - controller->SetFailed("invalid portid"); - done->Run(); -} - -void MyService::modifyStream(::google::protobuf::RpcController* controller, - const ::OstProto::StreamConfigList* request, - ::OstProto::Ack* response, - ::google::protobuf::Closure* done) -{ - int portId; - - qDebug("In %s", __PRETTY_FUNCTION__); - - portId = request->port_id().id(); - if ((portId < 0) || (portId >= portInfo.size())) - goto _invalid_port; - - for (int i = 0; i < request->stream_size(); i++) - { - StreamBase *stream; - - stream = portInfo[portId]->stream(request->stream(i).stream_id().id()); - if (stream) - { - stream->protoDataCopyFrom(request->stream(i)); - portInfo[portId]->setDirty(); - } - } - - //! \todo(LOW): fill-in response "Ack"???? - - done->Run(); - return; - -_invalid_port: - controller->SetFailed("invalid portid"); - done->Run(); -} - -void MyService::startTx(::google::protobuf::RpcController* controller, - const ::OstProto::PortIdList* request, - ::OstProto::Ack* response, - ::google::protobuf::Closure* done) -{ - qDebug("In %s", __PRETTY_FUNCTION__); - - for (int i = 0; i < request->port_id_size(); i++) - { - int portId; - - portId = request->port_id(i).id(); - if ((portId < 0) || (portId >= portInfo.size())) - continue; //! \todo (LOW): partial RPC? - - portInfo[portId]->startTransmit(); - } - - //! \todo (LOW): fill-in response "Ack"???? - - done->Run(); -} - -void MyService::stopTx(::google::protobuf::RpcController* controller, - const ::OstProto::PortIdList* request, - ::OstProto::Ack* response, - ::google::protobuf::Closure* done) -{ - qDebug("In %s", __PRETTY_FUNCTION__); - - for (int i = 0; i < request->port_id_size(); i++) - { - int portId; - - portId = request->port_id(i).id(); - if ((portId < 0) || (portId >= portInfo.size())) - continue; //! \todo (LOW): partial RPC? - - portInfo[portId]->stopTransmit(); - } - - //! \todo (LOW): fill-in response "Ack"???? - - done->Run(); -} - -void MyService::startCapture(::google::protobuf::RpcController* controller, - const ::OstProto::PortIdList* request, - ::OstProto::Ack* response, - ::google::protobuf::Closure* done) -{ - qDebug("In %s", __PRETTY_FUNCTION__); - - for (int i = 0; i < request->port_id_size(); i++) - { - int portId; - - portId = request->port_id(i).id(); - if ((portId < 0) || (portId >= portInfo.size())) - continue; //! \todo (LOW): partial RPC? - - portInfo[portId]->startCapture(); - } - - //! \todo (LOW): fill-in response "Ack"???? - - done->Run(); -} - -void MyService::stopCapture(::google::protobuf::RpcController* controller, - const ::OstProto::PortIdList* request, - ::OstProto::Ack* response, - ::google::protobuf::Closure* done) -{ - qDebug("In %s", __PRETTY_FUNCTION__); - for (int i=0; i < request->port_id_size(); i++) - { - int portId; - - portId = request->port_id(i).id(); - if ((portId < 0) || (portId >= portInfo.size())) - continue; //! \todo (LOW): partial RPC? - - portInfo[portId]->stopCapture(); - } - - //! \todo (LOW): fill-in response "Ack"???? - - done->Run(); -} - -void MyService::getCaptureBuffer(::google::protobuf::RpcController* controller, - const ::OstProto::PortId* request, - ::OstProto::CaptureBuffer* response, - ::google::protobuf::Closure* done) -{ - int portId; - - qDebug("In %s", __PRETTY_FUNCTION__); - - portId = request->id(); - if ((portId < 0) || (portId >= portInfo.size())) - goto _invalid_port; - - portInfo[portId]->stopCapture(); - static_cast(controller)->setBinaryBlob( - portInfo[portId]->captureData()); - - done->Run(); - return; - -_invalid_port: - controller->SetFailed("invalid portid"); - done->Run(); -} - -void MyService::getStats(::google::protobuf::RpcController* controller, - const ::OstProto::PortIdList* request, - ::OstProto::PortStatsList* response, - ::google::protobuf::Closure* done) -{ - //qDebug("In %s", __PRETTY_FUNCTION__); - - for (int i = 0; i < request->port_id_size(); i++) - { - int portId; - AbstractPort::PortStats stats; - OstProto::PortStats *s; - OstProto::PortState *st; - - portId = request->port_id(i).id(); - if ((portId < 0) || (portId >= portInfo.size())) - continue; //! \todo(LOW): partial rpc? - - s = response->add_port_stats(); - s->mutable_port_id()->set_id(request->port_id(i).id()); - - st = s->mutable_state(); - st->set_link_state(portInfo[portId]->linkState()); - st->set_is_transmit_on(portInfo[portId]->isTransmitOn()); - st->set_is_capture_on(portInfo[portId]->isCaptureOn()); - - portInfo[portId]->stats(&stats); - -#if 0 - if (portId == 2) - qDebug(">%llu", stats.rxPkts); -#endif - - s->set_rx_pkts(stats.rxPkts); - s->set_rx_bytes(stats.rxBytes); - s->set_rx_pps(stats.rxPps); - s->set_rx_bps(stats.rxBps); - - s->set_tx_pkts(stats.txPkts); - s->set_tx_bytes(stats.txBytes); - s->set_tx_pps(stats.txPps); - s->set_tx_bps(stats.txBps); - } - - done->Run(); -} - -void MyService::clearStats(::google::protobuf::RpcController* controller, - const ::OstProto::PortIdList* request, - ::OstProto::Ack* response, - ::google::protobuf::Closure* done) -{ - qDebug("In %s", __PRETTY_FUNCTION__); - - for (int i = 0; i < request->port_id_size(); i++) - { - int portId; - - portId = request->port_id(i).id(); - if ((portId < 0) || (portId >= portInfo.size())) - continue; //! \todo (LOW): partial RPC? - - portInfo[portId]->resetStats(); - } - - //! \todo (LOW): fill-in response "Ack"???? - - done->Run(); -} + +#include "myservice.h" + +#if 0 +#include +#include +#include "qdebug.h" + +#include "../common/protocollistiterator.h" +#include "../common/abstractprotocol.h" +#endif + +#include "../common/streambase.h" +#include "../rpc/pbrpccontroller.h" +#include "portmanager.h" + +MyService::MyService() +{ + PortManager *portManager = PortManager::instance(); + int n = portManager->portCount(); + + for (int i = 0; i < n; i++) + portInfo.append(portManager->port(i)); +} + +MyService::~MyService() +{ +} + +void MyService::getPortIdList(::google::protobuf::RpcController* controller, + const ::OstProto::Void* request, + ::OstProto::PortIdList* response, + ::google::protobuf::Closure* done) +{ + qDebug("In %s", __PRETTY_FUNCTION__); + + for (int i = 0; i < portInfo.size(); i++) + { + ::OstProto::PortId *p; + + p = response->add_port_id(); + p->set_id(portInfo[i]->id()); + } + + done->Run(); +} + +void MyService::getPortConfig(::google::protobuf::RpcController* controller, + const ::OstProto::PortIdList* request, + ::OstProto::PortConfigList* response, + ::google::protobuf::Closure* done) +{ + qDebug("In %s", __PRETTY_FUNCTION__); + + for (int i = 0; i < request->port_id_size(); i++) + { + int id; + + id = request->port_id(i).id(); + if (id < portInfo.size()) + { + OstProto::Port *p; + + p = response->add_port(); + portInfo[id]->protoDataCopyInto(p); + } + } + + done->Run(); +} + +void MyService::getStreamIdList(::google::protobuf::RpcController* controller, + const ::OstProto::PortId* request, + ::OstProto::StreamIdList* response, + ::google::protobuf::Closure* done) +{ + int portId; + + qDebug("In %s", __PRETTY_FUNCTION__); + + portId = request->id(); + if ((portId < 0) || (portId >= portInfo.size())) + goto _invalid_port; + + response->mutable_port_id()->set_id(portId); + for (int i = 0; i < portInfo[portId]->streamCount(); i++) + { + OstProto::StreamId *s; + + s = response->add_stream_id(); + s->set_id(portInfo[portId]->stream(i)->id()); + } + done->Run(); + return; + +_invalid_port: + controller->SetFailed("Invalid Port Id"); + done->Run(); +} + +void MyService::getStreamConfig(::google::protobuf::RpcController* controller, + const ::OstProto::StreamIdList* request, + ::OstProto::StreamConfigList* response, + ::google::protobuf::Closure* done) +{ + int portId; + + qDebug("In %s", __PRETTY_FUNCTION__); + + portId = request->port_id().id(); + if ((portId < 0) || (portId >= portInfo.size())) + goto _invalid_port; + + response->mutable_port_id()->set_id(portId); + for (int i = 0; i < request->stream_id_size(); i++) + { + StreamBase *stream; + OstProto::Stream *s; + + stream = portInfo[portId]->stream(request->stream_id(i).id()); + if (!stream) + continue; //! \todo(LOW): Partial status of RPC + + s = response->add_stream(); + stream->protoDataCopyInto(*s); + } + done->Run(); + return; + +_invalid_port: + controller->SetFailed("invalid portid"); + done->Run(); +} + +void MyService::addStream(::google::protobuf::RpcController* controller, + const ::OstProto::StreamIdList* request, + ::OstProto::Ack* response, + ::google::protobuf::Closure* done) +{ + int portId; + + qDebug("In %s", __PRETTY_FUNCTION__); + + portId = request->port_id().id(); + if ((portId < 0) || (portId >= portInfo.size())) + goto _invalid_port; + + for (int i = 0; i < request->stream_id_size(); i++) + { + StreamBase *stream; + + // If stream with same id as in request exists already ==> error!! + stream = portInfo[portId]->stream(request->stream_id(i).id()); + if (stream) + continue; //! \todo (LOW): Partial status of RPC + + // Append a new "default" stream - actual contents of the new stream is + // expected in a subsequent "modifyStream" request - set the stream id + // now itself however!!! + stream = new StreamBase; + stream->setId(request->stream_id(i).id()); + portInfo[portId]->addStream(stream); + + } + + //! \todo (LOW): fill-in response "Ack"???? + + done->Run(); + return; + +_invalid_port: + controller->SetFailed("invalid portid"); + done->Run(); +} + +void MyService::deleteStream(::google::protobuf::RpcController* controller, + const ::OstProto::StreamIdList* request, + ::OstProto::Ack* response, + ::google::protobuf::Closure* done) +{ + int portId; + + qDebug("In %s", __PRETTY_FUNCTION__); + + portId = request->port_id().id(); + if ((portId < 0) || (portId >= portInfo.size())) + goto _invalid_port; + + for (int i = 0; i < request->stream_id_size(); i++) + portInfo[portId]->deleteStream(request->stream_id(i).id()); + + //! \todo (LOW): fill-in response "Ack"???? + + done->Run(); + return; + +_invalid_port: + controller->SetFailed("invalid portid"); + done->Run(); +} + +void MyService::modifyStream(::google::protobuf::RpcController* controller, + const ::OstProto::StreamConfigList* request, + ::OstProto::Ack* response, + ::google::protobuf::Closure* done) +{ + int portId; + + qDebug("In %s", __PRETTY_FUNCTION__); + + portId = request->port_id().id(); + if ((portId < 0) || (portId >= portInfo.size())) + goto _invalid_port; + + for (int i = 0; i < request->stream_size(); i++) + { + StreamBase *stream; + + stream = portInfo[portId]->stream(request->stream(i).stream_id().id()); + if (stream) + { + stream->protoDataCopyFrom(request->stream(i)); + portInfo[portId]->setDirty(); + } + } + + //! \todo(LOW): fill-in response "Ack"???? + + done->Run(); + return; + +_invalid_port: + controller->SetFailed("invalid portid"); + done->Run(); +} + +void MyService::startTx(::google::protobuf::RpcController* controller, + const ::OstProto::PortIdList* request, + ::OstProto::Ack* response, + ::google::protobuf::Closure* done) +{ + qDebug("In %s", __PRETTY_FUNCTION__); + + for (int i = 0; i < request->port_id_size(); i++) + { + int portId; + + portId = request->port_id(i).id(); + if ((portId < 0) || (portId >= portInfo.size())) + continue; //! \todo (LOW): partial RPC? + + portInfo[portId]->startTransmit(); + } + + //! \todo (LOW): fill-in response "Ack"???? + + done->Run(); +} + +void MyService::stopTx(::google::protobuf::RpcController* controller, + const ::OstProto::PortIdList* request, + ::OstProto::Ack* response, + ::google::protobuf::Closure* done) +{ + qDebug("In %s", __PRETTY_FUNCTION__); + + for (int i = 0; i < request->port_id_size(); i++) + { + int portId; + + portId = request->port_id(i).id(); + if ((portId < 0) || (portId >= portInfo.size())) + continue; //! \todo (LOW): partial RPC? + + portInfo[portId]->stopTransmit(); + } + + //! \todo (LOW): fill-in response "Ack"???? + + done->Run(); +} + +void MyService::startCapture(::google::protobuf::RpcController* controller, + const ::OstProto::PortIdList* request, + ::OstProto::Ack* response, + ::google::protobuf::Closure* done) +{ + qDebug("In %s", __PRETTY_FUNCTION__); + + for (int i = 0; i < request->port_id_size(); i++) + { + int portId; + + portId = request->port_id(i).id(); + if ((portId < 0) || (portId >= portInfo.size())) + continue; //! \todo (LOW): partial RPC? + + portInfo[portId]->startCapture(); + } + + //! \todo (LOW): fill-in response "Ack"???? + + done->Run(); +} + +void MyService::stopCapture(::google::protobuf::RpcController* controller, + const ::OstProto::PortIdList* request, + ::OstProto::Ack* response, + ::google::protobuf::Closure* done) +{ + qDebug("In %s", __PRETTY_FUNCTION__); + for (int i=0; i < request->port_id_size(); i++) + { + int portId; + + portId = request->port_id(i).id(); + if ((portId < 0) || (portId >= portInfo.size())) + continue; //! \todo (LOW): partial RPC? + + portInfo[portId]->stopCapture(); + } + + //! \todo (LOW): fill-in response "Ack"???? + + done->Run(); +} + +void MyService::getCaptureBuffer(::google::protobuf::RpcController* controller, + const ::OstProto::PortId* request, + ::OstProto::CaptureBuffer* response, + ::google::protobuf::Closure* done) +{ + int portId; + + qDebug("In %s", __PRETTY_FUNCTION__); + + portId = request->id(); + if ((portId < 0) || (portId >= portInfo.size())) + goto _invalid_port; + + portInfo[portId]->stopCapture(); + static_cast(controller)->setBinaryBlob( + portInfo[portId]->captureData()); + + done->Run(); + return; + +_invalid_port: + controller->SetFailed("invalid portid"); + done->Run(); +} + +void MyService::getStats(::google::protobuf::RpcController* controller, + const ::OstProto::PortIdList* request, + ::OstProto::PortStatsList* response, + ::google::protobuf::Closure* done) +{ + //qDebug("In %s", __PRETTY_FUNCTION__); + + for (int i = 0; i < request->port_id_size(); i++) + { + int portId; + AbstractPort::PortStats stats; + OstProto::PortStats *s; + OstProto::PortState *st; + + portId = request->port_id(i).id(); + if ((portId < 0) || (portId >= portInfo.size())) + continue; //! \todo(LOW): partial rpc? + + s = response->add_port_stats(); + s->mutable_port_id()->set_id(request->port_id(i).id()); + + st = s->mutable_state(); + st->set_link_state(portInfo[portId]->linkState()); + st->set_is_transmit_on(portInfo[portId]->isTransmitOn()); + st->set_is_capture_on(portInfo[portId]->isCaptureOn()); + + portInfo[portId]->stats(&stats); + +#if 0 + if (portId == 2) + qDebug(">%llu", stats.rxPkts); +#endif + + s->set_rx_pkts(stats.rxPkts); + s->set_rx_bytes(stats.rxBytes); + s->set_rx_pps(stats.rxPps); + s->set_rx_bps(stats.rxBps); + + s->set_tx_pkts(stats.txPkts); + s->set_tx_bytes(stats.txBytes); + s->set_tx_pps(stats.txPps); + s->set_tx_bps(stats.txBps); + } + + done->Run(); +} + +void MyService::clearStats(::google::protobuf::RpcController* controller, + const ::OstProto::PortIdList* request, + ::OstProto::Ack* response, + ::google::protobuf::Closure* done) +{ + qDebug("In %s", __PRETTY_FUNCTION__); + + for (int i = 0; i < request->port_id_size(); i++) + { + int portId; + + portId = request->port_id(i).id(); + if ((portId < 0) || (portId >= portInfo.size())) + continue; //! \todo (LOW): partial RPC? + + portInfo[portId]->resetStats(); + } + + //! \todo (LOW): fill-in response "Ack"???? + + done->Run(); +}