Initial Import

This commit is contained in:
Srivats P. 2008-05-03 14:37:10 +00:00
commit 7e8d8308e3
72 changed files with 8683 additions and 0 deletions

88
client/about.ui Normal file
View File

@ -0,0 +1,88 @@
<ui version="4.0" >
<class>Dialog</class>
<widget class="QDialog" name="Dialog" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle" >
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" >
<item>
<widget class="QFrame" name="frame" >
<property name="frameShape" >
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow" >
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" >
<item>
<widget class="QLabel" name="label" >
<property name="text" >
<string>&lt;html>&lt;head>&lt;meta name="qrichtext" content="1" />&lt;style type="text/css">
p, li { white-space: pre-wrap; }
&lt;/style>&lt;/head>&lt;body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
&lt;p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">&lt;span style=" font-size:29pt; font-weight:600;">Ostinato&lt;/span>&lt;/p>&lt;/body>&lt;/html></string>
</property>
<property name="alignment" >
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons" >
<set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel" >
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel" >
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel" >
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel" >
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

69
client/hexlineedit.cpp Normal file
View File

@ -0,0 +1,69 @@
#include "hexlineedit.h"
#include "qdebug.h"
QString & uintToHexStr(quint32 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
bool isOk;
ulong num;
QString str;
qDebug("before = %s\n", text().toAscii().data());
num = text().remove(QChar(' ')).toULong(&isOk, 16);
setText(uintToHexStr(num, str, 4));
qDebug("after = %s\n", text().toAscii().data());
qDebug("after2 = %s\n", str.toAscii().data());
#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

24
client/hexlineedit.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef _HEXLINEEDIT
#define _HEXLINEEDIT
#include <QLineEdit>
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

Binary file not shown.

After

Width:  |  Height:  |  Size: 454 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 283 B

BIN
client/icons/bullet_red.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 592 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 B

BIN
client/icons/gaps.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
client/icons/magnifier.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 615 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 781 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 748 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 775 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 796 B

BIN
client/icons/sound_mute.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 474 B

BIN
client/icons/sound_none.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 417 B

BIN
client/icons/stream_add.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 814 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 847 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 865 B

11
client/main.cpp Normal file
View File

@ -0,0 +1,11 @@
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
MainWindow mainWin;
mainWin.show();
return app.exec();
}

30
client/mainwindow.cpp Normal file
View File

@ -0,0 +1,30 @@
#include <QtGui>
#include "mainwindow.h"
#include "portswindow.h"
#include "portstatswindow.h"
#include "portgrouplist.h"
PortGroupList *pgl;
MainWindow::MainWindow(QWidget *parent)
: QMainWindow (parent)
{
pgl = new PortGroupList;
PortsWindow *portsWindow = new PortsWindow(pgl, this);
PortStatsWindow *statsWindow = new PortStatsWindow(pgl, this);
QDockWidget *dock = new QDockWidget(tr("Ports"), this);
QDockWidget *dock2 = new QDockWidget(tr("Stats"), this);
setupUi(this);
dock->setWidget(portsWindow);
addDockWidget(Qt::TopDockWidgetArea, dock);
dock2->setWidget(statsWindow);
addDockWidget(Qt::BottomDockWidgetArea, dock2);
}
void MainWindow::on_actionPreferences_triggered()
{
}

18
client/mainwindow.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef _MAIN_WINDOW_H
#define _MAIN_WINDOW_H
#include <QMainWindow>
#include "ui_mainwindow.h"
class MainWindow : public QMainWindow, private Ui::MainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
public slots:
void on_actionPreferences_triggered();
};
#endif

159
client/mainwindow.ui Normal file
View File

@ -0,0 +1,159 @@
<ui version="4.0" >
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle" >
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget" />
<widget class="QMenuBar" name="menubar" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="menuFile" >
<property name="title" >
<string>File</string>
</property>
<addaction name="actionE_xit" />
</widget>
<widget class="QMenu" name="menuView" >
<property name="title" >
<string>View</string>
</property>
<addaction name="actionPreferences" />
</widget>
<widget class="QMenu" name="menuWindow" >
<property name="title" >
<string>Window</string>
</property>
<addaction name="actionMinimize" />
<addaction name="actionMaximize_Restore" />
<addaction name="actionMinimize_All" />
<addaction name="actionMaximize_Restoe_All" />
<addaction name="actionArrange_All_Cascade" />
<addaction name="actionArrange_All_Tile" />
<addaction name="actionDock" />
</widget>
<widget class="QMenu" name="menuHelp" >
<property name="title" >
<string>Help</string>
</property>
<addaction name="actionAbout" />
</widget>
<addaction name="menuFile" />
<addaction name="menuView" />
<addaction name="menuWindow" />
<addaction name="menuHelp" />
</widget>
<widget class="QStatusBar" name="statusbar" />
<action name="actionOpen_Config" >
<property name="text" >
<string>Open Config</string>
</property>
</action>
<action name="actionSave_Config" >
<property name="text" >
<string>Save Config</string>
</property>
</action>
<action name="actionSave_Config_As" >
<property name="text" >
<string>Save Config As ...</string>
</property>
</action>
<action name="actionOpen_Capture" >
<property name="text" >
<string>Open Capture</string>
</property>
</action>
<action name="actionSave_Capture" >
<property name="text" >
<string>Save Capture</string>
</property>
</action>
<action name="actionSave_Capture_As" >
<property name="text" >
<string>Save Capture As ...</string>
</property>
</action>
<action name="actionE_xit" >
<property name="text" >
<string>E&amp;xit</string>
</property>
</action>
<action name="actionCopy_Port_Config" >
<property name="text" >
<string>Copy Port Config</string>
</property>
</action>
<action name="actionPaste_Port_Config" >
<property name="text" >
<string>Paste Port Config</string>
</property>
</action>
<action name="actionPreferences" >
<property name="text" >
<string>Preferences</string>
</property>
</action>
<action name="actionMinimize" >
<property name="text" >
<string>Minimize</string>
</property>
</action>
<action name="actionMaximize_Restore" >
<property name="text" >
<string>Maximize/Restore</string>
</property>
</action>
<action name="actionMinimize_All" >
<property name="text" >
<string>Minimize All</string>
</property>
</action>
<action name="actionMaximize_Restoe_All" >
<property name="text" >
<string>Maximize/Restoe All</string>
</property>
</action>
<action name="actionArrange_All_Cascade" >
<property name="text" >
<string>Arrange All - Cascade</string>
</property>
</action>
<action name="actionArrange_All_Tile" >
<property name="text" >
<string>Arrange All - Tile</string>
</property>
</action>
<action name="actionDock" >
<property name="text" >
<string>Dock</string>
</property>
</action>
<action name="actionHelp" >
<property name="text" >
<string>Help</string>
</property>
</action>
<action name="actionAbout" >
<property name="text" >
<string>About</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>

542
client/modeltest.cpp Normal file
View File

@ -0,0 +1,542 @@
/****************************************************************************
**
** Copyright (C) 2007 Trolltech ASA. All rights reserved.
**
** This file is part of the Qt Concurrent project on Trolltech Labs.
**
** This file may be used under the terms of the GNU General Public
** License version 2.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
** http://www.trolltech.com/products/qt/opensource.html
**
** If you are unsure which license is appropriate for your use, please
** review the following information:
** http://www.trolltech.com/products/qt/licensing.html or contact the
** sales department at sales@trolltech.com.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/
#include <QtGui/QtGui>
#include "modeltest.h"
Q_DECLARE_METATYPE(QModelIndex)
/*!
Connect to all of the models signals. Whenever anything happens recheck everything.
*/
ModelTest::ModelTest(QAbstractItemModel *_model, QObject *parent) : QObject(parent), model(_model), fetchingMore(false)
{
Q_ASSERT(model);
connect(model, SIGNAL(columnsAboutToBeInserted(const QModelIndex &, int, int)),
this, SLOT(runAllTests()));
connect(model, SIGNAL(columnsAboutToBeRemoved(const QModelIndex &, int, int)),
this, SLOT(runAllTests()));
connect(model, SIGNAL(columnsInserted(const QModelIndex &, int, int)),
this, SLOT(runAllTests()));
connect(model, SIGNAL(columnsRemoved(const QModelIndex &, int, int)),
this, SLOT(runAllTests()));
connect(model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
this, SLOT(runAllTests()));
connect(model, SIGNAL(headerDataChanged(Qt::Orientation, int, int)),
this, SLOT(runAllTests()));
connect(model, SIGNAL(layoutAboutToBeChanged ()), this, SLOT(runAllTests()));
connect(model, SIGNAL(layoutChanged ()), this, SLOT(runAllTests()));
connect(model, SIGNAL(modelReset ()), this, SLOT(runAllTests()));
connect(model, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)),
this, SLOT(runAllTests()));
connect(model, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)),
this, SLOT(runAllTests()));
connect(model, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
this, SLOT(runAllTests()));
connect(model, SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
this, SLOT(runAllTests()));
// Special checks for inserting/removing
connect(model, SIGNAL(layoutAboutToBeChanged()),
this, SLOT(layoutAboutToBeChanged()));
connect(model, SIGNAL(layoutChanged()),
this, SLOT(layoutChanged()));
connect(model, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)),
this, SLOT(rowsAboutToBeInserted(const QModelIndex &, int, int)));
connect(model, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)),
this, SLOT(rowsAboutToBeRemoved(const QModelIndex &, int, int)));
connect(model, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
this, SLOT(rowsInserted(const QModelIndex &, int, int)));
connect(model, SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
this, SLOT(rowsRemoved(const QModelIndex &, int, int)));
runAllTests();
}
void ModelTest::runAllTests()
{
if (fetchingMore)
return;
nonDestructiveBasicTest();
rowCount();
columnCount();
hasIndex();
index();
parent();
data();
}
/*!
nonDestructiveBasicTest tries to call a number of the basic functions (not all)
to make sure the model doesn't outright segfault, testing the functions that makes sense.
*/
void ModelTest::nonDestructiveBasicTest()
{
Q_ASSERT(model->buddy(QModelIndex()) == QModelIndex());
model->canFetchMore(QModelIndex());
Q_ASSERT(model->columnCount(QModelIndex()) >= 0);
Q_ASSERT(model->data(QModelIndex()) == QVariant());
fetchingMore = true;
model->fetchMore(QModelIndex());
fetchingMore = false;
Qt::ItemFlags flags = model->flags(QModelIndex());
Q_ASSERT(flags == Qt::ItemIsDropEnabled || flags == 0);
model->hasChildren(QModelIndex());
model->hasIndex(0, 0);
model->headerData(0, Qt::Horizontal);
model->index(0, 0);
Q_ASSERT(model->index(-1, -1) == QModelIndex());
model->itemData(QModelIndex());
QVariant cache;
model->match(QModelIndex(), -1, cache);
model->mimeTypes();
Q_ASSERT(model->parent(QModelIndex()) == QModelIndex());
Q_ASSERT(model->rowCount() >= 0);
QVariant variant;
model->setData(QModelIndex(), variant, -1);
model->setHeaderData(-1, Qt::Horizontal, QVariant());
model->setHeaderData(0, Qt::Horizontal, QVariant());
model->setHeaderData(999999, Qt::Horizontal, QVariant());
QMap<int, QVariant> roles;
model->sibling(0, 0, QModelIndex());
model->span(QModelIndex());
model->supportedDropActions();
}
/*!
Tests model's implementation of QAbstractItemModel::rowCount() and hasChildren()
Models that are dynamically populated are not as fully tested here.
*/
void ModelTest::rowCount()
{
// check top row
QModelIndex topIndex = model->index(0, 0, QModelIndex());
int rows = model->rowCount(topIndex);
Q_ASSERT(rows >= 0);
if (rows > 0)
Q_ASSERT(model->hasChildren(topIndex) == true);
QModelIndex secondLevelIndex = model->index(0, 0, topIndex);
if (secondLevelIndex.isValid()) { // not the top level
// check a row count where parent is valid
rows = model->rowCount(secondLevelIndex);
Q_ASSERT(rows >= 0);
if (rows > 0)
Q_ASSERT(model->hasChildren(secondLevelIndex) == true);
}
// The models rowCount() is tested more extensively in checkChildren(),
// but this catches the big mistakes
}
/*!
Tests model's implementation of QAbstractItemModel::columnCount() and hasChildren()
*/
void ModelTest::columnCount()
{
// check top row
QModelIndex topIndex = model->index(0, 0, QModelIndex());
Q_ASSERT(model->columnCount(topIndex) >= 0);
// check a column count where parent is valid
QModelIndex childIndex = model->index(0, 0, topIndex);
if (childIndex.isValid())
Q_ASSERT(model->columnCount(childIndex) >= 0);
// columnCount() is tested more extensively in checkChildren(),
// but this catches the big mistakes
}
/*!
Tests model's implementation of QAbstractItemModel::hasIndex()
*/
void ModelTest::hasIndex()
{
// Make sure that invalid values returns an invalid index
Q_ASSERT(model->hasIndex(-2, -2) == false);
Q_ASSERT(model->hasIndex(-2, 0) == false);
Q_ASSERT(model->hasIndex(0, -2) == false);
int rows = model->rowCount();
int columns = model->columnCount();
// check out of bounds
Q_ASSERT(model->hasIndex(rows, columns) == false);
Q_ASSERT(model->hasIndex(rows + 1, columns + 1) == false);
if (rows > 0)
Q_ASSERT(model->hasIndex(0, 0) == true);
// hasIndex() is tested more extensively in checkChildren(),
// but this catches the big mistakes
}
/*!
Tests model's implementation of QAbstractItemModel::index()
*/
void ModelTest::index()
{
// Make sure that invalid values returns an invalid index
Q_ASSERT(model->index(-2, -2) == QModelIndex());
Q_ASSERT(model->index(-2, 0) == QModelIndex());
Q_ASSERT(model->index(0, -2) == QModelIndex());
int rows = model->rowCount();
int columns = model->columnCount();
if (rows == 0)
return;
// Catch off by one errors
Q_ASSERT(model->index(rows, columns) == QModelIndex());
Q_ASSERT(model->index(0, 0).isValid() == true);
// Make sure that the same index is *always* returned
QModelIndex a = model->index(0, 0);
QModelIndex b = model->index(0, 0);
Q_ASSERT(a == b);
// index() is tested more extensively in checkChildren(),
// but this catches the big mistakes
}
/*!
Tests model's implementation of QAbstractItemModel::parent()
*/
void ModelTest::parent()
{
// Make sure the model wont crash and will return an invalid QModelIndex
// when asked for the parent of an invalid index.
Q_ASSERT(model->parent(QModelIndex()) == QModelIndex());
if (model->rowCount() == 0)
return;
// Column 0 | Column 1 |
// QModelIndex() | |
// \- topIndex | topIndex1 |
// \- childIndex | childIndex1 |
// Common error test #1, make sure that a top level index has a parent
// that is a invalid QModelIndex.
QModelIndex topIndex = model->index(0, 0, QModelIndex());
Q_ASSERT(model->parent(topIndex) == QModelIndex());
// Common error test #2, make sure that a second level index has a parent
// that is the first level index.
if (model->rowCount(topIndex) > 0) {
QModelIndex childIndex = model->index(0, 0, topIndex);
qDebug("topIndex RCI %x %x %llx", topIndex.row(), topIndex.column(), topIndex.internalId());
qDebug("topIndex I %llx", topIndex.internalId());
qDebug("childIndex RCI %x %x %llx", childIndex.row(), childIndex.column(), childIndex.internalId());
Q_ASSERT(model->parent(childIndex) == topIndex);
}
// Common error test #3, the second column should NOT have the same children
// as the first column in a row.
// Usually the second column shouldn't have children.
QModelIndex topIndex1 = model->index(0, 1, QModelIndex());
if (model->rowCount(topIndex1) > 0) {
QModelIndex childIndex = model->index(0, 0, topIndex);
QModelIndex childIndex1 = model->index(0, 0, topIndex1);
Q_ASSERT(childIndex != childIndex1);
}
// Full test, walk n levels deep through the model making sure that all
// parent's children correctly specify their parent.
checkChildren(QModelIndex());
}
/*!
Called from the parent() test.
A model that returns an index of parent X should also return X when asking
for the parent of the index.
This recursive function does pretty extensive testing on the whole model in an
effort to catch edge cases.
This function assumes that rowCount(), columnCount() and index() already work.
If they have a bug it will point it out, but the above tests should have already
found the basic bugs because it is easier to figure out the problem in
those tests then this one.
*/
void ModelTest::checkChildren(const QModelIndex &parent, int currentDepth)
{
// First just try walking back up the tree.
QModelIndex p = parent;
while (p.isValid())
p = p.parent();
// For models that are dynamically populated
if (model->canFetchMore(parent)) {
fetchingMore = true;
model->fetchMore(parent);
fetchingMore = false;
}
int rows = model->rowCount(parent);
int columns = model->columnCount(parent);
if (rows > 0)
Q_ASSERT(model->hasChildren(parent));
// Some further testing against rows(), columns(), and hasChildren()
Q_ASSERT(rows >= 0);
Q_ASSERT(columns >= 0);
if (rows > 0)
Q_ASSERT(model->hasChildren(parent) == true);
//qDebug() << "parent:" << model->data(parent).toString() << "rows:" << rows
// << "columns:" << columns << "parent column:" << parent.column();
Q_ASSERT(model->hasIndex(rows + 1, 0, parent) == false);
for (int r = 0; r < rows; ++r) {
if (model->canFetchMore(parent)) {
fetchingMore = true;
model->fetchMore(parent);
fetchingMore = false;
}
Q_ASSERT(model->hasIndex(r, columns + 1, parent) == false);
for (int c = 0; c < columns; ++c) {
Q_ASSERT(model->hasIndex(r, c, parent) == true);
QModelIndex index = model->index(r, c, parent);
// rowCount() and columnCount() said that it existed...
Q_ASSERT(index.isValid() == true);
// index() should always return the same index when called twice in a row
QModelIndex modifiedIndex = model->index(r, c, parent);
Q_ASSERT(index == modifiedIndex);
// Make sure we get the same index if we request it twice in a row
QModelIndex a = model->index(r, c, parent);
QModelIndex b = model->index(r, c, parent);
Q_ASSERT(a == b);
// Some basic checking on the index that is returned
Q_ASSERT(index.model() == model);
Q_ASSERT(index.row() == r);
Q_ASSERT(index.column() == c);
// While you can technically return a QVariant usually this is a sign
// of an bug in data() Disable if this really is ok in your model.
//Q_ASSERT(model->data(index, Qt::DisplayRole).isValid() == true);
// If the next test fails here is some somewhat useful debug you play with.
/*
if (model->parent(index) != parent) {
qDebug() << r << c << currentDepth << model->data(index).toString()
<< model->data(parent).toString();
qDebug() << index << parent << model->parent(index);
// And a view that you can even use to show the model.
//QTreeView view;
//view.setModel(model);
//view.show();
}*/
// Check that we can get back our real parent.
QModelIndex p = model->parent(index);
//qDebug() << "child:" << index;
//qDebug() << p;
//qDebug() << parent;
Q_ASSERT(model->parent(index) == parent);
// recursively go down the children
if (model->hasChildren(index) && currentDepth < 10 ) {
//qDebug() << r << c << "has children" << model->rowCount(index);
checkChildren(index, ++currentDepth);
}/* else { if (currentDepth >= 10) qDebug() << "checked 10 deep"; };*/
// make sure that after testing the children that the index doesn't change.
QModelIndex newerIndex = model->index(r, c, parent);
Q_ASSERT(index == newerIndex);
}
}
}
/*!
Tests model's implementation of QAbstractItemModel::data()
*/
void ModelTest::data()
{
// Invalid index should return an invalid qvariant
Q_ASSERT(!model->data(QModelIndex()).isValid());
if (model->rowCount() == 0)
return;
// A valid index should have a valid QVariant data
Q_ASSERT(model->index(0, 0).isValid());
// shouldn't be able to set data on an invalid index
Q_ASSERT(model->setData(QModelIndex(), QLatin1String("foo"), Qt::DisplayRole) == false);
// General Purpose roles that should return a QString
QVariant variant = model->data(model->index(0, 0), Qt::ToolTipRole);
if (variant.isValid()) {
Q_ASSERT(qVariantCanConvert<QString>(variant));
}
variant = model->data(model->index(0, 0), Qt::StatusTipRole);
if (variant.isValid()) {
Q_ASSERT(qVariantCanConvert<QString>(variant));
}
variant = model->data(model->index(0, 0), Qt::WhatsThisRole);
if (variant.isValid()) {
Q_ASSERT(qVariantCanConvert<QString>(variant));
}
// General Purpose roles that should return a QSize
variant = model->data(model->index(0, 0), Qt::SizeHintRole);
if (variant.isValid()) {
Q_ASSERT(qVariantCanConvert<QSize>(variant));
}
// General Purpose roles that should return a QFont
QVariant fontVariant = model->data(model->index(0, 0), Qt::FontRole);
if (fontVariant.isValid()) {
Q_ASSERT(qVariantCanConvert<QFont>(fontVariant));
}
// Check that the alignment is one we know about
QVariant textAlignmentVariant = model->data(model->index(0, 0), Qt::TextAlignmentRole);
if (textAlignmentVariant.isValid()) {
int alignment = textAlignmentVariant.toInt();
Q_ASSERT(alignment == Qt::AlignLeft ||
alignment == Qt::AlignRight ||
alignment == Qt::AlignHCenter ||
alignment == Qt::AlignJustify ||
alignment == Qt::AlignTop ||
alignment == Qt::AlignBottom ||
alignment == Qt::AlignVCenter ||
alignment == Qt::AlignCenter ||
alignment == Qt::AlignAbsolute ||
alignment == Qt::AlignLeading ||
alignment == Qt::AlignTrailing);
}
// General Purpose roles that should return a QColor
QVariant colorVariant = model->data(model->index(0, 0), Qt::BackgroundColorRole);
if (colorVariant.isValid()) {
Q_ASSERT(qVariantCanConvert<QColor>(colorVariant));
}
colorVariant = model->data(model->index(0, 0), Qt::TextColorRole);
if (colorVariant.isValid()) {
Q_ASSERT(qVariantCanConvert<QColor>(colorVariant));
}
// Check that the "check state" is one we know about.
QVariant checkStateVariant = model->data(model->index(0, 0), Qt::CheckStateRole);
if (checkStateVariant.isValid()) {
int state = checkStateVariant.toInt();
Q_ASSERT(state == Qt::Unchecked ||
state == Qt::PartiallyChecked ||
state == Qt::Checked);
}
}
/*!
Store what is about to be inserted to make sure it actually happens
\sa rowsInserted()
*/
void ModelTest::rowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
{
Q_UNUSED(end);
Changing c;
c.parent = parent;
c.oldSize = model->rowCount(parent);
c.last = model->data(model->index(start - 1, 0, parent));
c.next = model->data(model->index(start, 0, parent));
insert.push(c);
}
/*!
Confirm that what was said was going to happen actually did
\sa rowsAboutToBeInserted()
*/
void ModelTest::rowsInserted(const QModelIndex & parent, int start, int end)
{
Changing c = insert.pop();
Q_ASSERT(c.parent == parent);
Q_ASSERT(c.oldSize + (end - start + 1) == model->rowCount(parent));
Q_ASSERT(c.last == model->data(model->index(start - 1, 0, c.parent)));
/*
if (c.next != model->data(model->index(end + 1, 0, c.parent))) {
qDebug() << start << end;
for (int i=0; i < model->rowCount(); ++i)
qDebug() << model->index(i, 0).data().toString();
qDebug() << c.next << model->data(model->index(end + 1, 0, c.parent));
}
*/
Q_ASSERT(c.next == model->data(model->index(end + 1, 0, c.parent)));
}
void ModelTest::layoutAboutToBeChanged()
{
for (int i = 0; i < qBound(0, model->rowCount(), 100); ++i)
changing.append(QPersistentModelIndex(model->index(i, 0)));
}
void ModelTest::layoutChanged()
{
for (int i = 0; i < changing.count(); ++i) {
QPersistentModelIndex p = changing[i];
Q_ASSERT(p == model->index(p.row(), p.column(), p.parent()));
}
changing.clear();
}
/*!
Store what is about to be inserted to make sure it actually happens
\sa rowsRemoved()
*/
void ModelTest::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
{
Changing c;
c.parent = parent;
c.oldSize = model->rowCount(parent);
c.last = model->data(model->index(start - 1, 0, parent));
c.next = model->data(model->index(end + 1, 0, parent));
remove.push(c);
}
/*!
Confirm that what was said was going to happen actually did
\sa rowsAboutToBeRemoved()
*/
void ModelTest::rowsRemoved(const QModelIndex & parent, int start, int end)
{
Changing c = remove.pop();
Q_ASSERT(c.parent == parent);
Q_ASSERT(c.oldSize - (end - start + 1) == model->rowCount(parent));
Q_ASSERT(c.last == model->data(model->index(start - 1, 0, c.parent)));
Q_ASSERT(c.next == model->data(model->index(start, 0, c.parent)));
}

76
client/modeltest.h Normal file
View File

@ -0,0 +1,76 @@
/****************************************************************************
**
** Copyright (C) 2007 Trolltech ASA. All rights reserved.
**
** This file is part of the Qt Concurrent project on Trolltech Labs.
**
** This file may be used under the terms of the GNU General Public
** License version 2.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
** http://www.trolltech.com/products/qt/opensource.html
**
** If you are unsure which license is appropriate for your use, please
** review the following information:
** http://www.trolltech.com/products/qt/licensing.html or contact the
** sales department at sales@trolltech.com.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/
#ifndef MODELTEST_H
#define MODELTEST_H
#include <QtCore/QObject>
#include <QtCore/QAbstractItemModel>
#include <QtCore/QStack>
class ModelTest : public QObject
{
Q_OBJECT
public:
ModelTest(QAbstractItemModel *model, QObject *parent = 0);
private Q_SLOTS:
void nonDestructiveBasicTest();
void rowCount();
void columnCount();
void hasIndex();
void index();
void parent();
void data();
protected Q_SLOTS:
void runAllTests();
void layoutAboutToBeChanged();
void layoutChanged();
void rowsAboutToBeInserted(const QModelIndex &parent, int start, int end);
void rowsInserted(const QModelIndex & parent, int start, int end);
void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
void rowsRemoved(const QModelIndex & parent, int start, int end);
private:
void checkChildren(const QModelIndex &parent, int currentDepth = 0);
QAbstractItemModel *model;
struct Changing
{
QModelIndex parent;
int oldSize;
QVariant last;
QVariant next;
};
QStack<Changing> insert;
QStack<Changing> remove;
bool fetchingMore;
QList<QPersistentModelIndex> changing;
};
#endif

4
client/modeltest.pri Normal file
View File

@ -0,0 +1,4 @@
INCLUDEPATH += $$PWD
DEPENDPATH += $$PWD
SOURCES += $$PWD/modeltest.cpp
HEADERS += $$PWD/modeltest.h

24
client/mythread.cpp Normal file
View File

@ -0,0 +1,24 @@
#include "mythread.h"
void MyThread::run()
{
int i, j;
for (i=0; i<NumPorts; i++)
for (j=0; j<NumStats; j++)
stats[i][j] = 0;
qDebug("after stats init\n");
while (1)
{
for (i=0; i<NumPorts; i++)
{
emit portStatsUpdate(i, (void*) &stats[i]);
for (j=0; j<NumStats; j++)
stats[i][j]+= qrand() & 0xF;
}
sleep(qrand() & 0x3);
}
}

23
client/mythread.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef _MY_THREAD_H
#define _MY_THREAD_H
#include <QThread>
#define NumPorts 2
#define NumStats 8
class MyThread : public QThread
{
Q_OBJECT
public:
void run();
signals:
void portStatsUpdate(int port, void *stats);
private:
int stats[2][8];
};
#endif

42
client/ostinato.pro Normal file
View File

@ -0,0 +1,42 @@
TEMPLATE = app
CONFIG += qt debug
QT += network
RESOURCES += ostinato.qrc
HEADERS += \
hexlineedit.h \
mainwindow.h \
mythread.h \
port.h \
portgroup.h \
portgrouplist.h \
portmodel.h \
portstatsmodel.h \
portstatswindow.h \
portswindow.h \
streamconfigdialog.h \
streammodel.h
FORMS += \
mainwindow.ui \
portstatswindow.ui \
portswindow.ui \
streamconfigdialog.ui
SOURCES += \
stream.cpp \
hexlineedit.cpp \
main.cpp \
mainwindow.cpp \
mythread.cpp \
port.cpp \
portgroup.cpp \
portgrouplist.cpp \
portmodel.cpp \
portstatsmodel.cpp \
portstatswindow.cpp \
portswindow.cpp \
streamconfigdialog.cpp \
streammodel.cpp
# TODO(LOW): Test only
include(modeltest.pri)

21
client/ostinato.qrc Normal file
View File

@ -0,0 +1,21 @@
<RCC>
<qresource prefix="/" >
<file>icons/bullet_error.png</file>
<file>icons/bullet_green.png</file>
<file>icons/bullet_orange.png</file>
<file>icons/bullet_red.png</file>
<file>icons/bullet_yellow.png</file>
<file>icons/control_play.png</file>
<file>icons/control_stop.png</file>
<file>icons/magnifier.png</file>
<file>icons/portgroup_add.png</file>
<file>icons/portgroup_connect.png</file>
<file>icons/portgroup_delete.png</file>
<file>icons/portgroup_disconnect.png</file>
<file>icons/sound_mute.png</file>
<file>icons/sound_none.png</file>
<file>icons/stream_add.png</file>
<file>icons/stream_delete.png</file>
<file>icons/stream_edit.png</file>
</qresource>
</RCC>

24
client/port.cpp Normal file
View File

@ -0,0 +1,24 @@
#include "port.h"
Port::Port(quint32 id, quint32 portGroupId)
{
mPortId = id;
mPortGroupId = portGroupId;
mAdminStatus = AdminDisable;
mOperStatus = OperDown;
mControlMode = ControlShared;
// FIXME(HI): TEST only
for(int i = 0; i < 10; i++)
mPortStats[i] = mPortGroupId*10000+mPortId*100+i;
}
void Port::insertDummyStreams()
{
mStreams.append(*(new Stream));
mStreams[0].setName(QString("%1:%2:0").arg(portGroupId()).arg(id()));
mStreams.append(*(new Stream));
mStreams[1].setName(QString("%1:%2:1").arg(portGroupId()).arg(id()));
}

55
client/port.h Normal file
View File

@ -0,0 +1,55 @@
#ifndef _PORT_H
#define _PORT_H
#include <Qt>
#include <QString>
#include <QList>
#include "stream.h"
class Port {
friend class StreamModel;
friend class PortStatsModel;
public:
enum AdminStatus { AdminDisable, AdminEnable };
enum OperStatus { OperDown, OperUp };
enum ControlMode { ControlShared, ControlExclusive };
private:
quint32 mPortId;
quint32 mPortGroupId;
QList<Stream> mStreams;
QString mName;
QString mDescription;
QString mUserAlias; // user defined
AdminStatus mAdminStatus;
OperStatus mOperStatus;
ControlMode mControlMode;
quint32 mPortStats[10]; // FIXME(HI):Hardcoding
public:
// FIXME(HIGH): default args is a hack for QList operations on Port
Port(quint32 id = 0xFFFFFFFF, quint32 pgId = 0xFFFFFFFF);
quint32 id() const { return mPortId; }
quint32 portGroupId() const { return mPortGroupId; }
const QString& name() const { return mName; }
const QString& description() const { return mDescription; }
const QString& userAlias() const { return mUserAlias; }
void setName(QString &name) { mName = name; }
void setName(const char* name) { mName = QString(name); }
void setDescription(QString &description) { mDescription = description; }
void setDescription(const char *description)
{ mDescription = QString(description); }
//void setAdminEnable(AdminStatus status) { mAdminStatus = status; }
void setAlias(QString &alias) { mUserAlias = alias; }
//void setExclusive(bool flag);
// FIXME(HIGH): Only for testing
void insertDummyStreams();
};
#endif

169
client/portgroup.cpp Normal file
View File

@ -0,0 +1,169 @@
#include "portgroup.h"
#include "../common/protocol.h"
quint32 PortGroup::mPortGroupAllocId = 0;
PortGroup::PortGroup(QHostAddress ip, quint16 port)
{
// Allocate an id for self
mPortGroupId = PortGroup::mPortGroupAllocId++;
// Init attributes for which we values were passed to us
mServerAddress = ip;
mServerPort = port;
// Init remaining attributes with defaults
mpSocket = new QTcpSocket(this);
// TODO: consider using QT's signal-slot autoconnect
connect(mpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(on_mpSocket_stateChanged()));
connect(mpSocket, SIGNAL(connected()), this, SLOT(when_connected()));
connect(mpSocket, SIGNAL(disconnected()), this, SLOT(when_disconnected()));
connect(mpSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(when_error(QAbstractSocket::SocketError)));
connect(mpSocket, SIGNAL(readyRead()), this, SLOT(when_dataAvail()));
}
PortGroup::~PortGroup()
{
qDebug("PortGroup Destructor");
// Disconnect and free TCP mpSocketet etc.
PortGroup::disconnectFromHost();
delete mpSocket;
}
void PortGroup::connectToHost(QHostAddress ip, quint16 port)
{
mServerAddress = ip;
mServerPort = port;
PortGroup::connectToHost();
}
void PortGroup::connectToHost()
{
qDebug("PortGroup::connectToHost()");
mpSocket->connectToHost(mServerAddress, mServerPort);
}
void PortGroup::disconnectFromHost()
{
mpSocket->disconnectFromHost();
}
// --------------------------------------------
// Private Methods
// --------------------------------------------
void PortGroup::ProcessMsg(const char *msg, quint32 size)
{
tCommHdr *hdr;
// TODO: For now, assuming we'll get a complete msg
// but need to fix this as this is a TCP stream
hdr = (tCommHdr*) msg;
if (hdr->ver != 1) // FIXME:hardcoding
{
qDebug("Rcvd msg with invalid version %d\n", hdr->ver);
goto _exit;
}
qDebug("msgType - %x\n", NTOHS(hdr->msgType));
switch (NTOHS(hdr->msgType))
{
case e_MT_CapabilityInfo:
ProcessCapabilityInfo(msg+sizeof(tCommHdr),
NTOHS(hdr->msgLen)-sizeof(tCommHdr));
break;
default:
qDebug("Rcvd msg with unrecognized msgType %d\n", NTOHS(hdr->msgType));
}
_exit:
return;
}
void PortGroup::ProcessCapabilityInfo(const char *msg, qint32 size)
{
tTlvPortCapability *cap = (tTlvPortCapability*) msg;
Port *p;
emit portListAboutToBeChanged(mPortGroupId);
while (size)
{
qDebug("size = %d, tlvType = %d, tlvLen = %d\n",
size, NTOHS(cap->tlvType), NTOHS(cap->tlvLen));
if (NTOHS(cap->tlvType) != e_TT_PortCapability)
{
qDebug("Unrecognized TLV Type %d\n", NTOHS(cap->tlvType));
goto _next;
}
p = new Port(NTOHL(cap->port), mPortGroupId);
p->setName(cap->name);
p->setDescription(cap->desc);
p->insertDummyStreams(); // FIXME: only for testing
qDebug("before port append\n");
mPorts.append(*p);
_next:
size -= NTOHS(cap->tlvLen);
cap = (tTlvPortCapability*)((char *)(cap) + NTOHS(cap->tlvLen));
}
emit portListChanged(mPortGroupId);
return;
}
// ------------------------------------------------
// Slots
// ------------------------------------------------
void PortGroup::on_mpSocket_stateChanged()
{
qDebug("state changed");
emit portGroupDataChanged(this);
}
void PortGroup::when_connected()
{
qDebug("connected\n");
emit portGroupDataChanged(this);
// Ask for Port Capability
tCommHdr pkt;
pkt.ver = 1;
pkt.resv1 = 0;
pkt.resv2 = 0;
pkt.msgType = HTONS(e_MT_CapabilityReq);
pkt.msgLen = HTONS(8);
mpSocket->write((char*) &pkt, sizeof(pkt));
}
void PortGroup::when_disconnected()
{
qDebug("disconnected\n");
emit portListAboutToBeChanged(mPortGroupId);
mPorts.clear();
emit portListChanged(mPortGroupId);
emit portGroupDataChanged(this);
}
void PortGroup::when_error(QAbstractSocket::SocketError socketError)
{
qDebug("error\n");
emit portGroupDataChanged(this);
}
void PortGroup::when_dataAvail()
{
qDebug("dataAvail\n");
QByteArray msg = mpSocket->read(1024); // FIXME: hardcoding
ProcessMsg(msg.constData(), msg.size());
}

66
client/portgroup.h Normal file
View File

@ -0,0 +1,66 @@
#ifndef _PORT_GROUP_H
#define _PORT_GROUP_H
#include "port.h"
#include <QHostAddress>
#include <QTcpSocket>
/* TODO
HIGH
MED
LOW
- Allow hostnames in addition to IP Address as "server address"
*/
#define DEFAULT_SERVER_PORT 7878
class PortGroup : public QObject {
Q_OBJECT
private:
quint32 mPortGroupId;
static quint32 mPortGroupAllocId;
QString mUserAlias; // user defined
QTcpSocket *mpSocket;
QHostAddress mServerAddress;
quint16 mServerPort;
public: // FIXME(HIGH): member access
QList<Port> mPorts;
public:
PortGroup(QHostAddress ip = QHostAddress::LocalHost,
quint16 port = DEFAULT_SERVER_PORT);
~PortGroup();
void connectToHost();
void connectToHost(QHostAddress ip, quint16 port);
void disconnectFromHost();
int numPorts() const { return mPorts.size(); }
quint32 id() const { return mPortGroupId; }
const QHostAddress& serverAddress() const { return mServerAddress; }
quint16 serverPort() const { return mServerPort; }
const QString& userAlias() const { return mUserAlias; }
QAbstractSocket::SocketState state() const { return mpSocket->state(); }
void setUserAlias(QString alias) { mUserAlias = alias; };
signals:
void portGroupDataChanged(PortGroup* portGroup);
void portListAboutToBeChanged(quint32 portGroupId);
void portListChanged(quint32 portGroupId);
private slots:
void on_mpSocket_stateChanged();
void when_connected();
void when_disconnected();
void when_error(QAbstractSocket::SocketError socketError);
void when_dataAvail();
private:
void ProcessCapabilityInfo(const char *msg, qint32 size);
void ProcessMsg(const char *msg, quint32 size);
};
#endif

108
client/portgrouplist.cpp Normal file
View File

@ -0,0 +1,108 @@
#include "portgrouplist.h"
// TODO(LOW): Remove
#include <modeltest.h>
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)
{
if (mPortGroupListModel.isPortGroup(index))
{
//return *(mPortGroups[mPortGroupListModel.portGroupId(index)]);
return *(mPortGroups[index.row()]);
}
#if 0 // FIXME(MED)
else
return NULL;
#endif
}
Port& PortGroupList::port(const QModelIndex& index)
{
if (mPortGroupListModel.isPort(index))
{
return (mPortGroups.at(index.parent().row())->
mPorts[index.row()]);
}
#if 0 // FIXME(MED)
else
return NULL;
#endif
}
void PortGroupList::addPortGroup(PortGroup &portGroup)
{
mPortGroupListModel.portGroupAboutToBeAppended();
connect(&portGroup, SIGNAL(portGroupDataChanged(PortGroup*)),
&mPortGroupListModel, SLOT(when_portGroupDataChanged(PortGroup*)));
#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()));
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;
}

47
client/portgrouplist.h Normal file
View File

@ -0,0 +1,47 @@
#ifndef _PORT_GROUP_LIST_H
#define _PORT_GROUP_LIST_H
#include "portgroup.h"
#include <QAbstractItemModel>
#include <QItemSelection>
#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<PortGroup*> mPortGroups;
PortModel mPortGroupListModel;
StreamModel mStreamListModel;
PortStatsModel mPortStatsModel;
// Methods
public:
PortGroupList::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);
void addPortGroup(PortGroup &portGroup);
void removePortGroup(PortGroup &portGroup);
private:
int indexOfPortGroup(quint32 portGroupId);
};
#endif

View File

@ -0,0 +1,55 @@
#ifndef _PORT_GROUP_LIST_H
#define _PORT_GROUP_LIST_H
#include "portgroup.h"
#include <QAbstractItemModel>
/* -----------------------------------------------------------
** NOTE: FILE NOT USED 'COZ MOC DOESN'T SUPPORT NESTED CLASSES
*-------------------------------------------------------------*/
class PortGroupList;
class PortGroupList : public QObject {
Q_OBJECT
class PortListModel : public QAbstractItemModel
{
// This is currently a read only model
Q_OBJECT
PortGroupList *pgl; // FIXME(HIGH): rename member
public:
PortListModel(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;
friend class PortGroupList; // FIXME(MED): Review need for friend
};
friend class PortListModel;
QList<PortGroup*> mPortGroups;
PortListModel mPortGroupListModel;
// Methods
public:
PortGroupList::PortGroupList();
QAbstractItemModel* getModel();
int addPortGroup(PortGroup &portGroup);
int removePortGroup(PortGroup &portGroup);
private slots:
void when_portlist_dataChanged();
};
#endif

191
client/portlistmodel.cpp Normal file
View File

@ -0,0 +1,191 @@
#include "portlistmodel.h"
-----------------------
This file is not used
-----------------------
PortListModel::PortListModel(QObject *parent)
: QAbstractItemModel(parent)
{
portList = new QList<PortGroup>;
#if 0 // FIXME: Dummy data only for testing; to be removed
PortGroup pg;
pg.name = "A";
pg.isLocal = TRUE;
pg.numPorts = 3;
pg.port = new Port[pg.numPorts];
pg.port[0].portId = 0;
pg.port[0].name = "A0";
pg.port[0].desc = "a0a0a0a0a0a0";
pg.port[1].portId = 1;
pg.port[1].name = "A1";
pg.port[1].desc = "a1a1a1a1a1a1";
pg.port[2].portId = 2;
pg.port[2].name = "A2";
pg.port[2].desc = "a2a2a2a2a2a2";
portList->append(pg);
pg.name = "B";
pg.isLocal = FALSE;
pg.numPorts = 2;
pg.port = new Port[pg.numPorts];
pg.port[0].portId = 0;
pg.port[0].name = "B0";
pg.port[0].desc = "b0b0b0b0b0b0";
pg.port[1].portId = 1;
pg.port[1].name = "B1";
pg.port[1].desc = "b1b1b1b1b1b1";
portList->append(pg);
#endif
// Do I need to do anything here?
}
int PortListModel::rowCount(const QModelIndex &parent) const
{
// qDebug("RowCount Enter\n");
if (!parent.isValid())
{
// Top Level Item
// qDebug("RowCount top\n");
// qDebug("RowCount Exit: %d\n", portList->size());
return portList->size();
}
// qDebug("RowCount non top %d, %d, %llx\n",
// parent.row(), parent.column(), parent.internalId());
quint16 p = parent.internalId() & 0xFFFF;
if (p == 0xFFFF)
{
// qDebug("RowCount Exit: %d\n", portList->at(parent.row()).numPorts);
return portList->at(parent.row()).numPorts;
}
else
{
// Leaf Item
return 0;
}
}
int PortListModel::columnCount(const QModelIndex &parent ) const
{
return 1; // FIXME: hardcoding
}
Qt::ItemFlags PortListModel::flags(const QModelIndex &index) const
{
return QAbstractItemModel::flags(index); // FIXME: no need for this func
}
QVariant PortListModel::data(const QModelIndex &index, int role) const
{
//qDebug("Enter PortListModel data\n");
// Check for a valid index
if (!index.isValid())
return QVariant();
// Check role
if ((role == Qt::DisplayRole))
{
#if 0 // Only for debug
qDebug("Exit PortListModel data\n");
return "Testing"; // FIXME: for dbg only
#endif
QModelIndex parent = index.parent();
if (!parent.isValid())
{
// Top Level Item
return QString("%1 (%2) [%3]").
arg(portList->at(index.row()).name).
arg(portList->at(index.row()).isLocal == TRUE? "LOCAL" : "REMOTE").
arg(portList->at(index.row()).numPorts);
}
return QString("%1: %2 (%3)").
arg(portList->at(parent.row()).port[index.row()].portId).
arg(portList->at(parent.row()).port[index.row()].name).
arg(portList->at(parent.row()).port[index.row()].desc);
}
else
return QVariant();
}
QVariant PortListModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role != Qt::DisplayRole)
return QVariant();
if (orientation == Qt::Horizontal)
return QVariant();
else
return QString("%1").arg(section+1);
}
QModelIndex PortListModel::index (int row, int col,
const QModelIndex & parent) const
{
#if 0
if (!hasIndex(row, col, parent))
return QModelIndex();
#endif
//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 = row, 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.row(), p = row;
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 PortListModel::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(pg, 0, id);
}
void PortListModel::doRefresh()
{
emit layoutChanged();
}

37
client/portlistmodel.h Normal file
View File

@ -0,0 +1,37 @@
#ifndef _PORT_LIST_MODEL_H
#define _PORT_LIST_MODEL_H
-----------------
This file is not used
------------------
#include <QAbstractItemModel>
#include <QStringList>
#include "portgroup.h"
static QStringList PortListCols = (QStringList()
<< "Name"
);
class PortListModel : public QAbstractItemModel
{
Q_OBJECT
public:
//PortListModel(QObject *parent = 0) : QAbstractItemModel(parent) {}
PortListModel(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;
void doRefresh(); // FIXME: temp till model exports functions to insert rows
QList<PortGroup> *portList; // FIXME: this shd be private
};
#endif

314
client/portmodel.cpp Normal file
View File

@ -0,0 +1,314 @@
#include "portmodel.h"
#include "portgrouplist.h"
#include <QIcon>
#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();
return QIcon(":/icons/bullet_green.png");
}
else
{
DBG0("Exit PortModel data 6\n");
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(PortGroup* portGroup)
{
QModelIndex index;
if (!pgl->mPortGroups.contains(portGroup))
{
qDebug("when_portGroupDataChanged(): pg not in list - do nothing");
return;
}
qDebug("when_portGroupDataChanged pgid = %d", portGroup->id());
qDebug("when_portGroupDataChanged idx = %d", pgl->mPortGroups.indexOf(portGroup));
index = createIndex(pgl->mPortGroups.indexOf(portGroup), 0,
(portGroup->id() << 16) | 0xFFFF);
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();
}
#if 0
void PortModel::triggerLayoutAboutToBeChanged()
{
emit layoutAboutToBeChanged();
}
void PortModel::triggerLayoutChanged()
{
emit layoutChanged();
}
#endif
void PortModel::when_portListChanged()
{
reset();
}

51
client/portmodel.h Normal file
View File

@ -0,0 +1,51 @@
#ifndef _PORT_MODEL_H
#define _PORT_MODEL_H
#include <QAbstractItemModel>
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(PortGroup *portGroup);
void portGroupAboutToBeAppended();
void portGroupAppended();
void portGroupAboutToBeRemoved(PortGroup *portGroup);
void portGroupRemoved();
void when_portListChanged();
#if 0
void triggerLayoutAboutToBeChanged();
void triggerLayoutChanged();
#endif
};
#endif

124
client/portstatsfilter.ui Normal file
View File

@ -0,0 +1,124 @@
<ui version="4.0" >
<class>Dialog</class>
<widget class="QDialog" name="Dialog" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>402</width>
<height>275</height>
</rect>
</property>
<property name="windowTitle" >
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" >
<item>
<layout class="QHBoxLayout" >
<item>
<widget class="QListView" name="lvAllPorts" />
</item>
<item>
<layout class="QVBoxLayout" >
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="tbFilterIn" >
<property name="text" >
<string>></string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="tbFilterOut" >
<property name="text" >
<string>&lt;</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QListView" name="lvFilteredPorts" />
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons" >
<set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>lvAllPorts</tabstop>
<tabstop>tbFilterIn</tabstop>
<tabstop>tbFilterOut</tabstop>
<tabstop>lvFilteredPorts</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel" >
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel" >
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel" >
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel" >
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -0,0 +1,9 @@
#include "portstatsfilterdialog.h"
PortStatsFilterDialog::PortStatsFilterDialog(AbstractItemModel *allPortsModel,
QWidget *parent)
{
setupUi(this);
lvAllPorts->setModel(allPortsModel);
}

View File

@ -0,0 +1,19 @@
#ifndef _PORT_STATS_FILTER_DIALOG_H
#define _PORT_STATS_FILTER_DIALOG_H
#include <QDialog>
#include <QAbstractItemModel>
#include "ui_portstatsfilterdialog.h"
#include "portgrouplist.h"
class PortStatsFilterDialog : public QDialog, public Ui::PortStatsFilterDialog
{
Q_OBJECT
public:
PortStatsFilterDialog(AbstractItemModel *allPortsModel,
QWidget *parent = 0);
};
#endif

119
client/portstatsmodel.cpp Normal file
View File

@ -0,0 +1,119 @@
#include "portstatsmodel.h"
#include "portgrouplist.h"
PortStatsModel::PortStatsModel(PortGroupList *p, QObject *parent)
: QAbstractTableModel(parent)
{
pgl = p;
}
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();
}
QVariant PortStatsModel::data(const QModelIndex &index, int role) const
{
int pgidx, pidx, portNum;
// Check for a valid index
if (!index.isValid())
return QVariant();
// Check for row/column limits
if (index.row() >= e_STAT_MAX)
return QVariant();
if (numPorts.isEmpty())
return QVariant();
if (index.column() >= (numPorts.last()))
return QVariant();
// TODO(LOW): Optimize using binary search: see qLowerBound()
portNum = index.column() + 1;
for (pgidx = 0; pgidx < numPorts.size(); pgidx++)
if (portNum <= numPorts.at(pgidx))
break;
if (pgidx)
{
if (numPorts.at(pgidx -1))
pidx = (portNum - 1) % numPorts.at(pgidx - 1);
else
pidx = portNum - 1;
}
else
pidx = portNum - 1;
//qDebug("PSM: %d - %d, %d", index.column(), pgidx, pidx);
// Check role
if (role == Qt::DisplayRole)
return pgl->mPortGroups.at(pgidx)->mPorts.at(pidx).mPortStats[index.row()];
else
return QVariant();
}
QVariant PortStatsModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role != Qt::DisplayRole)
return QVariant();
if (orientation == Qt::Horizontal)
return QString("Port %1").arg(section);
else
return PortStatName.at(section);
}
//
// 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)
{
// FIXME(MED): update only the changed port not all
QModelIndex topLeft = index(port, 0, QModelIndex());
QModelIndex bottomRight = index(port, e_STAT_MAX, QModelIndex());
emit dataChanged(topLeft, bottomRight);
}

59
client/portstatsmodel.h Normal file
View File

@ -0,0 +1,59 @@
#ifndef _PORT_STATS_MODEL_H
#define _PORT_STATS_MODEL_H
#include <QAbstractTableModel>
#include <QStringList>
typedef enum {
e_STAT_FRAMES_RCVD = 0,
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,
e_STAT_MAX
} PortStat;
static QStringList PortStatName = (QStringList()
<< "Frames Received"
<< "Frames Sent"
<< "Frame Send Rate (fps)"
<< "Frame Receive Rate (fps)"
<< "Bytes Received"
<< "Bytes Sent"
<< "Byte Send Rate (Bps)"
<< "Byte Receive Rate (Bps)"
);
class PortGroupList;
class PortStatsModel : public QAbstractTableModel
{
Q_OBJECT
PortGroupList *pgl;
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;
public slots:
void when_portListChanged();
void on_portStatsUpdate(int port, void*stats);
private:
// 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<quint16> numPorts;
};
#endif

View File

@ -0,0 +1,15 @@
#include "portstatswindow.h"
#include "portstatsmodel.h"
//PortStatsWindow::PortStatsWindow(QWidget *parent) : QDialog (parent)
PortStatsWindow::PortStatsWindow(PortGroupList *pgl, QWidget *parent)
{
setupUi(this);
tvPortStats->setModel(pgl->getPortStatsModel());
}
PortStatsWindow::~PortStatsWindow()
{
}

21
client/portstatswindow.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef _PORT_STATS_WINDOW_H
#define _PORT_STATS_WINDOW_H
#include <QDialog>
#include <QAbstractItemModel>
#include "ui_portstatswindow.h"
#include "portgrouplist.h"
class PortStatsWindow : public QDialog, public Ui::PortStatsWindow
{
Q_OBJECT
public:
PortStatsWindow(PortGroupList *pgl, QWidget *parent = 0);
~PortStatsWindow();
private:
QAbstractItemModel *model;
};
#endif

133
client/portstatswindow.ui Normal file
View File

@ -0,0 +1,133 @@
<ui version="4.0" >
<class>PortStatsWindow</class>
<widget class="QWidget" name="PortStatsWindow" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>502</width>
<height>415</height>
</rect>
</property>
<property name="windowTitle" >
<string>Form</string>
</property>
<layout class="QVBoxLayout" >
<item>
<widget class="QFrame" name="frame" >
<property name="frameShape" >
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow" >
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" >
<item>
<widget class="QToolButton" name="tbStartTransmit" >
<property name="toolTip" >
<string>Start Transmit</string>
</property>
<property name="statusTip" >
<string>Stop Transmit</string>
</property>
<property name="text" >
<string>Start Transmit</string>
</property>
<property name="icon" >
<iconset resource="ostinato.qrc" >:/icons/control_play.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="tbStopTransmit" >
<property name="toolTip" >
<string>Stop Transmit</string>
</property>
<property name="statusTip" >
<string>Stop Transmit</string>
</property>
<property name="text" >
<string>Stop Trasmit</string>
</property>
<property name="icon" >
<iconset resource="ostinato.qrc" >:/icons/control_stop.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="tbClear" >
<property name="text" >
<string>Clear</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="tbClearAll" >
<property name="text" >
<string>Clear All</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="tbStartCapture" >
<property name="text" >
<string>Start Capture</string>
</property>
<property name="icon" >
<iconset resource="ostinato.qrc" >:/icons/sound_none.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="tbStopCapture" >
<property name="text" >
<string>Stop Capture</string>
</property>
<property name="icon" >
<iconset resource="ostinato.qrc" >:/icons/sound_mute.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="tbViewCapture" >
<property name="text" >
<string>View Capture</string>
</property>
<property name="icon" >
<iconset resource="ostinato.qrc" >:/icons/magnifier.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line" >
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QTableView" name="tvPortStats" />
</item>
</layout>
</widget>
<resources>
<include location="ostinato.qrc" />
</resources>
<connections/>
</ui>

320
client/portswindow.cpp Normal file
View File

@ -0,0 +1,320 @@
#include "portswindow.h"
#include "streamlistmodel.h"
#include "streamconfigdialog.h"
#include <QInputDialog>
#include <QItemSelectionModel>
PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
{
//slm = new StreamListModel();
//plm = new PortGroupList();
plm = pgl;
setupUi(this);
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(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( 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()));
connect( tvPortList->selectionModel(),
SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)),
plm->getStreamModel(), SLOT(setCurrentPortIndex(const QModelIndex&)));
}
PortsWindow::~PortsWindow()
{
delete plm;
}
void PortsWindow::on_tvStreamList_activated(const QModelIndex & index)
{
StreamConfigDialog *scd;
if (!index.isValid())
{
qDebug("%s: invalid index", __FUNCTION__);
return;
}
// FIXME(MED): This way of passing params must be changed
scd = new StreamConfigDialog(plm->getStreamModel()->currentPortStreamList(),
(uint) 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)
{
updatePortViewActions(current);
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());
}
}
#if 0
void PortsWindow::updateStreamViewActions(const QModelIndex& current)
{
if (current.isValid())
actionDelete_Stream->setEnabled(true);
else
actionDelete_Stream->setDisabled(true);
}
#endif
void PortsWindow::updateStreamViewActions()
{
if (tvStreamList->selectionModel()->hasSelection())
{
qDebug("Has selection %d",
tvStreamList->selectionModel()->selection().size());
// If more than one non-contiguous ranges selected, disable "New"
if (tvStreamList->selectionModel()->selection().size() > 1)
actionNew_Stream->setDisabled(true);
else
actionNew_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);
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()
{
{
// 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");
}
}
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_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");
}

56
client/portswindow.h Normal file
View File

@ -0,0 +1,56 @@
#ifndef _PORTS_WINDOW_H
#define _PORTS_WINDOW_H
#include <QWidget>
#include <QAbstractItemModel>
#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 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_actionDelete_Stream_triggered();
};
#endif

214
client/portswindow.ui Normal file
View File

@ -0,0 +1,214 @@
<ui version="4.0" >
<class>PortsWindow</class>
<widget class="QWidget" name="PortsWindow" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>689</width>
<height>320</height>
</rect>
</property>
<property name="windowTitle" >
<string>Form</string>
</property>
<layout class="QHBoxLayout" >
<item>
<widget class="QSplitter" name="splitter" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<widget class="QTreeView" name="tvPortList" >
<property name="contextMenuPolicy" >
<enum>Qt::ActionsContextMenu</enum>
</property>
<property name="selectionMode" >
<enum>QAbstractItemView::SingleSelection</enum>
</property>
</widget>
<widget class="QStackedWidget" name="swDetail" >
<property name="currentIndex" >
<number>0</number>
</property>
<widget class="QWidget" name="portDetail" >
<layout class="QVBoxLayout" >
<item>
<layout class="QHBoxLayout" >
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pbApply" >
<property name="text" >
<string>Apply</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QGridLayout" >
<item rowspan="2" row="0" column="0" >
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>31</width>
<height>41</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1" >
<widget class="QLabel" name="label" >
<property name="text" >
<string>Capacity</string>
</property>
</widget>
</item>
<item row="0" column="2" >
<widget class="QLineEdit" name="lineEdit_3" />
</item>
<item row="0" column="3" >
<widget class="QLabel" name="label_3" >
<property name="text" >
<string>Aggr fps</string>
</property>
</widget>
</item>
<item row="0" column="4" >
<widget class="QLineEdit" name="lineEdit" />
</item>
<item row="1" column="1" >
<widget class="QLabel" name="label_2" >
<property name="text" >
<string>% age</string>
</property>
</widget>
</item>
<item row="1" column="2" >
<widget class="QLineEdit" name="lineEdit_4" />
</item>
<item row="1" column="3" >
<widget class="QLabel" name="label_4" >
<property name="text" >
<string>Aggr bps</string>
</property>
</widget>
</item>
<item row="1" column="4" >
<widget class="QLineEdit" name="lineEdit_2" />
</item>
</layout>
</item>
<item>
<widget class="QTabWidget" name="tabWidget" >
<property name="currentIndex" >
<number>0</number>
</property>
<widget class="QWidget" name="tab_3" >
<attribute name="title" >
<string>Control</string>
</attribute>
<layout class="QHBoxLayout" >
<item>
<widget class="QTableView" name="tvStreamList" >
<property name="contextMenuPolicy" >
<enum>Qt::ActionsContextMenu</enum>
</property>
<property name="selectionMode" >
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="selectionBehavior" >
<enum>QAbstractItemView::SelectRows</enum>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="portGroupDetail" >
<layout class="QHBoxLayout" >
<item>
<widget class="QLabel" name="label_5" >
<property name="text" >
<string>Port Group Detail</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="blankPage" />
</widget>
</widget>
</item>
</layout>
<action name="actionNew_Port_Group" >
<property name="icon" >
<iconset resource="ostinato.qrc" >:/icons/portgroup_add.png</iconset>
</property>
<property name="text" >
<string>New Port Group</string>
</property>
</action>
<action name="actionDelete_Port_Group" >
<property name="icon" >
<iconset resource="ostinato.qrc" >:/icons/portgroup_delete.png</iconset>
</property>
<property name="text" >
<string>Delete Port Group</string>
</property>
</action>
<action name="actionConnect_Port_Group" >
<property name="icon" >
<iconset resource="ostinato.qrc" >:/icons/portgroup_connect.png</iconset>
</property>
<property name="text" >
<string>Connect Port Group</string>
</property>
</action>
<action name="actionDisconnect_Port_Group" >
<property name="icon" >
<iconset resource="ostinato.qrc" >:/icons/portgroup_disconnect.png</iconset>
</property>
<property name="text" >
<string>Disconnect Port Group</string>
</property>
</action>
<action name="actionNew_Stream" >
<property name="icon" >
<iconset resource="ostinato.qrc" >:/icons/stream_add.png</iconset>
</property>
<property name="text" >
<string>New Stream</string>
</property>
</action>
<action name="actionDelete_Stream" >
<property name="icon" >
<iconset resource="ostinato.qrc" >:/icons/stream_delete.png</iconset>
</property>
<property name="text" >
<string>Delete Stream</string>
</property>
</action>
</widget>
<resources>
<include location="ostinato.qrc" />
</resources>
<connections/>
</ui>

123
client/stream.cpp Normal file
View File

@ -0,0 +1,123 @@
#include <stream.h>
Stream::Stream()
{
// Default constructor
InitDefaultMeta();
InitDefaultProto();
InitDefaultL2();
InitDefaultL3();
InitDefaultL4();
}
void Stream::InitDefaultMeta()
{
// TODO(LOW): Use #defines
meta.patternMode = e_dp_fixed;
meta.pattern = 0x00000000;
meta.dataStartOfs = 0; // FIXME(HIGH): this has to calculated
meta.lenMode = e_fl_fixed;
meta.frameLen = 64;
meta.frameLenMin = 64;
meta.frameLenMax = 1518;
}
void Stream::InitDefaultProto()
{
// TODO(LOW): Use #defines
proto.ft = e_ft_eth_2;
proto.dsap = 0x00;
proto.ssap = 0x00;
proto.ctl = 0x00;
proto.ouiMsb = 0x00;
proto.ouiLshw = 0x0000;
proto.protoMask = PM_L3_PROTO_NONE | PM_L4_PROTO_NONE;
proto.etherType = ETH_TYP_IP;
proto.ipProto = IP_PROTO_TCP;
}
void Stream::InitDefaultL2()
{
// TODO(LOW): Use #defines
l2.eth.dstMacMshw = 0x0000;
l2.eth.dstMacLsw = 0x00000001;
l2.eth.dstMacMode = e_mm_fixed;
l2.eth.dstMacCount = 16;
l2.eth.dstMacStep = 1;
l2.eth.srcMacMshw = 0x0000;
l2.eth.srcMacLsw = 0x00000002;
l2.eth.srcMacMode = e_mm_fixed;
l2.eth.srcMacCount = 16;
l2.eth.srcMacStep = 1;
l2.eth.vlanMask = VM_UNTAGGED;
l2.eth.ctpid = 0x8100;
l2.eth.cvlanPrio = 0;
l2.eth.cvlanCfi = 0;
l2.eth.cvlanId = 2;
l2.eth.stpid = 0x88a8;
l2.eth.svlanPrio = 0;
l2.eth.svlanCfi = 0;
l2.eth.svlanId = 2;
}
void Stream::InitDefaultL3()
{
InitDefaultL3Ip();
}
void Stream::InitDefaultL3Ip()
{
l3.ip.ipMask = STREAM_DEF_IP_MASK;
l3.ip.ver = STREAM_DEF_L3_IP_VER;
l3.ip.hdrLen = STREAM_DEF_L3_IP_HDR_LEN;
l3.ip.tos = STREAM_DEF_L3_IP_TOS;
l3.ip.totLen = STREAM_DEF_L3_IP_TOT_LEN;
l3.ip.id = STREAM_DEF_L3_IP_ID;
l3.ip.flags = STREAM_DEF_L3_IP_FLAGS;
l3.ip.fragOfs = STREAM_DEF_L3_IP_FRAG_OFS;
l3.ip.ttl = STREAM_DEF_L3_IP_TTL;
l3.ip.proto = STREAM_DEF_L3_IP_PROTO;
l3.ip.cksum = STREAM_DEF_L3_IP_CKSUM;
l3.ip.srcIp = STREAM_DEF_L3_IP_SRC_IP;
l3.ip.srcIpMode = STREAM_DEF_L3_IP_SRC_IP_MODE;
l3.ip.srcIpCount = STREAM_DEF_L3_IP_SRC_IP_COUNT;
l3.ip.srcIpMask = STREAM_DEF_L3_IP_SRC_IP_MASK;
l3.ip.dstIp = STREAM_DEF_L3_IP_DST_IP;
l3.ip.dstIpMode = STREAM_DEF_L3_IP_DST_IP_MODE;
l3.ip.dstIpCount = STREAM_DEF_L3_IP_DST_IP_COUNT;
l3.ip.dstIpMask = STREAM_DEF_L3_IP_DST_IP_MASK;
}
void Stream::InitDefaultL4()
{
InitDefaultL4Tcp();
InitDefaultL4Udp();
}
void Stream::InitDefaultL4Tcp()
{
l4.tcp.tcpMask = STREAM_DEF_L4_TCP_TCP_MASK;
l4.tcp.srcPort = STREAM_DEF_L4_TCP_SRC_PORT;
l4.tcp.dstPort = STREAM_DEF_L4_TCP_DST_PORT;
l4.tcp.seqNum = STREAM_DEF_L4_TCP_SEQ_NUM;
l4.tcp.ackNum = STREAM_DEF_L4_TCP_ACK_NUM;
l4.tcp.hdrLen = STREAM_DEF_L4_TCP_HDR_LEN;
l4.tcp.rsvd = STREAM_DEF_L4_TCP_RSVD;
l4.tcp.flags = STREAM_DEF_L4_TCP_FLAGS;
l4.tcp.window = STREAM_DEF_L4_TCP_WINDOW;
l4.tcp.cksum = STREAM_DEF_L4_TCP_CKSUM;
l4.tcp.urgPtr = STREAM_DEF_L4_TCP_URG_PTR;
}
void Stream::InitDefaultL4Udp()
{
l4.udp.udpMask = STREAM_DEF_L4_UDP_UDP_MASK;
l4.udp.srcPort = STREAM_DEF_L4_UDP_SRC_PORT;
l4.udp.dstPort = STREAM_DEF_L4_UDP_DST_PORT;
l4.udp.totLen = STREAM_DEF_L4_UDP_TOT_LEN;
l4.udp.cksum = STREAM_DEF_L4_UDP_CKSUM;
}

307
client/stream.h Normal file
View File

@ -0,0 +1,307 @@
#ifndef _STREAM_H
#define _STREAM_H
#include <QtGlobal>
#include <QString>
class StreamConfigDialog;
class StreamModel;
class Stream {
friend class StreamConfigDialog;
friend class StreamModel;
enum FrameType {
e_ft_none,
e_ft_eth_2,
e_ft_802_3_raw,
e_ft_802_3_llc,
e_ft_snap
};
enum DataPatternMode {
e_dp_fixed,
e_dp_inc,
e_dp_dec,
e_dp_random
};
enum FrameLengthMode {
e_fl_fixed,
e_fl_inc,
e_fl_dec,
e_fl_random
};
enum MacAddrMode {
e_mm_fixed,
e_mm_inc,
e_mm_dec,
};
enum IpAddrMode {
e_im_fixed,
e_im_inc_host,
e_im_dec_host,
e_im_random_host
};
// Meta Data
struct {
// Data Pattern
DataPatternMode patternMode;
quint32 pattern;
quint16 dataStartOfs;
// Frame Length (includes CRC)
FrameLengthMode lenMode;
quint16 frameLen;
quint16 frameLenMin;
quint16 frameLenMax;
} meta;
// Protocols
struct {
FrameType ft;
quint8 dsap;
quint8 ssap;
quint8 ctl;
quint8 ouiMsb;
quint16 ouiLshw;
quint16 protoMask;
#define PM_L3_PROTO_NONE 0x0001
#define PM_L3_PROTO_OTHER 0x0002
#define PM_L4_PROTO_NONE 0x0004
#define PM_L4_PROTO_OTHER 0x0008
quint16 etherType;
#define ETH_TYP_IP 0x0800
#define ETH_TYP_ARP 0x0806
quint16 ipProto;
#define IP_PROTO_ICMP 0x01
#define IP_PROTO_IGMP 0x02
#define IP_PROTO_TCP 0x06
#define IP_PROTO_UDP 0x11
} proto;
// L2
struct {
// Ethernet
struct {
// Dst Mac
quint16 dstMacMshw;
quint32 dstMacLsw;
MacAddrMode dstMacMode;
quint16 dstMacCount;
quint16 dstMacStep;
// srcMac
quint16 srcMacMshw;
quint32 srcMacLsw;
MacAddrMode srcMacMode;
quint16 srcMacCount;
quint16 srcMacStep;
quint16 vlanMask;
#define VM_UNTAGGED 0x0000
#define VM_CVLAN_TAGGED 0x0001
#define VM_CVLAN_TPID_OVERRIDE 0x0002
#define VM_SVLAN_TAGGED 0x0100
#define VM_SVLAN_TPID_OVERRIDE 0x0200
quint16 ctpid;
quint16 cvlanPrio : 3;
quint16 cvlanCfi : 1;
quint16 cvlanId : 13;
quint16 stpid;
quint16 svlanPrio : 3;
quint16 svlanCfi : 1;
quint16 svlanId : 13;
} eth;
} l2;
struct {
// IP
struct {
quint8 ipMask;
#define IM_OVERRIDE_VERSION 0x01
#define IM_OVERRIDE_HDRLEN 0x02
#define IM_OVERRIDE_TOTLEN 0x04
#define IM_OVERRIDE_CKSUM 0x08
#define STREAM_DEF_IP_MASK 0x00
quint8 ver : 4;
#define STREAM_DEF_L3_IP_VER 0x4
quint8 hdrLen : 4;
#define STREAM_DEF_L3_IP_HDR_LEN 0x5
quint8 tos;
#define STREAM_DEF_L3_IP_TOS 0x00
quint16 totLen;
#define STREAM_DEF_L3_IP_TOT_LEN 0x00
quint16 id;
#define STREAM_DEF_L3_IP_ID 0x1234
quint16 flags : 3;
#define IP_FLAG_UNUSED 0x1
#define IP_FLAG_DF 0x2
#define IP_FLAG_MF 0x4
#define STREAM_DEF_L3_IP_FLAGS 0x00
quint16 fragOfs : 13;
#define STREAM_DEF_L3_IP_FRAG_OFS 0x0000
quint8 ttl;
#define STREAM_DEF_L3_IP_TTL 0x7F
quint8 proto;
#define STREAM_DEF_L3_IP_PROTO 0x00
quint16 cksum;
#define STREAM_DEF_L3_IP_CKSUM 0x0000
// Source IP
quint32 srcIp;
#define STREAM_DEF_L3_IP_SRC_IP 0x02020202
IpAddrMode srcIpMode;
#define STREAM_DEF_L3_IP_SRC_IP_MODE e_im_fixed
quint16 srcIpCount;
#define STREAM_DEF_L3_IP_SRC_IP_COUNT 16
quint32 srcIpMask;
#define STREAM_DEF_L3_IP_SRC_IP_MASK 0xFFFFFFFF
// Destination IP
quint32 dstIp;
#define STREAM_DEF_L3_IP_DST_IP 0x01010101
IpAddrMode dstIpMode;
#define STREAM_DEF_L3_IP_DST_IP_MODE e_im_fixed
quint16 dstIpCount;
#define STREAM_DEF_L3_IP_DST_IP_COUNT 16
quint32 dstIpMask;
#define STREAM_DEF_L3_IP_DST_IP_MASK 0xFFFFFFFF
// TODO: Options
} ip;
// TODO: ARP
struct {
} arp;
} l3;
// L4
struct {
// TCP
struct {
quint32 tcpMask;
#define TM_OVERRIDE_HDRLEN 0x1
#define TM_OVERRIDE_CKSUM 0x2
#define STREAM_DEF_L4_TCP_TCP_MASK 0x00;
quint16 srcPort;
#define STREAM_DEF_L4_TCP_SRC_PORT 8902;
quint16 dstPort;
#define STREAM_DEF_L4_TCP_DST_PORT 80
quint32 seqNum;
#define STREAM_DEF_L4_TCP_SEQ_NUM 129018
quint32 ackNum;
#define STREAM_DEF_L4_TCP_ACK_NUM 98223
quint8 hdrLen : 4;
#define STREAM_DEF_L4_TCP_HDR_LEN 0x5
quint8 rsvd : 4;
#define STREAM_DEF_L4_TCP_RSVD 0x0
quint8 flags;
#define TCP_FLAG_URG 0x01
#define TCP_FLAG_ACK 0x02
#define TCP_FLAG_PSH 0x04
#define TCP_FLAG_RST 0x08
#define TCP_FLAG_SYN 0x10
#define TCP_FLAG_FIN 0x20
#define STREAM_DEF_L4_TCP_FLAGS 0x00
quint16 window;
#define STREAM_DEF_L4_TCP_WINDOW 1024
quint16 cksum;
#define STREAM_DEF_L4_TCP_CKSUM 0x0000
quint16 urgPtr;
#define STREAM_DEF_L4_TCP_URG_PTR 0x0000
} tcp;
// UDP
struct {
quint32 udpMask;
#define UM_OVERRIDE_TOTLEN 0x01
#define UM_OVERRIDE_CKSUM 0x02
#define STREAM_DEF_L4_UDP_UDP_MASK 0x00
quint16 srcPort;
#define STREAM_DEF_L4_UDP_SRC_PORT 8902
quint16 dstPort;
#define STREAM_DEF_L4_UDP_DST_PORT 80
quint16 totLen;
#define STREAM_DEF_L4_UDP_TOT_LEN 0x0000
quint16 cksum;
#define STREAM_DEF_L4_UDP_CKSUM 0x0000
} udp;
// TODO: ICMP
struct {
} icmp;
// TODO: IGMP
struct {
} igmp;
} l4;
QString mName;
bool mIsEnabled;
// -------------------------------------------------------
// Methods
// -------------------------------------------------------
public:
Stream();
int enable(bool flag);
const QString& name() const { return mName; }
bool isEnabled() const { return mIsEnabled; }
void setName(QString name) { mName = name; }
void setEnabled(bool isEnabled) { mIsEnabled = isEnabled; }
private:
void InitDefaultMeta();
void InitDefaultProto();
void InitDefaultL2();
void InitDefaultL3();
void InitDefaultL3Ip();
void InitDefaultL4();
void InitDefaultL4Tcp();
void InitDefaultL4Udp();
};
#endif

View File

@ -0,0 +1,677 @@
#include <QHostAddress>
#include "streamconfigdialog.h"
#include "stream.h"
StreamConfigDialog::StreamConfigDialog(QList<Stream> *streamList,
uint streamIndex, QWidget *parent) : QDialog (parent)
{
setupUi(this);
setupUiExtra();
// FIXME(MED): Assumption that streamlist and streamIndex are valid
mpStreamList = streamList;
mCurrentStreamIndex = streamIndex;
LoadCurrentStream();
qDebug("stream %p %d/%d loaded",
mpStreamList, mCurrentStreamIndex, mpStreamList->size());
// FIXME(MED): Enable this navigation
#if 0
pbPrev->setDisabled((currStreamIdx == 0));
pbNext->setDisabled((currStreamIdx == 2));
#endif
}
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
twProto->setTabEnabled(2, FALSE);
twProto->setTabEnabled(3, FALSE);
/*
** Setup Validators
*/
// Meta Data
lePktLen->setValidator(new QIntValidator(MIN_PKT_LEN, MAX_PKT_LEN, this));
// L2 Ethernet
leDstMac->setValidator(new QRegExpValidator(reMac, this));
leSrcMac->setValidator(new QRegExpValidator(reMac, this));
leDstMacCount->setValidator(new QIntValidator(1, MAX_MAC_ITER_COUNT, this));
leSrcMacCount->setValidator(new QIntValidator(1, MAX_MAC_ITER_COUNT, this));
leCvlanTpid->setValidator(new QRegExpValidator(reHex2B, this));
leSvlanTpid->setValidator(new QRegExpValidator(reHex2B, this));
//leEtherType->setValidator(new QRegExpValidator(reHex2B, 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()));
// Show "Packet Config" page by default
twTopLevel->setCurrentIndex(0);
}
StreamConfigDialog::~StreamConfigDialog()
{
}
void StreamConfigDialog::on_cmbDstMacMode_currentIndexChanged(QString mode)
{
if (mode == "Fixed")
leDstMacCount->setEnabled(FALSE);
else
leDstMacCount->setEnabled(TRUE);
}
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_rbFtLlcSnap_toggled(bool checked)
{
if (checked)
{
leDsap->setText("AA");
leSsap->setText("AA");
leControl->setText("03");
}
}
void StreamConfigDialog::on_rbL3Ipv4_toggled(bool checked)
{
if (checked)
{
swL3Proto->setCurrentIndex(0);
twProto->setTabEnabled(2, TRUE);
twProto->setTabText(2, "L3 (IPv4)");
leType->setText("08 00");
}
else
{
twProto->setTabEnabled(2, FALSE);
twProto->setTabText(2, "L3");
}
}
void StreamConfigDialog::on_rbL3Arp_toggled(bool checked)
{
if (checked)
{
swL3Proto->setCurrentIndex(1);
twProto->setTabEnabled(2, TRUE);
twProto->setTabText(2, "L3 (ARP)");
leType->setText("08 06");
}
else
{
twProto->setTabEnabled(2, FALSE);
twProto->setTabText(2, "L3");
}
}
void StreamConfigDialog::on_rbL4Icmp_toggled(bool checked)
{
QString str;
if (checked)
{
swL4Proto->setCurrentIndex(2);
twProto->setTabEnabled(3, TRUE);
twProto->setTabText(3, "L4 (ICMP)");
leIpProto->setText(uintToHexStr(IP_PROTO_ICMP, str, 1));
}
else
{
twProto->setTabEnabled(3, FALSE);
twProto->setTabText(3, "L4");
}
}
void StreamConfigDialog::on_rbL4Igmp_toggled(bool checked)
{
QString str;
if (checked)
{
swL4Proto->setCurrentIndex(3);
twProto->setTabEnabled(3, TRUE);
twProto->setTabText(3, "L4 (IGMP)");
leIpProto->setText(uintToHexStr(IP_PROTO_IGMP, str, 1));
}
else
{
twProto->setTabEnabled(3, FALSE);
twProto->setTabText(3, "L4");
}
}
void StreamConfigDialog::on_rbL4Tcp_toggled(bool checked)
{
QString str;
if (checked)
{
swL4Proto->setCurrentIndex(0);
twProto->setTabEnabled(3, TRUE);
twProto->setTabText(3, "L4 (TCP)");
leIpProto->setText(uintToHexStr(IP_PROTO_TCP, str, 1));
}
else
{
twProto->setTabEnabled(3, FALSE);
twProto->setTabText(3, "L4");
}
}
void StreamConfigDialog::on_rbL4Udp_toggled(bool checked)
{
QString str;
if (checked)
{
swL4Proto->setCurrentIndex(1);
twProto->setTabEnabled(3, TRUE);
twProto->setTabText(3, "L4 (UDP)");
leIpProto->setText(uintToHexStr(IP_PROTO_UDP, str, 1));
}
else
{
twProto->setTabEnabled(3, FALSE);
twProto->setTabText(3, "L4");
}
}
void StreamConfigDialog::on_rbL4Other_toggled(bool checked)
{
if (checked)
leIpProto->setEnabled(true);
else
leIpProto->setEnabled(false);
}
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);
}
QString & uintToHexStr(quint32 num, QString &hexStr, quint8 octets)
{
int i;
QChar zero('0');
hexStr = "";
for (i = octets; i > 0; i--)
{
ushort byte;
QString str1 = "%1";
QString str;
byte = num & 0xff;
str = str1.arg(byte, 2, 16, zero).append(' ');
hexStr.prepend(str);
num = num >> 8;
}
return hexStr;
}
#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
void StreamConfigDialog::LoadCurrentStream()
{
Stream *pStream = &((*mpStreamList)[mCurrentStreamIndex]);
QString str;
qDebug("loading pStream %p", pStream);
// Meta Data
{
cmbPatternMode->setCurrentIndex(pStream->meta.patternMode);
lePattern->setText(uintToHexStr(pStream->meta.pattern, str, 4));
cmbPktLenMode->setCurrentIndex(pStream->meta.lenMode);
lePktLen->setText(str.setNum(pStream->meta.frameLen));
lePktLenMin->setText(str.setNum(pStream->meta.frameLenMin));
lePktLenMax->setText(str.setNum(pStream->meta.frameLenMax));
}
// Protocols
{
qDebug("ft = %d\n", pStream->proto.ft);
switch(pStream->proto.ft)
{
case Stream::e_ft_none:
rbFtNone->setChecked(TRUE);
break;
case Stream::e_ft_eth_2:
rbFtEthernet2->setChecked(TRUE);
break;
case Stream::e_ft_802_3_raw:
rbFt802Dot3Raw->setChecked(TRUE);
break;
case Stream::e_ft_802_3_llc:
rbFt802Dot3Llc->setChecked(TRUE);
break;
case Stream::e_ft_snap:
rbFtLlcSnap->setChecked(TRUE);
break;
}
leDsap->setText(uintToHexStr(pStream->proto.dsap, str, 1));
leSsap->setText(uintToHexStr(pStream->proto.ssap, str, 1));
leControl->setText(uintToHexStr(pStream->proto.ctl, str, 1));
leOui->setText(uintToHexStr((pStream->proto.ouiMsb << 16 + pStream->proto.ouiLshw), str, 3));
leType->setText(uintToHexStr(pStream->proto.etherType, str, 2));
// Check for specific supported protocols first ...
if (pStream->proto.etherType == ETH_TYP_IP)
rbL3Ipv4->setChecked(TRUE);
else if (pStream->proto.etherType == ETH_TYP_ARP)
rbL3Arp->setChecked(TRUE);
// ... then for None/Other
rbL3None->setChecked((pStream->proto.protoMask & PM_L3_PROTO_NONE) > 0);
rbL3Other->setChecked((pStream->proto.protoMask & PM_L3_PROTO_OTHER) > 0);
// Check for specific supported protocols first ...
if (pStream->proto.ipProto == IP_PROTO_ICMP)
rbL4Icmp->setChecked(TRUE);
else if (pStream->proto.ipProto == IP_PROTO_IGMP)
rbL4Igmp->setChecked(TRUE);
else if (pStream->proto.ipProto == IP_PROTO_TCP)
rbL4Tcp->setChecked(TRUE);
else if (pStream->proto.ipProto == IP_PROTO_UDP)
rbL4Udp->setChecked(TRUE);
// ... then for None/Other
rbL4None->setChecked((pStream->proto.protoMask & PM_L4_PROTO_NONE) > 0);
rbL4Other->setChecked((pStream->proto.protoMask & PM_L4_PROTO_OTHER) > 0);
}
// L2
{
// L2 | Ethernet
{
leDstMac->setText(uintToHexStr(pStream->l2.eth.dstMacMshw, str, 2) +
uintToHexStr(pStream->l2.eth.dstMacLsw, str, 4));
cmbDstMacMode->setCurrentIndex(pStream->l2.eth.dstMacMode);
leDstMacCount->setText(str.setNum(pStream->l2.eth.dstMacCount));
leDstMacStep->setText(str.setNum(pStream->l2.eth.dstMacStep));
leSrcMac->setText(uintToHexStr(pStream->l2.eth.srcMacMshw, str, 2) +
uintToHexStr(pStream->l2.eth.srcMacLsw, str, 4));
cmbSrcMacMode->setCurrentIndex(pStream->l2.eth.srcMacMode);
leSrcMacCount->setText(str.setNum(pStream->l2.eth.srcMacCount));
leSrcMacStep->setText(str.setNum(pStream->l2.eth.srcMacStep));
cmbCvlanPrio->setCurrentIndex(pStream->l2.eth.cvlanPrio);
cmbCvlanCfi->setCurrentIndex(pStream->l2.eth.cvlanCfi);
leCvlanId->setText(str.setNum(pStream->l2.eth.cvlanId));
leCvlanTpid->setText(str.setNum(pStream->l2.eth.ctpid));
cbCvlanTpidOverride->setChecked((pStream->l2.eth.vlanMask & VM_CVLAN_TPID_OVERRIDE) > 0);
gbCvlan->setChecked((pStream->l2.eth.vlanMask & VM_CVLAN_TAGGED) > 0);
cmbSvlanPrio->setCurrentIndex(pStream->l2.eth.svlanPrio);
cmbSvlanCfi->setCurrentIndex(pStream->l2.eth.svlanCfi);
leSvlanId->setText(str.setNum(pStream->l2.eth.svlanId));
leSvlanTpid->setText(str.setNum(pStream->l2.eth.stpid));
cbSvlanTpidOverride->setChecked((pStream->l2.eth.vlanMask & VM_SVLAN_TPID_OVERRIDE) > 0);
gbSvlan->setChecked((pStream->l2.eth.vlanMask & VM_SVLAN_TAGGED) > 0);
}
}
// L3
{
// L3 | IP
{
leIpVersion->setText(str.setNum(pStream->l3.ip.ver));
cbIpVersionOverride->setChecked((pStream->l3.ip.ipMask & IM_OVERRIDE_VERSION) > 0);
leIpHdrLen->setText(str.setNum(pStream->l3.ip.hdrLen));
cbIpHdrLenOverride->setChecked((pStream->l3.ip.ipMask & IM_OVERRIDE_HDRLEN) > 0);
leIpTos->setText(uintToHexStr(pStream->l3.ip.tos, str, 1));
leIpLength->setText(str.setNum(pStream->l3.ip.totLen));
cbIpLengthOverride->setChecked((pStream->l3.ip.ipMask & IM_OVERRIDE_TOTLEN) > 0);
leIpId->setText(uintToHexStr(pStream->l3.ip.id, str, 2));
leIpFragOfs->setText(str.setNum(pStream->l3.ip.fragOfs));
cbIpFlagsDf->setChecked((pStream->l3.ip.flags & IP_FLAG_DF) > 0);
cbIpFlagsMf->setChecked((pStream->l3.ip.flags & IP_FLAG_MF) > 0);
leIpTtl->setText(str.setNum(pStream->l3.ip.ttl));
leIpProto->setText(uintToHexStr(pStream->l3.ip.proto, str, 1));
leIpCksum->setText(uintToHexStr(pStream->l3.ip.cksum, str, 2));
cbIpCksumOverride->setChecked((pStream->l3.ip.ipMask & IM_OVERRIDE_CKSUM) > 0);
leIpSrcAddr->setText(QHostAddress(pStream->l3.ip.srcIp).toString());
cmbIpSrcAddrMode->setCurrentIndex(pStream->l3.ip.srcIpMode);
leIpSrcAddrCount->setText(str.setNum(pStream->l3.ip.srcIpCount));
leIpSrcAddrMask->setText(QHostAddress(pStream->l3.ip.srcIpMask).toString());
leIpDstAddr->setText(QHostAddress(pStream->l3.ip.dstIp).toString());
cmbIpDstAddrMode->setCurrentIndex(pStream->l3.ip.dstIpMode);
leIpDstAddrCount->setText(str.setNum(pStream->l3.ip.dstIpCount));
leIpDstAddrMask->setText(QHostAddress(pStream->l3.ip.dstIpMask).toString());
}
// L3 | ARP
{
// TODO
}
}
// L4
{
// L4 | TCP
{
leTcpSrcPort->setText(str.setNum(pStream->l4.tcp.srcPort));
leTcpDstPort->setText(str.setNum(pStream->l4.tcp.dstPort));
leTcpSeqNum->setText(str.setNum(pStream->l4.tcp.seqNum));
leTcpAckNum->setText(str.setNum(pStream->l4.tcp.ackNum));
leTcpHdrLen->setText(str.setNum(pStream->l4.tcp.hdrLen));
cbTcpHdrLenOverride->setChecked((pStream->l4.tcp.tcpMask & TM_OVERRIDE_HDRLEN) > 0);
leTcpWindow->setText(str.setNum(pStream->l4.tcp.window));
leTcpCksum->setText(str.setNum(pStream->l4.tcp.cksum));
cbTcpCksumOverride->setChecked((pStream->l4.tcp.tcpMask & TM_OVERRIDE_CKSUM) > 0);
leTcpUrgentPointer->setText(str.setNum(pStream->l4.tcp.urgPtr));
cbTcpFlagsUrg->setChecked((pStream->l4.tcp.flags & TCP_FLAG_URG) > 0);
cbTcpFlagsAck->setChecked((pStream->l4.tcp.flags & TCP_FLAG_ACK) > 0);
cbTcpFlagsPsh->setChecked((pStream->l4.tcp.flags & TCP_FLAG_PSH) > 0);
cbTcpFlagsRst->setChecked((pStream->l4.tcp.flags & TCP_FLAG_RST) > 0);
cbTcpFlagsSyn->setChecked((pStream->l4.tcp.flags & TCP_FLAG_SYN) > 0);
cbTcpFlagsFin->setChecked((pStream->l4.tcp.flags & TCP_FLAG_FIN) > 0);
}
// L4 | UDP
{
leUdpSrcPort->setText(str.setNum(pStream->l4.udp.srcPort));
leUdpDstPort->setText(str.setNum(pStream->l4.udp.dstPort));
leUdpLength->setText(str.setNum(pStream->l4.udp.totLen));
cbUdpLengthOverride->setChecked((pStream->l4.udp.udpMask & UM_OVERRIDE_TOTLEN) > 0);
leUdpCksum->setText(str.setNum(pStream->l4.udp.cksum));
cbUdpCksumOverride->setChecked((pStream->l4.udp.udpMask & UM_OVERRIDE_CKSUM) > 0);
}
// L4 | ICMP
{
// TODO
}
// L4 | IGMP
{
// TODO
}
}
}
void StreamConfigDialog::StoreCurrentStream()
{
Stream *pStream = &(*mpStreamList)[mCurrentStreamIndex];
QString str;
bool isOk;
qDebug("storing pStream %p", pStream);
// Meta Data
pStream->meta.patternMode = (Stream::DataPatternMode) cmbPatternMode->currentIndex();
pStream->meta.pattern = lePattern->text().remove(QChar(' ')).toULong(&isOk, 16);
pStream->meta.lenMode = (Stream::FrameLengthMode) cmbPktLenMode->currentIndex();
pStream->meta.frameLen = lePktLen->text().toULong(&isOk);
pStream->meta.frameLenMin = lePktLenMin->text().toULong(&isOk);
pStream->meta.frameLenMax = lePktLenMax->text().toULong(&isOk);
// Protocols
{
if (rbFtNone->isChecked())
pStream->proto.ft = Stream::e_ft_none;
else if (rbFtEthernet2->isChecked())
pStream->proto.ft = Stream::e_ft_eth_2;
else if (rbFt802Dot3Raw->isChecked())
pStream->proto.ft = Stream::e_ft_802_3_raw;
else if (rbFt802Dot3Llc->isChecked())
pStream->proto.ft = Stream::e_ft_802_3_llc;
else if (rbFtLlcSnap->isChecked())
pStream->proto.ft = Stream::e_ft_snap;
qDebug("store ft = %d\n", pStream->proto.ft);
pStream->proto.dsap = leDsap->text().remove(QChar(' ')).toULong(&isOk, 16);
pStream->proto.ssap = leSsap->text().remove(QChar(' ')).toULong(&isOk, 16);
pStream->proto.ctl = leControl->text().remove(QChar(' ')).toULong(&isOk, 16);
pStream->proto.ouiMsb = leOui->text().remove(QChar(' ')).toULong(&isOk, 16) >> 16;
pStream->proto.ouiLshw = 0x0000FFFF & leOui->text().remove(QChar(' ')).toULong(&isOk, 16);
pStream->proto.etherType = leType->text().remove(QChar(' ')).toULong(&isOk, 16);
pStream->proto.ipProto = leIpProto->text().remove(QChar(' ')).toULong(&isOk, 16);
// Just check for None/Other - no need to do anything for specific supported protocols
pStream->proto.protoMask = 0;
if (rbL3None->isChecked())
pStream->proto.protoMask |= PM_L3_PROTO_NONE;
else if (rbL3Other->isChecked())
pStream->proto.protoMask |= PM_L3_PROTO_OTHER;
if (rbL4None->isChecked())
pStream->proto.protoMask |= PM_L4_PROTO_NONE;
else if (rbL4Other->isChecked())
pStream->proto.protoMask |= PM_L4_PROTO_OTHER;
}
// L2
{
// L2 | Ethernet
{
pStream->l2.eth.dstMacMshw = leDstMac->text().remove(QChar(' ')).left(4).toULong(&isOk, 16);
pStream->l2.eth.dstMacLsw = leDstMac->text().remove(QChar(' ')).right(8).toULong(&isOk, 16);
pStream->l2.eth.dstMacMode = (Stream::MacAddrMode) cmbDstMacMode->currentIndex();
pStream->l2.eth.dstMacCount = leDstMacCount->text().toULong(&isOk);
pStream->l2.eth.dstMacStep = leDstMacStep->text().toULong(&isOk);
pStream->l2.eth.srcMacMshw = leSrcMac->text().remove(QChar(' ')).left(4).toULong(&isOk, 16);
pStream->l2.eth.srcMacLsw = leSrcMac->text().remove(QChar(' ')).right(8).toULong(&isOk, 16);
pStream->l2.eth.srcMacMode = (Stream::MacAddrMode) cmbSrcMacMode->currentIndex();
pStream->l2.eth.srcMacCount = leSrcMacCount->text().toULong(&isOk);
pStream->l2.eth.srcMacStep = leSrcMacStep->text().toULong(&isOk);
pStream->l2.eth.vlanMask = 0;
pStream->l2.eth.cvlanPrio = cmbCvlanPrio->currentIndex();
pStream->l2.eth.cvlanCfi = cmbCvlanCfi->currentIndex();
pStream->l2.eth.cvlanId = leCvlanId->text().toULong(&isOk);
pStream->l2.eth.ctpid = leCvlanTpid->text().remove(QChar(' ')).toULong(&isOk);
if (cbCvlanTpidOverride->isChecked())
pStream->l2.eth.vlanMask |= VM_CVLAN_TPID_OVERRIDE;
if (gbCvlan->isChecked())
pStream->l2.eth.vlanMask |= VM_CVLAN_TAGGED;
pStream->l2.eth.svlanPrio = cmbSvlanPrio->currentIndex();
pStream->l2.eth.svlanCfi = cmbSvlanCfi->currentIndex();
pStream->l2.eth.svlanId = leSvlanId->text().toULong(&isOk);
pStream->l2.eth.stpid = leSvlanTpid->text().remove(QChar(' ')).toULong(&isOk);
if (cbSvlanTpidOverride->isChecked())
pStream->l2.eth.vlanMask |= VM_SVLAN_TPID_OVERRIDE;
if (gbSvlan->isChecked())
pStream->l2.eth.vlanMask |= VM_SVLAN_TAGGED;
}
}
// L3
{
// L3 | IP
{
pStream->l3.ip.ipMask = 0;
pStream->l3.ip.ver = leIpVersion->text().toULong(&isOk);
if (cbIpVersionOverride->isChecked())
pStream->l3.ip.ipMask |= IM_OVERRIDE_VERSION;
pStream->l3.ip.hdrLen = leIpHdrLen->text().toULong(&isOk);
if (cbIpHdrLenOverride->isChecked())
pStream->l3.ip.ipMask |= IM_OVERRIDE_HDRLEN;
pStream->l3.ip.tos = leIpTos->text().toULong(&isOk, 16);
pStream->l3.ip.totLen = leIpLength->text().toULong(&isOk);
if (cbIpLengthOverride->isChecked())
pStream->l3.ip.ipMask |= IM_OVERRIDE_TOTLEN;
pStream->l3.ip.id = leIpId->text().remove(QChar(' ')).toULong(&isOk, 16);
pStream->l3.ip.fragOfs = leIpFragOfs->text().toULong(&isOk);
if (cbIpFlagsDf->isChecked()) pStream->l3.ip.ipMask |= IP_FLAG_DF;
if (cbIpFlagsMf->isChecked()) pStream->l3.ip.ipMask |= IP_FLAG_MF;
pStream->l3.ip.ttl = leIpTtl->text().toULong(&isOk);
pStream->l3.ip.proto = leIpProto->text().remove(QChar(' ')).toULong(&isOk, 16);
pStream->l3.ip.cksum = leIpCksum->text().remove(QChar(' ')).toULong(&isOk);
if (cbIpCksumOverride->isChecked())
pStream->l3.ip.ipMask |= IM_OVERRIDE_CKSUM;
pStream->l3.ip.srcIp = QHostAddress(leIpSrcAddr->text()).toIPv4Address();
pStream->l3.ip.srcIpMode = (Stream::IpAddrMode) cmbIpSrcAddrMode->currentIndex();
pStream->l3.ip.srcIpCount = leIpSrcAddrCount->text().toULong(&isOk);
pStream->l3.ip.srcIpMask = QHostAddress(leIpSrcAddrMask->text()).toIPv4Address();
pStream->l3.ip.dstIp = QHostAddress(leIpDstAddr->text()).toIPv4Address();
pStream->l3.ip.dstIpMode = (Stream::IpAddrMode) cmbIpDstAddrMode->currentIndex();
pStream->l3.ip.dstIpCount = leIpDstAddrCount->text().toULong(&isOk);
pStream->l3.ip.dstIpMask = QHostAddress(leIpDstAddrMask->text()).toIPv4Address();
}
// L3 | ARP
{
// TODO
}
}
// L4
{
// L4 | TCP
{
pStream->l4.tcp.tcpMask = 0;
pStream->l4.tcp.srcPort = leTcpSrcPort->text().toULong(&isOk);
pStream->l4.tcp.dstPort = leTcpDstPort->text().toULong(&isOk);
pStream->l4.tcp.seqNum = leTcpSeqNum->text().toULong(&isOk);
pStream->l4.tcp.ackNum = leTcpAckNum->text().toULong(&isOk);
pStream->l4.tcp.hdrLen = leTcpHdrLen->text().toULong(&isOk);
if (cbTcpHdrLenOverride->isChecked())
pStream->l4.tcp.tcpMask |= TM_OVERRIDE_HDRLEN;
pStream->l4.tcp.window = leTcpWindow->text().toULong(&isOk);
pStream->l4.tcp.cksum = leTcpCksum->text().remove(QChar(' ')).toULong(&isOk);
if (cbTcpCksumOverride->isChecked())
pStream->l4.tcp.tcpMask |= TM_OVERRIDE_CKSUM;
pStream->l4.tcp.urgPtr = leTcpUrgentPointer->text().toULong(&isOk);
pStream->l4.tcp.flags = 0;
if (cbTcpFlagsUrg->isChecked()) pStream->l4.tcp.flags |= TCP_FLAG_URG;
if (cbTcpFlagsAck->isChecked()) pStream->l4.tcp.flags |= TCP_FLAG_ACK;
if (cbTcpFlagsPsh->isChecked()) pStream->l4.tcp.flags |= TCP_FLAG_PSH;
if (cbTcpFlagsRst->isChecked()) pStream->l4.tcp.flags |= TCP_FLAG_RST;
if (cbTcpFlagsSyn->isChecked()) pStream->l4.tcp.flags |= TCP_FLAG_SYN;
if (cbTcpFlagsFin->isChecked()) pStream->l4.tcp.flags |= TCP_FLAG_FIN;
}
// L4 | UDP
{
pStream->l4.udp.udpMask = 0;
pStream->l4.udp.srcPort = leUdpSrcPort->text().toULong(&isOk);
pStream->l4.udp.dstPort = leUdpDstPort->text().toULong(&isOk);
pStream->l4.udp.totLen = leUdpLength->text().toULong(&isOk);
if (cbUdpLengthOverride->isChecked()) pStream->l4.udp.udpMask |= UM_OVERRIDE_TOTLEN;
pStream->l4.udp.cksum = leUdpCksum->text().remove(QChar(' ')).toULong(&isOk);
if (cbUdpCksumOverride->isChecked()) pStream->l4.udp.udpMask |= UM_OVERRIDE_CKSUM;
}
// L4 | ICMP
{
// TODO
}
// L4 | IGMP
{
// TODO
}
}
}
void StreamConfigDialog::on_pbOk_clicked()
{
// Store dialog contents into stream
StoreCurrentStream();
qDebug("stream stored");
}
//Junk Line for introducing a compiler error

View File

@ -0,0 +1,58 @@
#ifndef _STREAM_CONFIG_DIALOG_H
#define _STREAM_CONFIG_DIALOG_H
#include <QDialog>
#include "ui_streamconfigdialog.h"
#include <stream.h>
#define MAX_MAC_ITER_COUNT 256
#define MIN_PKT_LEN 64
#define MAX_PKT_LEN 1522
/*
** TODO
** - Improve HexStr handling
**
*/
class StreamConfigDialog : public QDialog, public Ui::StreamConfigDialog
{
Q_OBJECT
public:
StreamConfigDialog(QList<Stream> *streamList, uint streamIndex,
QWidget *parent = 0);
~StreamConfigDialog();
private:
QList<Stream> *mpStreamList;
uint mCurrentStreamIndex;
void setupUiExtra();
void LoadCurrentStream();
void StoreCurrentStream();
private slots:
void on_cmbDstMacMode_currentIndexChanged(QString mode);
void on_pbPrev_clicked();
void on_pbNext_clicked();
void on_rbFtLlcSnap_toggled(bool checked);
void on_rbL3Ipv4_toggled(bool checked);
void on_rbL3Arp_toggled(bool checked);
void on_rbL4Icmp_toggled(bool checked);
void on_rbL4Igmp_toggled(bool checked);
void on_rbL4Tcp_toggled(bool checked);
void on_rbL4Udp_toggled(bool checked);
void on_rbL4Other_toggled(bool checked);
void update_NumPacketsAndNumBursts();
void on_pbOk_clicked();
};
QString & uintToHexStr(quint32 num, QString &hexStr, quint8 octets);
#endif

3224
client/streamconfigdialog.ui Normal file

File diff suppressed because it is too large Load Diff

119
client/streamlistmodel.cpp Normal file
View File

@ -0,0 +1,119 @@
#include "streamlistmodel.h"
StreamListModel::StreamListModel(QObject *parent)
: QAbstractTableModel(parent)
{
uint i;
// Enable all streams by default
for (i=0; i<MAX_ROWS; i++)
{
streamList[i].isEnabled = true;
}
}
int StreamListModel::rowCount(const QModelIndex &parent) const
{
return MAX_ROWS; // FIXME
}
int StreamListModel::columnCount(const QModelIndex &parent ) const
{
return MAX_COLS; // FIXME
}
Qt::ItemFlags StreamListModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags flags = QAbstractTableModel::flags(index);
if (index.column() == 0)
;
else if (index.column() == 1)
flags |= Qt::ItemIsEditable;
else if (index.column() == 2)
flags |= Qt::ItemIsUserCheckable | Qt::ItemIsEditable;
return flags;
}
QVariant StreamListModel::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() >= MAX_ROWS)
return QVariant();
if (index.column() >= MAX_COLS)
return QVariant();
// Check role
if (index.column() == 0) // Icon
{
if ((role == Qt::DisplayRole))
return QString("EDIT");
else
return QVariant();
}
else if (index.column() == 1) // Name
{
if ((role == Qt::DisplayRole) || (role == Qt::EditRole))
return streamList[index.row()].streamName;
else
return QVariant();
}
else if (index.column() == 2) // Enabled?
{
//if ((role == Qt::CheckStateRole) || (role == Qt::EditRole))
// return streamList[index.row()].isEnabled ? Qt::Checked : Qt::Unchecked;
if ((role == Qt::DisplayRole) || (role == Qt::EditRole))
return streamList[index.row()].isEnabled;
else
return QVariant();
}
}
bool StreamListModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (index.isValid() && role == Qt::EditRole)
{
if (index.column() == 1) // Name
streamList[index.row()].streamName = value.toString();
else if (index.column() == 2) // Enabled?
streamList[index.row()].isEnabled = value.toBool();
else
return false;
return true;
}
return false;
}
QVariant StreamListModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role != Qt::DisplayRole)
return QVariant();
if (orientation == Qt::Horizontal)
return StreamListCols.at(section);
else
return QString("%1").arg(section+1);
}
#if 0
// QModelIndex StreamListModel::index (int portNum, PortStat stat, const QModelIndex & parent = QModelIndex() ) const
void StreamListModel::on_portStatsUpdate(int port, void*stats)
{
int i;
QModelIndex topLeft = index(port, 0, QModelIndex());
QModelIndex bottomRight = index(port, e_STAT_MAX, QModelIndex());
for (i = 0; i < e_STAT_MAX; i++)
dummyStats[port][i] = ((int *)stats)[i];
emit dataChanged(topLeft, bottomRight);
}
#endif

46
client/streamlistmodel.h Normal file
View File

@ -0,0 +1,46 @@
#ifndef _STREAM_LIST_MODEL_H
#define _STREAM_LIST_MODEL_H
#include <QAbstractTableModel>
#include <QStringList>
static QStringList StreamListCols = (QStringList()
<< "Icon"
<< "Name"
<< "Enable"
);
#define MAX_ROWS 5
#define MAX_COLS 3
class StreamListModel : public QAbstractTableModel
{
Q_OBJECT
public:
//StreamListModel(QObject *parent = 0) : QAbstractTableModel(parent) {}
StreamListModel(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;
// QModelIndex index (int portNum, PortStat stat, const QModelIndex & parent = QModelIndex() ) const;
public slots:
// void on_portStatsUpdate(int port, void*stats);
private:
// FIXME: temp
//#define NUM_PORTS 2
// int dummyStats[NUM_PORTS][e_STAT_MAX];
struct {
QString streamName;
bool isEnabled;
} streamList[MAX_ROWS];
};
#endif

218
client/streammodel.cpp Normal file
View File

@ -0,0 +1,218 @@
#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->mStreams.size();
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 | Qt::ItemIsEditable;
break;
default:
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->mStreams.size())
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");
#if 0
else if ((role == Qt::DisplayRole))
return QString("EDIT");
#endif
else
return QVariant();
break;
}
case StreamName:
{
if ((role == Qt::DisplayRole) || (role == Qt::EditRole))
return mCurrentPort->mStreams[index.row()].name();
else
return QVariant();
break;
}
case StreamStatus:
{
#if 0
if ((role == Qt::DisplayRole) || (role == Qt::EditRole))
return streamList[index.row()].isEnabled;
if ((role == Qt::DisplayRole) || (role == Qt::CheckStateRole) ||
#endif
if ((role == Qt::CheckStateRole) || (role == Qt::EditRole))
{
if (mCurrentPort->mStreams[index.row()].isEnabled())
return Qt::Checked;
else
return Qt::Unchecked;
}
else
return QVariant();
break;
}
default:
qDebug("-------------UNHANDLED STREAM FIELD----------------");
}
return QVariant();
}
bool StreamModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (mCurrentPort == NULL)
return false;
if (index.isValid() && role == Qt::EditRole)
{
// Edit Supported Fields
switch (index.column())
{
case StreamName:
mCurrentPort->mStreams[index.row()].setName(value.toString());
return true;
break;
case StreamStatus:
mCurrentPort->mStreams[index.row()].setEnabled(value.toBool());
return true;
break;
// Edit Not Supported Fields
case StreamIcon:
return false;
break;
// 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("Icon");
break;
case StreamName:
return QString("Name");
break;
case StreamStatus:
return QString("Enabled");
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->mStreams.insert(row, Stream());
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++)
{
// FIXME(HIGH): do we need to free the removed stream?
mCurrentPort->mStreams.removeAt(row);
}
endRemoveRows();
return true;
}
// --------------------- SLOTS ------------------------
void StreamModel::setCurrentPortIndex(const QModelIndex &current)
{
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();
}

49
client/streammodel.h Normal file
View File

@ -0,0 +1,49 @@
#ifndef _STREAM_MODEL_H
#define _STREAM_MODEL_H
#include <QAbstractTableModel>
#include "port.h"
class PortGroupList;
class StreamModel : public QAbstractTableModel
{
Q_OBJECT
enum StreamFields {
StreamIcon = 0,
StreamName,
StreamStatus,
StreamMaxFields
};
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());
// FIXME(HIGH): This *is* like a kludge
QList<Stream>* currentPortStreamList()
{ return &mCurrentPort->mStreams; }
public slots:
void setCurrentPortIndex(const QModelIndex &current);
};
#endif

53
common/protocol.h Normal file
View File

@ -0,0 +1,53 @@
#ifndef _PROTOCOL_H
#define _PROTOCOL_H
#define UINT8 unsigned char
#define UINT16 unsigned short
#define UINT32 unsigned int
#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: portability
#define HTONL(x) BYTESWAP4(x)
#define NTOHL(x) BYTESWAP4(x)
#define HTONS(x) BYTESWAP2(x)
#define NTOHS(x) BYTESWAP2(x)
typedef struct {
UINT8 ver;
UINT8 resv1;
UINT16 resv2;
UINT16 msgType;
UINT16 msgLen;
} tCommHdr;
typedef enum {
e_MT_CapabilityReq=1,
e_MT_CapabilityInfo
} eMsgType;
typedef enum {
e_TT_PortCapability
} eTlvType;
typedef struct {
UINT16 tlvType;
UINT16 tlvLen;
UINT32 port;
UINT32 speed;
#define TLV_MAX_PORT_NAME 64
#define TLV_MAX_PORT_DESC 64
char name[TLV_MAX_PORT_NAME];
char desc[TLV_MAX_PORT_DESC];
} tTlvPortCapability;
#endif

12
server/abstracthost.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef _ABSTRACT_HOST
#define _ABSTRACT_HOST
class AbstractHost
{
public:
virtual void Log(const char* str) = 0;
virtual int SendMsg(const void* msg, int size) = 0;
};
#endif

85
server/drone.cpp Normal file
View File

@ -0,0 +1,85 @@
#include "drone.h"
extern int myport; // FIXME(HIGH)
Drone::Drone(QDialog *parent)
: QDialog(parent)
{
ui.setupUi(this);
serverPortNum = DRONE_PORT;
clientSock = NULL;
if (myport)
serverPortNum = myport;
rxtx = new RxTx(this);
server = new QTcpServer(this);
connect(server, SIGNAL(newConnection()), this, SLOT(when_newConnection()));
//if (!server->listen(QHostAddress("10.0.0.1"), serverPortNum))
if (!server->listen(QHostAddress::Any, serverPortNum))
LogInt(tr("Unable to start the server: %1").arg(server->errorString()));
else
LogInt(tr("The server is running on %1:%2").arg(server->serverAddress().toString()).arg(server->serverPort()));
}
void Drone::Log(const char* str)
{
ui.teLog->append(QString(str));
}
int Drone::SendMsg(const void* msg, int size)
{
qDebug("Inside SendMsg\n");
clientSock->write((char*) msg, size);
}
void Drone::LogInt(const QString &str)
{
ui.teLog->append(str);
}
void Drone::when_newConnection()
{
if (clientSock)
{
QTcpSocket *sock;
LogInt(tr("already connected, no new connections will be accepted\n"));
sock = server->nextPendingConnection();
// TODO: Send reason msg to client
sock->disconnectFromHost();
goto _exit;
}
clientSock = server->nextPendingConnection();
LogInt(tr("accepting new connection from %1:%2").arg(clientSock->peerAddress().toString()).arg(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 Drone::when_disconnected()
{
LogInt(tr("closing connection from %1:%2").arg(clientSock->peerAddress().toString()).arg(clientSock->peerPort()));
clientSock->deleteLater();
clientSock = NULL;
}
void Drone::when_dataAvail()
{
QByteArray msg = clientSock->read(1024); // FIXME: hardcoding
LogInt(QString(msg.toHex()));
rxtx->ProcessMsg(msg.constData(), msg.size());
}
void Drone::when_error(QAbstractSocket::SocketError socketError)
{
LogInt(clientSock->errorString());
}

36
server/drone.h Normal file
View File

@ -0,0 +1,36 @@
#ifndef _DRONE_H
#define _DRONE_H
#include <QTcpServer>
#include <QTcpSocket>
#include "ui_drone.h"
#include "abstracthost.h"
#include "rxtx.h"
class Drone : public QDialog, AbstractHost
{
Q_OBJECT
public:
Drone(QDialog *parent = 0);
void Log(const char *msg);
int SendMsg(const void* msg, int msgLen);
Ui::Drone ui;
private:
RxTx *rxtx;
QTcpServer *server;
QTcpSocket *clientSock;
#define DRONE_PORT 7878
quint16 serverPortNum;
// Ui::Drone ui;
void LogInt(const QString &msg);
private slots:
void when_newConnection();
void when_disconnected();
void when_dataAvail();
void when_error(QAbstractSocket::SocketError socketError);
};
#endif

9
server/drone.pro Normal file
View File

@ -0,0 +1,9 @@
TEMPLATE = app
CONFIG += qt
QT += network
DEFINES += HAVE_REMOTE
INCLUDEPATH += "C:\DevelLibs\WpdPack\Include"
LIBS += -L"C:\DevelLibs\WpdPack\Lib" -lwpcap
HEADERS += drone.h
FORMS += drone.ui
SOURCES += drone_main.cpp drone.cpp rxtx.cpp

126
server/drone.ui Normal file
View File

@ -0,0 +1,126 @@
<ui version="4.0" >
<class>Drone</class>
<widget class="QDialog" name="Drone" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle" >
<string>Drone</string>
</property>
<layout class="QVBoxLayout" >
<item>
<widget class="QTabWidget" name="twDisplay" >
<property name="currentIndex" >
<number>1</number>
</property>
<widget class="QWidget" name="tabStatus" >
<attribute name="title" >
<string>Status</string>
</attribute>
<widget class="QLabel" name="label" >
<property name="geometry" >
<rect>
<x>160</x>
<y>100</y>
<width>46</width>
<height>14</height>
</rect>
</property>
<property name="text" >
<string>TODO</string>
</property>
</widget>
</widget>
<widget class="QWidget" name="tabLog" >
<attribute name="title" >
<string>Log</string>
</attribute>
<layout class="QHBoxLayout" >
<item>
<widget class="QTextEdit" name="teLog" >
<property name="readOnly" >
<bool>true</bool>
</property>
<property name="acceptRichText" >
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<layout class="QHBoxLayout" >
<item>
<widget class="QPushButton" name="pbClearLog" >
<property name="text" >
<string>Clear Log</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushButton" >
<property name="text" >
<string>Exit</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>pushButton</sender>
<signal>clicked(bool)</signal>
<receiver>Drone</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel" >
<x>341</x>
<y>279</y>
</hint>
<hint type="destinationlabel" >
<x>226</x>
<y>268</y>
</hint>
</hints>
</connection>
<connection>
<sender>pbClearLog</sender>
<signal>clicked()</signal>
<receiver>teLog</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel" >
<x>52</x>
<y>278</y>
</hint>
<hint type="destinationlabel" >
<x>100</x>
<y>185</y>
</hint>
</hints>
</connection>
</connections>
</ui>

22
server/drone_main.cpp Normal file
View File

@ -0,0 +1,22 @@
#include "drone.h"
Drone *drone;
//void FindDevList(void);
int myport;
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// FIXME(HIGH)
if (argc > 1)
myport = atoi(argv[1]);
drone = new Drone;
//FindDevList();
drone->show();
return app.exec();
}

147
server/rxtx.cpp Normal file
View File

@ -0,0 +1,147 @@
#include "rxtx.h"
#include "../common/protocol.h"
#include "qtglobal" // FIXME: needed only for qdebug
//#define LOG(...) drone->ui.teLOG->append(QString().sprintf( __VA_ARGS__))
//#define LOG(...) drone->LOG(QString().sprintf( __VA_ARGS__))
#define LOG(...) {sprintf(logStr, __VA_ARGS__); host->Log(logStr);}
RxTx::RxTx(AbstractHost *host)
{
pcap_if_t *d;
int i=0;
char errbuf[PCAP_ERRBUF_SIZE];
// Init Data
RxTx::host = host;
numPorts = 0;
alldevs = NULL;
LOG("Retrieving the device list from the local machine\n");
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
{
LOG("Error in pcap_findalldevs_ex: %s\n", errbuf);
goto _fail;
}
/* Count number of local ports */
for(d = alldevs; d != NULL; d = d->next)
numPorts++;
portInfo = new PortInfo[numPorts];
/* Print the list */
for(i=0, d=alldevs; d!=NULL; i++, d=d->next)
{
portInfo[i].portId = i;
portInfo[i].dev = d;
#if 1
LOG("%d. %s", i, d->name);
if (d->description)
{
LOG(" (%s)\n", d->description);
}
else
LOG(" (No description available)\n");
#endif
}
if (i == 0)
{
LOG("\nNo interfaces found! Make sure WinPcap is installed.\n");
goto _fail;
}
_fail:
return;
}
#if 0
RxTx::LOG(char* fmt, ...)
{
sprintf(logStr, fmt, _VA_ARGS_);
host->LOG(logStr);
}
#endif
RxTx::~RxTx()
{
pcap_freealldevs(alldevs);
}
void RxTx::ProcessMsg(const char* msg, int len)
{
tCommHdr *hdr;
// TODO: For now, assuming we'll get a complete msg
// but need to fix this as this is a TCP stream
hdr = (tCommHdr*) msg;
if (hdr->ver != 1) // FIXME:hardcoding
{
LOG("Rcvd msg with invalid version %d\n", hdr->ver);
goto _exit;
}
qDebug("msgType - %x: %x\n", hdr->msgType, NTOHS(hdr->msgType));
switch (NTOHS(hdr->msgType))
{
case e_MT_CapabilityReq:
SendCapabilityInfo();
break;
default:
LOG("Rcvd msg with unrecognized msgType %d\n", NTOHS(hdr->msgType));
}
_exit:
return;
}
void RxTx::SendCapabilityInfo(void)
{
unsigned char *msg, *p;
unsigned int i, msgLen;
p = msg = (unsigned char*) pktBuff;
((tCommHdr*)(p))->ver = 1;
((tCommHdr*)(p))->msgType = HTONS(e_MT_CapabilityInfo);
p += sizeof(tCommHdr);
for (i = 0; i < numPorts; i++)
{
// TLV: Port Capability
((tTlvPortCapability*)(p))->tlvType = HTONS(e_TT_PortCapability);
((tTlvPortCapability*)(p))->tlvLen = HTONS(sizeof(tTlvPortCapability));
((tTlvPortCapability*)(p))->port = HTONL(portInfo[i].portId);
((tTlvPortCapability*)(p))->speed = 0; // TODO
#if 0
strncpy(((tTlvPortCapability*)(p))->name,
portInfo[i].dev->name, TLV_MAX_PORT_NAME);
((tTlvPortCapability*)(p))->name[TLV_MAX_PORT_NAME-1] = 0;
#else
strcpy(((tTlvPortCapability*)(p))->name, "eth");
//strcat(((tTlvPortCapability*)(p))->name, itoa(portInfo[i].portId, NULL, 10));
itoa(portInfo[i].portId, &(((tTlvPortCapability*)(p))->name[3]), 10);
#endif
strncpy(((tTlvPortCapability*)(p))->desc,
portInfo[i].dev->description, TLV_MAX_PORT_DESC);
((tTlvPortCapability*)(p))->desc[TLV_MAX_PORT_DESC -1] = 0;
p += sizeof(tTlvPortCapability);
}
msgLen = (p - msg);
((tCommHdr*)(msg))->msgLen = HTONS(msgLen);
logStr[0] = 0;
for (i = 0; i < msgLen >> 2; i++)
{
char word[10];
sprintf(word, "%08X ", HTONL(((unsigned int *)(msg))[i]));
strcat(logStr, word);
}
host->Log("Sending msg\n");
host->Log(logStr);
host->SendMsg(pktBuff, msgLen);
}

35
server/rxtx.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef _RXTX_H
#define _RXTX_H
#include "pcap.h"
#include "abstracthost.h"
typedef struct
{
unsigned int portId;
pcap_if_t *dev;
} PortInfo;
class RxTx
{
public:
RxTx(AbstractHost* host);
~RxTx();
void ProcessMsg(const char* msg, int len);
private:
AbstractHost *host;
char logStr[1024];
#define MAX_PKT_SIZE 1024
unsigned char pktBuff[MAX_PKT_SIZE];
unsigned numPorts;
PortInfo *portInfo;
pcap_if_t *alldevs;
//void Log(char *fmt, ...);
void SendCapabilityInfo(void);
};
#endif