- Ostinato Client
		- will start the server as a child process at startup and terminate it at exit

	- Ostinato Server (Drone)
		- is now a system tray application
		- if not able to bind to a IP/Port successfully, informs the user and exits
		- the GUI is now nothing more than a TextLabel

Others
	- If a getStats() request is pending, the client will not queue up any more requests till a reply is received for the pending one
	- Nitpicks in the Payload protocol Widget, PortsWindow Widget
This commit is contained in:
Srivats P. 2009-11-29 16:32:31 +00:00
parent 4c5b8faff7
commit bb6a9235c3
19 changed files with 367 additions and 184 deletions

View File

@ -1,6 +1,7 @@
#include <QApplication>
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char* argv[])
{
QApplication app(argc, argv);

View File

@ -1,17 +1,25 @@
#include "mainwindow.h"
#include "portgrouplist.h"
#if 0
#include "dbgthread.h"
#endif
#include "portgrouplist.h"
#include "portstatswindow.h"
#include "portswindow.h"
#include "ui_about.h"
#include <QDockWidget>
#include <QProcess>
PortGroupList *pgl;
MainWindow::MainWindow(QWidget *parent)
: QMainWindow (parent)
{
localServer_ = new QProcess(this);
localServer_->start("drone.exe");
pgl = new PortGroupList;
portsWindow = new PortsWindow(pgl, this);
@ -37,6 +45,10 @@ MainWindow::MainWindow(QWidget *parent)
MainWindow::~MainWindow()
{
delete pgl;
localServer_->terminate();
localServer_->waitForFinished();
delete localServer_;
}
void MainWindow::on_actionHelpAbout_triggered()

View File

@ -1,19 +1,21 @@
#ifndef _MAIN_WINDOW_H
#define _MAIN_WINDOW_H
#include <QMainWindow>
#include <QDockWidget>
#include "ui_mainwindow.h"
#include <QMainWindow>
#include "portswindow.h"
#include "portstatswindow.h"
class PortsWindow;
class PortStatsWindow;
class QDockWidget;
class QProcess;
class MainWindow : public QMainWindow, private Ui::MainWindow
{
Q_OBJECT
private:
QProcess *localServer_;
PortsWindow *portsWindow;
PortStatsWindow *statsWindow;
QDockWidget *portsDock;

View File

@ -21,6 +21,7 @@ PortGroup::PortGroup(QHostAddress ip, quint16 port)
*/
rpcController = new PbRpcController;
rpcControllerStats = new PbRpcController;
isGetStatsPending_ = false;
serviceStub = new OstProto::OstService::Stub(rpcChannel,
OstProto::OstService::STUB_OWNS_CHANNEL);
@ -640,8 +641,12 @@ void PortGroup::getPortStats()
if (state() != QAbstractSocket::ConnectedState)
return;
if (isGetStatsPending_)
return;
portStatsList = new OstProto::PortStatsList;
rpcControllerStats->Reset();
isGetStatsPending_ = true;
serviceStub->getStats(rpcControllerStats, &portIdList, portStatsList,
NewCallback(this, &PortGroup::processPortStatsList, portStatsList));
}
@ -669,6 +674,7 @@ void PortGroup::processPortStatsList(OstProto::PortStatsList *portStatsList)
_error_exit:
delete portStatsList;
isGetStatsPending_ = false;
}
void PortGroup::clearPortStats(QList<uint> *portList)

View File

@ -34,6 +34,7 @@ private:
PbRpcChannel *rpcChannel;
PbRpcController *rpcController;
PbRpcController *rpcControllerStats;
bool isGetStatsPending_;
::OstProto::OstService::Stub *serviceStub;
::OstProto::PortIdList portIdList;

View File

@ -71,7 +71,6 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
PortsWindow::~PortsWindow()
{
delete plm;
}
void PortsWindow::on_tvStreamList_activated(const QModelIndex & index)

View File

@ -18,6 +18,9 @@
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="childrenCollapsible" >
<bool>false</bool>
</property>
<widget class="QTreeView" name="tvPortList" >
<property name="contextMenuPolicy" >
<enum>Qt::ActionsContextMenu</enum>

View File

@ -5,63 +5,100 @@
<rect>
<x>0</x>
<y>0</y>
<width>142</width>
<height>98</height>
<width>299</width>
<height>114</height>
</rect>
</property>
<property name="windowTitle" >
<string>Form</string>
</property>
<layout class="QHBoxLayout" >
<item>
<widget class="QGroupBox" name="groupBox_6" >
<property name="title" >
<string>Data Pattern</string>
<layout class="QGridLayout" >
<item row="0" column="0" >
<widget class="QLabel" name="label" >
<property name="text" >
<string>Type</string>
</property>
<property name="buddy" >
<cstring>cmbPatternMode</cstring>
</property>
<layout class="QVBoxLayout" >
<item>
<widget class="QComboBox" name="cmbPatternMode" >
<item>
<property name="text" >
<string>Fixed Word</string>
</property>
</item>
<item>
<property name="text" >
<string>Increment Byte</string>
</property>
</item>
<item>
<property name="text" >
<string>Decrement Byte</string>
</property>
</item>
<item>
<property name="text" >
<string>Random</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lePattern" >
<property name="inputMask" >
<string>>HH HH HH HH; </string>
</property>
<property name="text" >
<string> </string>
</property>
<property name="maxLength" >
<number>11</number>
</property>
<property name="alignment" >
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="1" >
<widget class="QComboBox" name="cmbPatternMode" >
<item>
<property name="text" >
<string>Fixed Word</string>
</property>
</item>
<item>
<property name="text" >
<string>Increment Byte</string>
</property>
</item>
<item>
<property name="text" >
<string>Decrement Byte</string>
</property>
</item>
<item>
<property name="text" >
<string>Random</string>
</property>
</item>
</widget>
</item>
<item row="0" column="2" >
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0" >
<widget class="QLabel" name="label_2" >
<property name="text" >
<string>Pattern</string>
</property>
<property name="buddy" >
<cstring>lePattern</cstring>
</property>
</widget>
</item>
<item row="1" column="1" >
<widget class="QLineEdit" name="lePattern" >
<property name="inputMask" >
<string>>HH HH HH HH; </string>
</property>
<property name="text" >
<string> </string>
</property>
<property name="maxLength" >
<number>11</number>
</property>
<property name="alignment" >
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="1" >
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>

View File

@ -27,14 +27,25 @@ bool RpcServer::registerService(::google::protobuf::Service *service,
connect(server, SIGNAL(newConnection()), this, SLOT(when_newConnection()));
if (!server->listen(QHostAddress::Any, tcpPortNum))
{
LogInt(tr("Unable to start the server: %1").arg(server->errorString()));
qDebug("Unable to start the server: %s",
server->errorString().toAscii().constData());
errorString_ = QString("Error starting Ostinato server: %1").arg(
server->errorString());
return false;
}
LogInt(tr("The server is running on %1:%2").arg(server->serverAddress().toString()).arg(server->serverPort()));
qDebug("The server is running on %s: %d",
server->serverAddress().toString().toAscii().constData(),
server->serverPort());
errorString_ = QString();
return true;
}
QString RpcServer::errorString()
{
return errorString_;
}
void RpcServer::done(::google::protobuf::Message *resp, PbRpcController *PbRpcController)
{
QIODevice *blob;
@ -111,7 +122,7 @@ void RpcServer::when_newConnection()
{
QTcpSocket *sock;
LogInt(tr("already connected, no new connections will be accepted\n"));
qDebug("already connected, no new connections will be accepted");
// Accept and close connection
//! \todo (MED) Send reason msg to client
@ -122,7 +133,9 @@ void RpcServer::when_newConnection()
}
clientSock = server->nextPendingConnection();
LogInt(tr("accepting new connection from %1:%2").arg(clientSock->peerAddress().toString()).arg(clientSock->peerPort()));
qDebug("accepting new connection from %s: %d",
clientSock->peerAddress().toString().toAscii().constData(),
clientSock->peerPort());
connect(clientSock, SIGNAL(readyRead()),
this, SLOT(when_dataAvail()));
@ -137,7 +150,9 @@ _exit:
void RpcServer::when_disconnected()
{
LogInt(tr("connection closed from %1:%2").arg(clientSock->peerAddress().toString()).arg(clientSock->peerPort()));
qDebug("connection closed from %s: %d",
clientSock->peerAddress().toString().toAscii().constData(),
clientSock->peerPort());
clientSock->deleteLater();
clientSock = NULL;
@ -145,7 +160,7 @@ void RpcServer::when_disconnected()
void RpcServer::when_error(QAbstractSocket::SocketError socketError)
{
LogInt(clientSock->errorString());
qDebug("%s", clientSock->errorString().toAscii().constData());
}
void RpcServer::when_dataAvail()

View File

@ -23,8 +23,7 @@ class RpcServer : public QObject
bool isPending;
int pendingMethodId;
void LogInt (QString log) {qDebug("%s", log.toAscii().data());}
QString errorString_;
public:
RpcServer(); //! \todo (LOW) use 'parent' param
@ -32,6 +31,7 @@ public:
bool registerService(::google::protobuf::Service *service,
quint16 tcpPortNum);
QString errorString();
void done(::google::protobuf::Message *resp, PbRpcController *controller);
private slots:

View File

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

View File

@ -1,23 +1,76 @@
#include "drone.h"
#include "rpcserver.h"
#include "myservice.h"
#include <QCloseEvent>
#include <QMessageBox>
extern int myport;
Drone::Drone(QDialog *parent)
: QDialog(parent)
Drone::Drone(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
setupUi(this);
rpcServer = new RpcServer();
service = new MyService(this);
rpcServer->registerService(service, myport ? myport : 7878);
}
void Drone::Log(const char* str)
{
ui.teLog->append(QString(str));
rpcServer = new RpcServer();
service = new MyService();
}
void Drone::LogInt(const QString &str)
Drone::~Drone()
{
ui.teLog->append(str);
trayIcon_->hide();
delete rpcServer;
delete service;
}
bool Drone::init()
{
Q_ASSERT(rpcServer);
if (!rpcServer->registerService(service, myport ? myport : 7878))
{
QMessageBox::critical(0, qApp->applicationName(),
rpcServer->errorString());
return false;
}
trayIconMenu_ = new QMenu(this);
trayIconMenu_->addAction(actionShow);
trayIconMenu_->addAction(actionExit);
trayIconMenu_->setDefaultAction(actionShow);
trayIcon_ = new QSystemTrayIcon();
trayIcon_->setIcon(QIcon(":/icons/portgroup.png"));
trayIcon_->setToolTip(qApp->applicationName());
trayIcon_->setContextMenu(trayIconMenu_);
trayIcon_->show();
connect(trayIcon_, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason)));
connect(this, SIGNAL(hideMe(bool)), this, SLOT(setHidden(bool)),
Qt::QueuedConnection);
return true;
}
void Drone::changeEvent(QEvent *event)
{
if (event->type() == QEvent::WindowStateChange && isMinimized())
{
emit hideMe(true);
event->ignore();
return;
}
QWidget::changeEvent(event);
}
void Drone::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
{
if (reason == QSystemTrayIcon::DoubleClick)
{
showNormal();
activateWindow();
}
}

View File

@ -1,26 +1,37 @@
#ifndef _DRONE_H
#define _DRONE_H
#include <QTcpServer>
#include <QTcpSocket>
#include "ui_drone.h"
#include "abstracthost.h"
#include "rpcserver.h"
#include "myservice.h"
class Drone : public QDialog, AbstractHost
#include <QMenu>
#include <QSystemTrayIcon>
class RpcServer;
namespace OstProto { class OstService; }
class Drone : public QWidget, Ui::Drone
{
Q_OBJECT
public:
Ui::Drone ui;
Drone(QDialog *parent = 0);
void Log(const char *msg);
public:
Drone(QWidget *parent = 0);
~Drone();
bool init();
signals:
void hideMe(bool hidden);
protected:
void changeEvent(QEvent *event);
private:
QSystemTrayIcon *trayIcon_;
QMenu *trayIconMenu_;
RpcServer *rpcServer;
OstProto::OstService *service;
private slots:
void trayIconActivated(QSystemTrayIcon::ActivationReason reason);
private:
RpcServer *rpcServer;
OstProto::OstService *service;
void LogInt(const QString &msg);
};
#endif

View File

@ -11,6 +11,7 @@ unix:LIBS += -L"../common" -lostproto
win32:LIBS += -L"../rpc/debug" -lpbrpc
unix:LIBS += -L"../rpc" -lpbrpc
POST_TARGETDEPS += "../common/debug/libostproto.a" "../rpc/debug/libpbrpc.a"
RESOURCES += drone.qrc
HEADERS += drone.h
FORMS += drone.ui
SOURCES += drone_main.cpp drone.cpp

View File

@ -1,69 +1,82 @@
<ui version="4.0" >
<class>Drone</class>
<widget class="QDialog" name="Drone" >
<widget class="QWidget" name="Drone" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
<width>268</width>
<height>216</height>
</rect>
</property>
<property name="windowTitle" >
<string>Drone</string>
</property>
<property name="windowIcon" >
<iconset resource="drone.qrc" >:/icons/portgroup.png</iconset>
</property>
<layout class="QVBoxLayout" >
<item>
<widget class="QTabWidget" name="twDisplay" >
<property name="currentIndex" >
<number>1</number>
<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="QLabel" name="label_2" >
<property name="text" >
<string>&lt;html>&lt;head>&lt;meta name="qrichtext" content="1" />&lt;style type="text/css">&#xd;
p, li { white-space: pre-wrap; }&#xd;
&lt;/style>&lt;/head>&lt;body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">&#xd;
&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 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>
<widget class="QLabel" name="label_3" >
<property name="text" >
<string>(Server)</string>
</property>
<property name="alignment" >
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label" >
<property name="text" >
<string>TODO: Info/Status here</string>
</property>
<property name="alignment" >
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<size>
<width>20</width>
<height>51</height>
</size>
</property>
</spacer>
</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" >
@ -84,41 +97,82 @@
</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>
</item>
</layout>
<action name="actionShow" >
<property name="text" >
<string>Show</string>
</property>
</action>
<action name="actionExit" >
<property name="text" >
<string>Exit</string>
</property>
</action>
</widget>
<resources/>
<resources>
<include location="drone.qrc" />
</resources>
<connections>
<connection>
<sender>pushButton</sender>
<signal>clicked(bool)</signal>
<receiver>Drone</receiver>
<slot>accept()</slot>
<signal>clicked()</signal>
<receiver>actionExit</receiver>
<slot>trigger()</slot>
<hints>
<hint type="sourcelabel" >
<x>341</x>
<y>279</y>
<x>134</x>
<y>194</y>
</hint>
<hint type="destinationlabel" >
<x>226</x>
<y>268</y>
<x>-1</x>
<y>-1</y>
</hint>
</hints>
</connection>
<connection>
<sender>pbClearLog</sender>
<signal>clicked()</signal>
<receiver>teLog</receiver>
<slot>clear()</slot>
<sender>actionShow</sender>
<signal>triggered()</signal>
<receiver>Drone</receiver>
<slot>showNormal()</slot>
<hints>
<hint type="sourcelabel" >
<x>52</x>
<y>278</y>
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel" >
<x>100</x>
<y>185</y>
<x>133</x>
<y>107</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionExit</sender>
<signal>triggered()</signal>
<receiver>Drone</receiver>
<slot>close()</slot>
<hints>
<hint type="sourcelabel" >
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel" >
<x>133</x>
<y>107</y>
</hint>
</hints>
</connection>

View File

@ -1,18 +1,25 @@
#include "drone.h"
Drone *drone;
int myport;
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Drone drone;
app.setApplicationName(drone.objectName());
if (argc > 1)
myport = atoi(argv[1]);
drone = new Drone;
drone->show();
return app.exec();
if (!drone.init())
exit(-1);
drone.setWindowFlags(drone.windowFlags()
| Qt::WindowMaximizeButtonHint
| Qt::WindowMinimizeButtonHint);
drone.showMinimized();
app.exec();
return 0;
}

BIN
server/icons/portgroup.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

View File

@ -14,7 +14,7 @@
#include <Ntddndis.h>
#endif
#define LOG(...) {sprintf(logStr, __VA_ARGS__); host->Log(logStr);}
#define LOG(...) {}
#define MB (1024*1024)
StreamInfo::StreamInfo()
@ -831,14 +831,13 @@ _found:
return i;
}
MyService::MyService(AbstractHost *host)
MyService::MyService()
{
pcap_if_t *dev;
int i=0;
char errbuf[PCAP_ERRBUF_SIZE];
// Init Data
this->host = host;
numPorts = 0;
alldevs = NULL;

View File

@ -9,7 +9,6 @@
#include "../common/protocol.pb.h"
#include "../common/streambase.h"
#include "abstracthost.h"
#include <pcap.h>
#include <QtGlobal>
#include <QList>
@ -191,9 +190,6 @@ public:
class MyService: public OstProto::OstService
{
AbstractHost *host;
char logStr[1024];
uint numPorts;
/*! PortInfo::d::port_id and index into portInfo[] are same! */
@ -203,7 +199,7 @@ class MyService: public OstProto::OstService
int getStreamIndex(unsigned int portIdx,unsigned int streamId);
public:
MyService(AbstractHost* host);
MyService();
virtual ~MyService();
/* Methods provided by the service */