Implemented "exclusive control" for a port using bindconfig (Win32 only). Following changes done for the same -
- OstProto service has a new method "modifyPort()" - At port init port.isExclusive is now set using a bindconfig query (Win32 only) - AbstractPort interface has 2 new pure virtual methods - hasExclusiveControl() and setExclusiveControl() - PcapPort does not support this functionality (yet) so these methods return false - WinPcapPort suppots this new functionality using bindconfig - Port's notes (specifying Rx/Tx limitations) are now set and updated based on hasExclusiveControl() - Presence of 'notes' on a port is indicated using a '*' after the port name in the port stats window - The tabwidget has been removed from Port Window | Stream View Pane - Ostinato Client has a new action in the port window's context menu for the same - Port Icon in the Port Window is decorated based on exclusive control
This commit is contained in:
parent
70ca42fbb3
commit
b28bcd3055
BIN
client/icons/deco_exclusive.png
Normal file
BIN
client/icons/deco_exclusive.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 793 B |
@ -12,6 +12,7 @@
|
||||
<file>icons/bullet_yellow.png</file>
|
||||
<file>icons/control_play.png</file>
|
||||
<file>icons/control_stop.png</file>
|
||||
<file>icons/deco_exclusive.png</file>
|
||||
<file>icons/delete.png</file>
|
||||
<file>icons/magnifier.png</file>
|
||||
<file>icons/portgroup_add.png</file>
|
||||
|
@ -22,6 +22,7 @@ Port::Port(quint32 id, quint32 portGroupId)
|
||||
|
||||
Port::~Port()
|
||||
{
|
||||
qDebug("%s", __FUNCTION__);
|
||||
while (!mStreams.isEmpty())
|
||||
delete mStreams.takeFirst();
|
||||
}
|
||||
|
@ -31,7 +31,6 @@ class Port : public QObject {
|
||||
|
||||
public:
|
||||
enum AdminStatus { AdminDisable, AdminEnable };
|
||||
enum ControlMode { ControlShared, ControlExclusive };
|
||||
|
||||
// FIXME(HIGH): default args is a hack for QList operations on Port
|
||||
Port(quint32 id = 0xFFFFFFFF, quint32 pgId = 0xFFFFFFFF);
|
||||
@ -50,8 +49,8 @@ public:
|
||||
{ return QString().fromStdString(d.notes()); }
|
||||
AdminStatus adminStatus()
|
||||
{ return (d.is_enabled()?AdminEnable:AdminDisable); }
|
||||
ControlMode controlMode()
|
||||
{ return (d.is_exclusive_control()?ControlExclusive:ControlShared); }
|
||||
bool hasExclusiveControl()
|
||||
{ return d.is_exclusive_control(); }
|
||||
|
||||
//void setAdminEnable(AdminStatus status) { mAdminStatus = status; }
|
||||
void setAlias(QString &alias) { mUserAlias = alias; }
|
||||
|
@ -32,7 +32,7 @@ PortGroup::PortGroup(QHostAddress ip, quint16 port)
|
||||
// FIXME(LOW):Can't for my life figure out why this ain't working!
|
||||
//QMetaObject::connectSlotsByName(this);
|
||||
connect(rpcChannel, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
|
||||
this, SLOT(on_rpcChannel_stateChanged()));
|
||||
this, SLOT(on_rpcChannel_stateChanged(QAbstractSocket::SocketState)));
|
||||
connect(rpcChannel, SIGNAL(connected()),
|
||||
this, SLOT(on_rpcChannel_connected()));
|
||||
connect(rpcChannel, SIGNAL(disconnected()),
|
||||
@ -56,9 +56,9 @@ PortGroup::~PortGroup()
|
||||
// ------------------------------------------------
|
||||
// Slots
|
||||
// ------------------------------------------------
|
||||
void PortGroup::on_rpcChannel_stateChanged()
|
||||
void PortGroup::on_rpcChannel_stateChanged(QAbstractSocket::SocketState state)
|
||||
{
|
||||
qDebug("state changed");
|
||||
qDebug("state changed %d", state);
|
||||
emit portGroupDataChanged(mPortGroupId);
|
||||
}
|
||||
|
||||
@ -275,6 +275,80 @@ _error_exit:
|
||||
delete portConfigList;
|
||||
}
|
||||
|
||||
void PortGroup::modifyPort(int portIndex, bool isExclusive)
|
||||
{
|
||||
OstProto::PortConfigList portConfigList;
|
||||
OstProto::Port *port;
|
||||
OstProto::Ack *ack;
|
||||
|
||||
qDebug("%s: portIndex = %d", __FUNCTION__, portIndex);
|
||||
|
||||
Q_ASSERT(portIndex < mPorts.size());
|
||||
|
||||
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
|
||||
mainWindow->setDisabled(true);
|
||||
|
||||
port = portConfigList.add_port();
|
||||
port->mutable_port_id()->set_id(mPorts[portIndex]->id());
|
||||
port->set_is_exclusive_control(isExclusive);
|
||||
|
||||
ack = new OstProto::Ack;
|
||||
rpcController->Reset();
|
||||
serviceStub->modifyPort(rpcController, &portConfigList, ack,
|
||||
NewCallback(this, &PortGroup::processModifyPortAck, portIndex, ack));
|
||||
}
|
||||
|
||||
void PortGroup::processModifyPortAck(int portIndex, OstProto::Ack *ack)
|
||||
{
|
||||
OstProto::PortIdList portIdList;
|
||||
OstProto::PortId *portId;
|
||||
OstProto::PortConfigList *portConfigList;
|
||||
|
||||
qDebug("In %s", __FUNCTION__);
|
||||
|
||||
portId = portIdList.add_port_id();
|
||||
portId->set_id(mPorts[portIndex]->id());
|
||||
|
||||
portConfigList = new OstProto::PortConfigList;
|
||||
|
||||
rpcController->Reset();
|
||||
serviceStub->getPortConfig(rpcController, &portIdList, portConfigList,
|
||||
NewCallback(this, &PortGroup::processUpdatedPortConfig,
|
||||
portConfigList));
|
||||
|
||||
delete ack;
|
||||
}
|
||||
|
||||
void PortGroup::processUpdatedPortConfig(OstProto::PortConfigList *portConfigList)
|
||||
{
|
||||
qDebug("In %s", __FUNCTION__);
|
||||
|
||||
if (rpcController->Failed())
|
||||
{
|
||||
qDebug("%s: rpc failed", __FUNCTION__);
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
if (portConfigList->port_size() != 1)
|
||||
qDebug("port size = %d (expected = 1)", portConfigList->port_size());
|
||||
|
||||
for(int i = 0; i < portConfigList->port_size(); i++)
|
||||
{
|
||||
uint id;
|
||||
|
||||
id = portConfigList->port(i).port_id().id();
|
||||
// FIXME: don't mix port id & index into mPorts[]
|
||||
mPorts[id]->updatePortConfig(portConfigList->mutable_port(i));
|
||||
}
|
||||
|
||||
emit portGroupDataChanged(mPortGroupId);
|
||||
|
||||
_exit:
|
||||
mainWindow->setEnabled(true);
|
||||
QApplication::restoreOverrideCursor();
|
||||
delete portConfigList;
|
||||
}
|
||||
|
||||
void PortGroup::getStreamIdList(int portIndex,
|
||||
OstProto::StreamIdList *streamIdList)
|
||||
{
|
||||
|
@ -23,21 +23,19 @@ class PortGroup : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
quint32 mPortGroupId;
|
||||
static quint32 mPortGroupAllocId;
|
||||
QString mUserAlias; // user defined
|
||||
#if 0 // PB
|
||||
QTcpSocket *mpSocket;
|
||||
QHostAddress mServerAddress;
|
||||
quint16 mServerPort;
|
||||
#endif
|
||||
PbRpcChannel *rpcChannel;
|
||||
PbRpcController *rpcController;
|
||||
PbRpcController *rpcControllerStats;
|
||||
bool isGetStatsPending_;
|
||||
::OstProto::OstService::Stub *serviceStub;
|
||||
static quint32 mPortGroupAllocId;
|
||||
quint32 mPortGroupId;
|
||||
QString mUserAlias; // user defined
|
||||
|
||||
PbRpcChannel *rpcChannel;
|
||||
PbRpcController *rpcController;
|
||||
PbRpcController *rpcControllerStats;
|
||||
bool isGetStatsPending_;
|
||||
|
||||
::OstProto::OstService::Stub *serviceStub;
|
||||
|
||||
::OstProto::PortIdList portIdList;
|
||||
|
||||
::OstProto::PortIdList portIdList;
|
||||
public: // FIXME(HIGH): member access
|
||||
QList<Port*> mPorts;
|
||||
|
||||
@ -67,6 +65,10 @@ public:
|
||||
void processPortIdList(OstProto::PortIdList *portIdList);
|
||||
void processPortConfigList(OstProto::PortConfigList *portConfigList);
|
||||
|
||||
void modifyPort(int portId, bool isExclusive);
|
||||
void processModifyPortAck(int portIndex, OstProto::Ack *ack);
|
||||
void processUpdatedPortConfig(OstProto::PortConfigList *portConfigList);
|
||||
|
||||
void getStreamIdList(int portIndex = 0,
|
||||
OstProto::StreamIdList *streamIdList = NULL);
|
||||
void getStreamConfigList(int portIndex = 0,
|
||||
@ -98,7 +100,7 @@ signals:
|
||||
void statsChanged(quint32 portGroupId);
|
||||
|
||||
private slots:
|
||||
void on_rpcChannel_stateChanged();
|
||||
void on_rpcChannel_stateChanged(QAbstractSocket::SocketState state);
|
||||
void on_rpcChannel_connected();
|
||||
void on_rpcChannel_disconnected();
|
||||
void on_rpcChannel_error(QAbstractSocket::SocketError socketError);
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include "portmodel.h"
|
||||
#include "portgrouplist.h"
|
||||
|
||||
#include <QIcon>
|
||||
#include <QPainter>
|
||||
|
||||
#if 0
|
||||
#define DBG0(x) qDebug(x)
|
||||
@ -14,6 +16,23 @@ PortModel::PortModel(PortGroupList *p, QObject *parent)
|
||||
: QAbstractItemModel(parent)
|
||||
{
|
||||
pgl = p;
|
||||
|
||||
portIconFactory[OstProto::LinkStateUnknown][false] =
|
||||
QIcon(":/icons/bullet_white.png");
|
||||
portIconFactory[OstProto::LinkStateDown][false] =
|
||||
QIcon(":/icons/bullet_red.png");
|
||||
portIconFactory[OstProto::LinkStateUp][false] =
|
||||
QIcon(":/icons/bullet_green.png");
|
||||
|
||||
for (int linkState = 0; linkState < kLinkStatesCount; linkState++)
|
||||
{
|
||||
QPixmap pixmap(":/icons/deco_exclusive.png");
|
||||
QPainter painter(&pixmap);
|
||||
QIcon icon = portIconFactory[linkState][false];
|
||||
|
||||
painter.drawPixmap(0, 0, icon.pixmap(QSize(32,32)));
|
||||
portIconFactory[linkState][true] = QIcon(pixmap);
|
||||
}
|
||||
}
|
||||
|
||||
int PortModel::rowCount(const QModelIndex &parent) const
|
||||
@ -123,38 +142,27 @@ QVariant PortModel::data(const QModelIndex &index, int role) const
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pgl->mPortGroups.at(parent.row())->numPorts() == 0)
|
||||
{
|
||||
DBG0("Exit PortModel data 4\n");
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
Port *port = pgl->mPortGroups.at(parent.row())->mPorts[index.row()];
|
||||
|
||||
// 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());
|
||||
// FIXME(LOW) - IP Address below
|
||||
return QString("Port %1: %2 [%3] (%4)")
|
||||
.arg(port->id())
|
||||
.arg(port->name())
|
||||
.arg(QHostAddress("0.0.0.0").toString())
|
||||
.arg(port->description());
|
||||
}
|
||||
else if ((role == Qt::DecorationRole))
|
||||
{
|
||||
DBG0("Exit PortModel data 5\n");
|
||||
if (pgl->mPortGroups.at(parent.row())->numPorts() == 0)
|
||||
return QVariant();
|
||||
switch(pgl->mPortGroups.at(parent.row())->mPorts[index.row()]->linkState())
|
||||
{
|
||||
case OstProto::LinkStateUnknown:
|
||||
return QIcon(":/icons/bullet_white.png");
|
||||
case OstProto::LinkStateDown:
|
||||
return QIcon(":/icons/bullet_red.png");
|
||||
case OstProto::LinkStateUp:
|
||||
return QIcon(":/icons/bullet_green.png");
|
||||
default:
|
||||
qFatal("unexpected/unimplemented port oper state");
|
||||
}
|
||||
return portIconFactory[port->linkState()][port->hasExclusiveControl()];
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -235,7 +243,7 @@ QModelIndex PortModel::parent(const QModelIndex &index) const
|
||||
|
||||
bool PortModel::isPortGroup(const QModelIndex& index)
|
||||
{
|
||||
if ((index.internalId() & 0xFFFF) == 0xFFFF)
|
||||
if (index.isValid() && ((index.internalId() & 0xFFFF) == 0xFFFF))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
@ -243,7 +251,7 @@ bool PortModel::isPortGroup(const QModelIndex& index)
|
||||
|
||||
bool PortModel::isPort(const QModelIndex& index)
|
||||
{
|
||||
if ((index.internalId() & 0xFFFF) != 0xFFFF)
|
||||
if (index.isValid() && ((index.internalId() & 0xFFFF) != 0xFFFF))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define _PORT_MODEL_H
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QIcon>
|
||||
|
||||
class PortGroupList;
|
||||
class PortGroup;
|
||||
@ -12,24 +13,29 @@ class PortModel : public QAbstractItemModel
|
||||
|
||||
friend class PortGroupList;
|
||||
|
||||
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:
|
||||
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);
|
||||
|
||||
static const int kLinkStatesCount = 3;
|
||||
static const int kExclusiveStatesCount = 2;
|
||||
QIcon portIconFactory[kLinkStatesCount][kExclusiveStatesCount];
|
||||
|
||||
private slots:
|
||||
void when_portGroupDataChanged(int portGroupId, int portId);
|
||||
@ -45,7 +51,6 @@ private slots:
|
||||
void triggerLayoutAboutToBeChanged();
|
||||
void triggerLayoutChanged();
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -193,9 +193,18 @@ QVariant PortStatsModel::headerData(int section, Qt::Orientation orientation, in
|
||||
if (orientation == Qt::Horizontal)
|
||||
{
|
||||
uint portGroupIdx, portIdx;
|
||||
QString portName;
|
||||
|
||||
getDomainIndexes(index(0, section), portGroupIdx, portIdx);
|
||||
return QString("Port %1-%2").arg(portGroupIdx).arg(portIdx);
|
||||
portName = QString("Port %1-%2").arg(portGroupIdx).arg(portIdx);
|
||||
if (portGroupIdx < (uint) pgl->mPortGroups.size()
|
||||
&& portIdx < (uint) pgl->mPortGroups.at(portGroupIdx)->mPorts.size())
|
||||
{
|
||||
if (!pgl->mPortGroups.at(portGroupIdx)->mPorts[portIdx]->notes()
|
||||
.isEmpty())
|
||||
portName += " *";
|
||||
}
|
||||
return portName;
|
||||
}
|
||||
else
|
||||
return PortStatName.at(section);
|
||||
|
@ -16,6 +16,8 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
|
||||
|
||||
setupUi(this);
|
||||
|
||||
tvPortList->header()->hide();
|
||||
|
||||
tvStreamList->setItemDelegate(delegate);
|
||||
|
||||
tvStreamList->verticalHeader()->setDefaultSectionSize(
|
||||
@ -27,6 +29,8 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
|
||||
tvPortList->addAction(actionConnect_Port_Group);
|
||||
tvPortList->addAction(actionDisconnect_Port_Group);
|
||||
|
||||
tvPortList->addAction(actionExclusive_Control);
|
||||
|
||||
tvStreamList->addAction(actionNew_Stream);
|
||||
tvStreamList->addAction(actionEdit_Stream);
|
||||
tvStreamList->addAction(actionDelete_Stream);
|
||||
@ -210,6 +214,8 @@ void PortsWindow::updatePortViewActions(const QModelIndex& current)
|
||||
actionDelete_Port_Group->setDisabled(true);
|
||||
actionConnect_Port_Group->setDisabled(true);
|
||||
actionDisconnect_Port_Group->setDisabled(true);
|
||||
|
||||
actionExclusive_Control->setDisabled(true);
|
||||
|
||||
goto _EXIT;
|
||||
}
|
||||
@ -219,6 +225,9 @@ void PortsWindow::updatePortViewActions(const QModelIndex& current)
|
||||
if (plm->isPortGroup(current))
|
||||
{
|
||||
actionDelete_Port_Group->setEnabled(true);
|
||||
|
||||
actionExclusive_Control->setDisabled(true);
|
||||
|
||||
switch(plm->portGroup(current).state())
|
||||
{
|
||||
case QAbstractSocket::UnconnectedState:
|
||||
@ -247,9 +256,15 @@ void PortsWindow::updatePortViewActions(const QModelIndex& current)
|
||||
}
|
||||
else if (plm->isPort(current))
|
||||
{
|
||||
actionDelete_Port_Group->setEnabled(false);
|
||||
actionConnect_Port_Group->setEnabled(false);
|
||||
actionDisconnect_Port_Group->setEnabled(false);
|
||||
actionDelete_Port_Group->setDisabled(true);
|
||||
actionConnect_Port_Group->setDisabled(true);
|
||||
actionDisconnect_Port_Group->setDisabled(true);
|
||||
|
||||
actionExclusive_Control->setEnabled(true);
|
||||
if (plm->port(current).hasExclusiveControl())
|
||||
actionExclusive_Control->setChecked(true);
|
||||
else
|
||||
actionExclusive_Control->setChecked(false);
|
||||
}
|
||||
|
||||
_EXIT:
|
||||
@ -346,6 +361,15 @@ void PortsWindow::on_actionDisconnect_Port_Group_triggered()
|
||||
if (current.isValid())
|
||||
plm->portGroup(current).disconnectFromHost();
|
||||
}
|
||||
|
||||
void PortsWindow::on_actionExclusive_Control_triggered(bool checked)
|
||||
{
|
||||
QModelIndex current = tvPortList->selectionModel()->currentIndex();
|
||||
|
||||
if (plm->isPort(current))
|
||||
plm->portGroup(current.parent()).modifyPort(current.row(), checked);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void PortsWindow::on_actionNew_Stream_triggered()
|
||||
{
|
||||
|
@ -51,6 +51,8 @@ private slots:
|
||||
void on_actionConnect_Port_Group_triggered();
|
||||
void on_actionDisconnect_Port_Group_triggered();
|
||||
|
||||
void on_actionExclusive_Control_triggered(bool checked);
|
||||
|
||||
void on_actionNew_Stream_triggered();
|
||||
void on_actionEdit_Stream_triggered();
|
||||
void on_actionDelete_Stream_triggered();
|
||||
|
@ -6,7 +6,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>689</width>
|
||||
<height>254</height>
|
||||
<height>352</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
@ -34,7 +34,10 @@
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="portDetail" >
|
||||
<layout class="QGridLayout" >
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
@ -47,13 +50,7 @@
|
||||
<property name="bottomMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="horizontalSpacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="verticalSpacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0" >
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<item>
|
||||
<spacer>
|
||||
@ -77,7 +74,7 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<item>
|
||||
<widget class="QFrame" name="frAggregate" >
|
||||
<property name="frameShape" >
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
@ -129,52 +126,23 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" >
|
||||
<widget class="QTabWidget" name="tabWidget" >
|
||||
<property name="currentIndex" >
|
||||
<number>0</number>
|
||||
<item>
|
||||
<widget class="QTableView" name="tvStreamList" >
|
||||
<property name="contextMenuPolicy" >
|
||||
<enum>Qt::ActionsContextMenu</enum>
|
||||
</property>
|
||||
<property name="frameShape" >
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="lineWidth" >
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="selectionMode" >
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior" >
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab_3" >
|
||||
<attribute name="title" >
|
||||
<string>Control</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="spacing" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTableView" name="tvStreamList" >
|
||||
<property name="contextMenuPolicy" >
|
||||
<enum>Qt::ActionsContextMenu</enum>
|
||||
</property>
|
||||
<property name="frameShape" >
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="lineWidth" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="selectionMode" >
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior" >
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
@ -254,6 +222,14 @@
|
||||
<string>Edit Stream</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExclusive_Control" >
|
||||
<property name="checkable" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Exclusive Control (EXPERIMENTAL)</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="ostinato.qrc" />
|
||||
|
@ -1,9 +1,7 @@
|
||||
// stream.proto
|
||||
|
||||
package OstProto;
|
||||
|
||||
message StreamId {
|
||||
required uint32 id = 1;
|
||||
required uint32 id = 1;
|
||||
}
|
||||
|
||||
message StreamCore {
|
||||
@ -136,7 +134,7 @@ message PortConfigList {
|
||||
}
|
||||
|
||||
message StreamConfigList {
|
||||
required PortId port_id = 1;
|
||||
required PortId port_id = 1;
|
||||
repeated Stream stream = 2;
|
||||
}
|
||||
|
||||
@ -188,6 +186,7 @@ message PortStatsList {
|
||||
service OstService {
|
||||
rpc getPortIdList(Void) returns (PortIdList);
|
||||
rpc getPortConfig(PortIdList) returns (PortConfigList);
|
||||
rpc modifyPort(PortConfigList) returns (Ack);
|
||||
|
||||
rpc getStreamIdList(PortId) returns (StreamIdList);
|
||||
rpc getStreamConfig(StreamIdList) returns (StreamConfigList);
|
||||
|
@ -64,7 +64,7 @@ void PbRpcChannel::CallMethod(
|
||||
::google::protobuf::Closure* done)
|
||||
{
|
||||
char msg[MSGBUF_SIZE];
|
||||
int len;
|
||||
int len;
|
||||
bool ret;
|
||||
|
||||
if (isPending)
|
||||
@ -80,6 +80,7 @@ void PbRpcChannel::CallMethod(
|
||||
call.done = done;
|
||||
|
||||
pendingCallList.append(call);
|
||||
qDebug("pendingCallList size = %d", pendingCallList.size());
|
||||
|
||||
Q_ASSERT(pendingCallList.size() < 100);
|
||||
|
||||
@ -113,7 +114,7 @@ void PbRpcChannel::CallMethod(
|
||||
*((quint32*)(&msg[4])) = HTONL(len); // len
|
||||
|
||||
// Avoid printing stats since it happens every couple of seconds
|
||||
if (pendingMethodId != 12)
|
||||
if (pendingMethodId != 13)
|
||||
{
|
||||
qDebug("client(%s) sending %d bytes encoding <%s>", __FUNCTION__,
|
||||
PB_HDR_SIZE + len, req->DebugString().c_str());
|
||||
@ -230,7 +231,7 @@ void PbRpcChannel::on_mpSocket_readyRead()
|
||||
response->ParseFromArray((void*) msg, len);
|
||||
|
||||
// Avoid printing stats
|
||||
if (method != 12)
|
||||
if (method != 13)
|
||||
{
|
||||
qDebug("client(%s): Parsed as %s", __FUNCTION__,
|
||||
response->DebugString().c_str());
|
||||
@ -262,6 +263,7 @@ void PbRpcChannel::on_mpSocket_readyRead()
|
||||
if (pendingCallList.size())
|
||||
{
|
||||
RpcCall call = pendingCallList.takeFirst();
|
||||
qDebug("RpcChannel: executing queued method %d", call.method->index());
|
||||
CallMethod(call.method, call.controller, call.request, call.response,
|
||||
call.done);
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ void RpcServer::done(::google::protobuf::Message *request,
|
||||
*((quint32*)(&msg[4])) = HTONL(len); // len
|
||||
|
||||
// Avoid printing stats since it happens once every couple of seconds
|
||||
if (pendingMethodId != 12)
|
||||
if (pendingMethodId != 13)
|
||||
{
|
||||
qDebug("Server(%s): sending %d bytes to client encoding <%s>",
|
||||
__FUNCTION__, len + PB_HDR_SIZE, response->DebugString().c_str());
|
||||
|
@ -13,7 +13,6 @@ AbstractPort::AbstractPort(int id, const char *device)
|
||||
//! \todo (LOW) admin enable/disable of port
|
||||
data_.set_is_enabled(true);
|
||||
|
||||
//! \todo (HIGH) port exclusive control
|
||||
data_.set_is_exclusive_control(false);
|
||||
|
||||
isSendQueueDirty_ = true;
|
||||
@ -23,12 +22,29 @@ AbstractPort::AbstractPort(int id, const char *device)
|
||||
resetStats();
|
||||
}
|
||||
|
||||
AbstractPort::~AbstractPort()
|
||||
{
|
||||
}
|
||||
|
||||
void AbstractPort::init()
|
||||
{
|
||||
}
|
||||
|
||||
AbstractPort::~AbstractPort()
|
||||
bool AbstractPort::modify(const OstProto::Port &port)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
//! \todo Use reflection to find out which fields are set
|
||||
if (port.has_is_exclusive_control())
|
||||
{
|
||||
bool val = port.is_exclusive_control();
|
||||
|
||||
ret = setExclusiveControl(val);
|
||||
if (ret)
|
||||
data_.set_is_exclusive_control(val);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
StreamBase* AbstractPort::streamAtIndex(int index)
|
||||
|
@ -33,6 +33,12 @@ public:
|
||||
int id() { return data_.port_id().id(); }
|
||||
void protoDataCopyInto(OstProto::Port *port) { port->CopyFrom(data_); }
|
||||
|
||||
bool modify(const OstProto::Port &port);
|
||||
|
||||
virtual OstProto::LinkState linkState() { return linkState_; }
|
||||
virtual bool hasExclusiveControl() = 0;
|
||||
virtual bool setExclusiveControl(bool exclusive) = 0;
|
||||
|
||||
int streamCount() { return streamList_.size(); }
|
||||
StreamBase* streamAtIndex(int index);
|
||||
StreamBase* stream(int streamId);
|
||||
@ -42,8 +48,6 @@ public:
|
||||
bool isDirty() { return isSendQueueDirty_; }
|
||||
void setDirty() { isSendQueueDirty_ = true; }
|
||||
|
||||
virtual OstProto::LinkState linkState() { return linkState_; }
|
||||
|
||||
virtual void clearPacketList() = 0;
|
||||
virtual bool appendToPacketList(long sec, long usec, const uchar *packet,
|
||||
int length) = 0;
|
||||
|
@ -69,6 +69,30 @@ void MyService::getPortConfig(::google::protobuf::RpcController* /*controller*/,
|
||||
done->Run();
|
||||
}
|
||||
|
||||
void MyService::modifyPort(::google::protobuf::RpcController* /*controller*/,
|
||||
const ::OstProto::PortConfigList* request,
|
||||
::OstProto::Ack* /*response*/,
|
||||
::google::protobuf::Closure* done)
|
||||
{
|
||||
qDebug("In %s", __PRETTY_FUNCTION__);
|
||||
|
||||
for (int i = 0; i < request->port_size(); i++)
|
||||
{
|
||||
OstProto::Port port;
|
||||
int id;
|
||||
|
||||
port = request->port(i);
|
||||
id = port.port_id().id();
|
||||
if (id < portInfo.size())
|
||||
{
|
||||
portInfo[id]->modify(port);
|
||||
}
|
||||
}
|
||||
|
||||
//! \todo (LOW): fill-in response "Ack"????
|
||||
done->Run();
|
||||
}
|
||||
|
||||
void MyService::getStreamIdList(::google::protobuf::RpcController* controller,
|
||||
const ::OstProto::PortId* request,
|
||||
::OstProto::StreamIdList* response,
|
||||
|
@ -25,6 +25,10 @@ public:
|
||||
const ::OstProto::PortIdList* request,
|
||||
::OstProto::PortConfigList* response,
|
||||
::google::protobuf::Closure* done);
|
||||
void MyService::modifyPort(::google::protobuf::RpcController* /*controller*/,
|
||||
const ::OstProto::PortConfigList* request,
|
||||
::OstProto::Ack* response,
|
||||
::google::protobuf::Closure* done);
|
||||
virtual void getStreamIdList(::google::protobuf::RpcController* controller,
|
||||
const ::OstProto::PortId* request,
|
||||
::OstProto::StreamIdList* response,
|
||||
|
@ -44,24 +44,12 @@ PcapPort::PcapPort(int id, const char *device)
|
||||
|
||||
void PcapPort::init()
|
||||
{
|
||||
QString notes;
|
||||
|
||||
if (!monitorRx_->isDirectional() && !data_.is_exclusive_control())
|
||||
notes.append("<i>Rx Frames/Bytes</i>: Includes non Ostinato Tx pkts also (Tx by Ostinato are not included)<br>");
|
||||
|
||||
if (!monitorTx_->isDirectional())
|
||||
{
|
||||
transmitter_->useExternalStats(&stats_);
|
||||
notes.append("<i>Tx Frames/Bytes</i>: Only Ostinato Tx pkts (Tx by others NOT included)<br>");
|
||||
}
|
||||
|
||||
transmitter_->setHandle(monitorRx_->handle());
|
||||
|
||||
if (!notes.isEmpty())
|
||||
data_.set_notes(QString("<b>Limitation(s)</b>"
|
||||
"<p>%1<br>"
|
||||
"Rx/Tx Rates are also subject to above limitation(s)</p>").
|
||||
arg(notes).toStdString());
|
||||
updateNotes();
|
||||
|
||||
monitorRx_->start();
|
||||
monitorTx_->start();
|
||||
@ -75,6 +63,25 @@ PcapPort::~PcapPort()
|
||||
delete monitorRx_;
|
||||
}
|
||||
|
||||
void PcapPort::updateNotes()
|
||||
{
|
||||
QString notes;
|
||||
|
||||
if (!monitorRx_->isDirectional() && !hasExclusiveControl())
|
||||
notes.append("<i>Rx Frames/Bytes</i>: Includes non Ostinato Tx pkts also (Tx by Ostinato are not included)<br>");
|
||||
|
||||
if (!monitorTx_->isDirectional() && !hasExclusiveControl())
|
||||
notes.append("<i>Tx Frames/Bytes</i>: Only Ostinato Tx pkts (Tx by others NOT included)<br>");
|
||||
|
||||
if (notes.isEmpty())
|
||||
data_.set_notes("");
|
||||
else
|
||||
data_.set_notes(QString("<b>Limitation(s)</b>"
|
||||
"<p>%1<br>"
|
||||
"Rx/Tx Rates are also subject to above limitation(s)</p>").
|
||||
arg(notes).toStdString());
|
||||
}
|
||||
|
||||
PcapPort::PortMonitor::PortMonitor(const char *device, Direction direction,
|
||||
AbstractPort::PortStats *stats)
|
||||
{
|
||||
|
@ -16,6 +16,9 @@ public:
|
||||
|
||||
void init();
|
||||
|
||||
virtual bool hasExclusiveControl() { return false; }
|
||||
virtual bool setExclusiveControl(bool exclusive) { return false; }
|
||||
|
||||
virtual void clearPacketList() {
|
||||
transmitter_->clearPacketList();
|
||||
setPacketListLoopMode(false, 0);
|
||||
@ -114,11 +117,14 @@ protected:
|
||||
|
||||
PortMonitor *monitorRx_;
|
||||
PortMonitor *monitorTx_;
|
||||
|
||||
void updateNotes();
|
||||
|
||||
private:
|
||||
PortTransmitter *transmitter_;
|
||||
PortCapturer *capturer_;
|
||||
|
||||
static pcap_if_t *deviceList_;
|
||||
static pcap_if_t *deviceList_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "winpcapport.h"
|
||||
|
||||
#include <QProcess>
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
|
||||
const uint OID_GEN_MEDIA_CONNECT_STATUS = 0x00010114;
|
||||
@ -20,6 +22,8 @@ WinPcapPort::WinPcapPort(int id, const char *device)
|
||||
sizeof(uint));
|
||||
if (!linkStateOid_)
|
||||
qFatal("failed to alloc oidData");
|
||||
|
||||
data_.set_is_exclusive_control(hasExclusiveControl());
|
||||
}
|
||||
|
||||
WinPcapPort::~WinPcapPort()
|
||||
@ -53,6 +57,41 @@ OstProto::LinkState WinPcapPort::linkState()
|
||||
return linkState_;
|
||||
}
|
||||
|
||||
bool WinPcapPort::hasExclusiveControl()
|
||||
{
|
||||
QString portName(adapter_->Name + strlen("\\Device\\NPF_"));
|
||||
int exitCode;
|
||||
|
||||
qDebug("%s: %s", __FUNCTION__, portName.toAscii().constData());
|
||||
|
||||
exitCode = QProcess::execute("bindconfig.exe",
|
||||
QStringList() << "comp" << portName);
|
||||
|
||||
qDebug("%s: exit code %d", __FUNCTION__, exitCode);
|
||||
|
||||
if (exitCode == 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WinPcapPort::setExclusiveControl(bool exclusive)
|
||||
{
|
||||
QString portName(adapter_->Name + strlen("\\Device\\NPF_"));
|
||||
QString status;
|
||||
|
||||
qDebug("%s: %s", __FUNCTION__, portName.toAscii().constData());
|
||||
|
||||
status = exclusive ? "disable" : "enable";
|
||||
|
||||
QProcess::execute("bindconfig.exe",
|
||||
QStringList() << "comp" << portName << status);
|
||||
|
||||
updateNotes();
|
||||
|
||||
return (exclusive == hasExclusiveControl());
|
||||
}
|
||||
|
||||
WinPcapPort::PortMonitor::PortMonitor(const char *device, Direction direction,
|
||||
AbstractPort::PortStats *stats)
|
||||
: PcapPort::PortMonitor(device, direction, stats)
|
||||
|
@ -16,6 +16,8 @@ public:
|
||||
~WinPcapPort();
|
||||
|
||||
virtual OstProto::LinkState linkState();
|
||||
virtual bool hasExclusiveControl();
|
||||
virtual bool setExclusiveControl(bool exclusive);
|
||||
|
||||
protected:
|
||||
class PortMonitor: public PcapPort::PortMonitor
|
||||
|
Loading…
Reference in New Issue
Block a user