- Queued RPC calls would cause crashes due to invalid pointers to request/response and/or controller; this has been fixed
    - PbRpcController now takes ownership of request and response messages and
      will delete them when it itself is being deleted
    - This design mandates that request and response messages for each RPC call
      have to be allocated on the heap.
    - The convention for the Closure 'done' call now is to allocate and pass a
      pointer to the controller object to it which will delete it after use;
      this requires that controller itself be also allocated on the heap
      (NOTE: this is just a convention - not mandatory)
    - All existing RPC calls (in portgroup.cpp) have been changed to follow the
      above convention
- Reordering of queued RPC calls has been fixed
- PortManager is now destroyed at exit; because of this fix the per port temporary capture files are auto-removed at exit
- WinPcapPort destructor no longer deletes the monitor threads because the parent class PcapPort already does it
- Capture does not automatically (and incorrectly) stop after one packet if started immediately after a View Capture operation
- User is prompted to stop transmit on a port first if he tries to apply configuration changes on a port in 'transmit' state
This commit is contained in:
Srivats P. 2010-02-17 15:26:42 +00:00
parent b28bcd3055
commit 2581562ec5
14 changed files with 441 additions and 473 deletions

View File

@ -18,6 +18,7 @@ Port::Port(quint32 id, quint32 portGroupId)
d.mutable_port_id()->set_id(id); d.mutable_port_id()->set_id(id);
stats.mutable_port_id()->set_id(id); stats.mutable_port_id()->set_id(id);
mPortGroupId = portGroupId; mPortGroupId = portGroupId;
capFile_ = NULL;
} }
Port::~Port() Port::~Port()

View File

@ -1,9 +1,10 @@
#ifndef _PORT_H #ifndef _PORT_H
#define _PORT_H #define _PORT_H
#include <QObject>
#include <QString>
#include <QList> #include <QList>
#include <QString>
#include <QTemporaryFile>
#include "stream.h" #include "stream.h"
//class StreamModel; //class StreamModel;
@ -16,6 +17,7 @@ class Port : public QObject {
OstProto::Port d; OstProto::Port d;
OstProto::PortStats stats; OstProto::PortStats stats;
QTemporaryFile *capFile_;
// FIXME(HI): consider removing mPortId as it is duplicated inside 'd' // FIXME(HI): consider removing mPortId as it is duplicated inside 'd'
quint32 mPortId; quint32 mPortId;
@ -66,6 +68,12 @@ public:
{ return stats.state().link_state(); } { return stats.state().link_state(); }
OstProto::PortStats getStats() { return stats; } OstProto::PortStats getStats() { return stats; }
QTemporaryFile* getCaptureFile()
{
delete capFile_;
capFile_ = new QTemporaryFile();
return capFile_;
}
// FIXME(MED): naming inconsistency - PortConfig/Stream; also retVal // FIXME(MED): naming inconsistency - PortConfig/Stream; also retVal
void updatePortConfig(OstProto::Port *port); void updatePortConfig(OstProto::Port *port);

File diff suppressed because it is too large Load Diff

View File

@ -28,13 +28,13 @@ private:
QString mUserAlias; // user defined QString mUserAlias; // user defined
PbRpcChannel *rpcChannel; PbRpcChannel *rpcChannel;
PbRpcController *rpcController; PbRpcController *statsController;
PbRpcController *rpcControllerStats;
bool isGetStatsPending_; bool isGetStatsPending_;
::OstProto::OstService::Stub *serviceStub; OstProto::OstService::Stub *serviceStub;
::OstProto::PortIdList portIdList; OstProto::PortIdList *portIdList_;
OstProto::PortStatsList *portStatsList_;
public: // FIXME(HIGH): member access public: // FIXME(HIGH): member access
QList<Port*> mPorts; QList<Port*> mPorts;
@ -62,36 +62,40 @@ public:
QAbstractSocket::SocketState state() const QAbstractSocket::SocketState state() const
{ return rpcChannel->state(); } { return rpcChannel->state(); }
void processPortIdList(OstProto::PortIdList *portIdList); void processPortIdList(PbRpcController *controller);
void processPortConfigList(OstProto::PortConfigList *portConfigList); void processPortConfigList(PbRpcController *controller);
void processAddStreamAck(PbRpcController *controller);
void processDeleteStreamAck(PbRpcController *controller);
void processModifyStreamAck(int portIndex, PbRpcController *controller);
void modifyPort(int portId, bool isExclusive); void modifyPort(int portId, bool isExclusive);
void processModifyPortAck(int portIndex, OstProto::Ack *ack); void processModifyPortAck(PbRpcController *controller);
void processUpdatedPortConfig(OstProto::PortConfigList *portConfigList); void processUpdatedPortConfig(PbRpcController *controller);
void getStreamIdList(int portIndex = 0, void getStreamIdList();
OstProto::StreamIdList *streamIdList = NULL); void processStreamIdList(int portIndex, PbRpcController *controller);
void getStreamConfigList(int portIndex = 0, void getStreamConfigList();
OstProto::StreamConfigList *streamConfigList = NULL); void processStreamConfigList(int portIndex, PbRpcController *controller);
void processModifyStreamAck(OstProto::Ack *ack); void processModifyStreamAck(OstProto::Ack *ack);
void startTx(QList<uint> *portList = NULL); void startTx(QList<uint> *portList = NULL);
void processStartTxAck(OstProto::Ack *ack); void processStartTxAck(PbRpcController *controller);
void stopTx(QList<uint> *portList = NULL); void stopTx(QList<uint> *portList = NULL);
void processStopTxAck(OstProto::Ack *ack); void processStopTxAck(PbRpcController *controller);
void startCapture(QList<uint> *portList = NULL); void startCapture(QList<uint> *portList = NULL);
void processStartCaptureAck(OstProto::Ack *ack); void processStartCaptureAck(PbRpcController *controller);
void stopCapture(QList<uint> *portList = NULL); void stopCapture(QList<uint> *portList = NULL);
void processStopCaptureAck(OstProto::Ack *ack); void processStopCaptureAck(PbRpcController *controller);
void viewCapture(QList<uint> *portList = NULL); void viewCapture(QList<uint> *portList = NULL);
void processViewCaptureAck(OstProto::CaptureBuffer *buf, QFile *capFile); void processViewCaptureAck(PbRpcController *controller);
void getPortStats(); void getPortStats();
void processPortStatsList(OstProto::PortStatsList *portStatsList); void processPortStatsList();
void clearPortStats(QList<uint> *portList = NULL); void clearPortStats(QList<uint> *portList = NULL);
void processClearStatsAck(OstProto::Ack *ack); void processClearStatsAck(PbRpcController *controller);
signals: signals:
void portGroupDataChanged(int portGroupId, int portId = 0xFFFF); void portGroupDataChanged(int portGroupId, int portId = 0xFFFF);
@ -106,16 +110,8 @@ private slots:
void on_rpcChannel_error(QAbstractSocket::SocketError socketError); void on_rpcChannel_error(QAbstractSocket::SocketError socketError);
public slots: public slots:
void when_configApply(int portIndex, uint *cookie = NULL); void when_configApply(int portIndex);
#if 0 // PB
void on_rpcChannel_when_dataAvail();
#endif
private:
#if 0 // PB
void ProcessCapabilityInfo(const char *msg, qint32 size);
void ProcessMsg(const char *msg, quint32 size);
#endif
}; };
#endif #endif

View File

@ -22,12 +22,13 @@ PortGroupList::PortGroupList()
PortGroupList::~PortGroupList() PortGroupList::~PortGroupList()
{ {
while (!mPortGroups.isEmpty())
delete mPortGroups.takeFirst();
delete portStatsModelTester_; delete portStatsModelTester_;
delete portModelTester_; delete portModelTester_;
delete streamModelTester_; delete streamModelTester_;
while (!mPortGroups.isEmpty())
delete mPortGroups.takeFirst();
} }
bool PortGroupList::isPortGroup(const QModelIndex& index) bool PortGroupList::isPortGroup(const QModelIndex& index)

View File

@ -2,6 +2,7 @@
#include <QInputDialog> #include <QInputDialog>
#include <QItemSelectionModel> #include <QItemSelectionModel>
#include <QMessageBox>
#include "streamconfigdialog.h" #include "streamconfigdialog.h"
#include "streamlistdelegate.h" #include "streamlistdelegate.h"
@ -289,6 +290,13 @@ void PortsWindow::on_pbApply_clicked()
goto _exit; goto _exit;
} }
if (plm->port(curPort).getStats().state().is_transmit_on())
{
QMessageBox::information(0, "Configuration Change",
"Please stop transmit on the port before applying any changes");
goto _exit;
}
curPortGroup = plm->getPortModel()->parent(curPort); curPortGroup = plm->getPortModel()->parent(curPort);
if (!curPortGroup.isValid()) if (!curPortGroup.isValid())
{ {

View File

@ -70,8 +70,9 @@ void PbRpcChannel::CallMethod(
if (isPending) if (isPending)
{ {
RpcCall call; RpcCall call;
qDebug("RpcChannel: queueing method %d since %d is pending", qDebug("RpcChannel: queueing method %d since %d is pending; "
method->index(), pendingMethodId); "queued message = <%s>",
method->index(), pendingMethodId, req->DebugString().c_str());
call.method = method; call.method = method;
call.controller = controller; call.controller = controller;
@ -252,18 +253,19 @@ void PbRpcChannel::on_mpSocket_readyRead()
} }
done->Run();
pendingMethodId = -1; pendingMethodId = -1;
controller = NULL; controller = NULL;
response = NULL; response = NULL;
isPending = false; isPending = false;
parsing = false; parsing = false;
done->Run();
if (pendingCallList.size()) if (pendingCallList.size())
{ {
RpcCall call = pendingCallList.takeFirst(); RpcCall call = pendingCallList.takeFirst();
qDebug("RpcChannel: executing queued method %d", call.method->index()); qDebug("RpcChannel: executing queued method %d <%s>",
call.method->index(), call.request->DebugString().c_str());
CallMethod(call.method, call.controller, call.request, call.response, CallMethod(call.method, call.controller, call.request, call.response,
call.done); call.done);
} }

View File

@ -5,17 +5,26 @@
class QIODevice; class QIODevice;
/*!
PbRpcController takes ownership of the 'request' and 'response' messages and
will delete them when it itself is destroyed
*/
class PbRpcController : public ::google::protobuf::RpcController class PbRpcController : public ::google::protobuf::RpcController
{ {
bool failed;
QIODevice *blob;
std::string errStr;
public: public:
PbRpcController() { Reset(); } PbRpcController(::google::protobuf::Message *request,
::google::protobuf::Message *response) {
request_ = request;
response_ = response;
Reset();
}
~PbRpcController() { delete request_; delete response_; }
::google::protobuf::Message* request() { return request_; }
::google::protobuf::Message* response() { return response_; }
// Client Side Methods // Client Side Methods
void Reset() { failed=false; blob = NULL; } void Reset() { failed = false; blob = NULL; }
bool Failed() const { return failed; } bool Failed() const { return failed; }
void StartCancel() { /*! \todo (MED) */} void StartCancel() { /*! \todo (MED) */}
std::string ErrorText() const { return errStr; } std::string ErrorText() const { return errStr; }
@ -31,6 +40,14 @@ public:
// srivatsp added // srivatsp added
QIODevice* binaryBlob() { return blob; }; QIODevice* binaryBlob() { return blob; };
void setBinaryBlob(QIODevice *binaryBlob) { blob = binaryBlob; }; void setBinaryBlob(QIODevice *binaryBlob) { blob = binaryBlob; };
private:
bool failed;
QIODevice *blob;
std::string errStr;
::google::protobuf::Message *request_;
::google::protobuf::Message *response_;
}; };
#endif #endif

View File

@ -10,7 +10,6 @@ RpcServer::RpcServer()
isPending = false; isPending = false;
pendingMethodId = -1; // don't care as long as isPending is false pendingMethodId = -1; // don't care as long as isPending is false
controller_.Reset();
} }
RpcServer::~RpcServer() RpcServer::~RpcServer()
@ -47,22 +46,22 @@ QString RpcServer::errorString()
return errorString_; return errorString_;
} }
void RpcServer::done(::google::protobuf::Message *request, void RpcServer::done(PbRpcController *controller)
::google::protobuf::Message *response)
{ {
google::protobuf::Message *response = controller->response();
QIODevice *blob; QIODevice *blob;
char msg[MSGBUF_SIZE]; char msg[MSGBUF_SIZE];
int len; int len;
//qDebug("In RpcServer::done"); //qDebug("In RpcServer::done");
if (controller_.Failed()) if (controller->Failed())
{ {
qDebug("rpc failed"); qDebug("rpc failed");
goto _exit; goto _exit;
} }
blob = controller_.binaryBlob(); blob = controller->binaryBlob();
if (blob) if (blob)
{ {
len = blob->size(); len = blob->size();
@ -114,8 +113,7 @@ void RpcServer::done(::google::protobuf::Message *request,
clientSock->write(msg, PB_HDR_SIZE + len); clientSock->write(msg, PB_HDR_SIZE + len);
_exit: _exit:
delete request; delete controller;
delete response;
isPending = false; isPending = false;
} }
@ -176,6 +174,7 @@ void RpcServer::when_dataAvail()
static quint32 len; static quint32 len;
const ::google::protobuf::MethodDescriptor *methodDesc; const ::google::protobuf::MethodDescriptor *methodDesc;
::google::protobuf::Message *req, *resp; ::google::protobuf::Message *req, *resp;
PbRpcController *controller;
if (!parsing) if (!parsing)
{ {
@ -240,12 +239,12 @@ void RpcServer::when_dataAvail()
//qDebug("Server(%s): successfully parsed as <%s>", __FUNCTION__, //qDebug("Server(%s): successfully parsed as <%s>", __FUNCTION__,
//resp->DebugString().c_str()); //resp->DebugString().c_str());
controller_.Reset(); controller = new PbRpcController(req, resp);
//qDebug("before service->callmethod()"); //qDebug("before service->callmethod()");
service->CallMethod(methodDesc, &controller_, req, resp, service->CallMethod(methodDesc, controller, req, resp,
NewCallback(this, &RpcServer::done, req, resp)); google::protobuf::NewCallback(this, &RpcServer::done, controller));
parsing = false; parsing = false;

View File

@ -23,7 +23,6 @@ class RpcServer : public QObject
bool isPending; bool isPending;
int pendingMethodId; int pendingMethodId;
PbRpcController controller_;
QString errorString_; QString errorString_;
public: public:
@ -33,8 +32,7 @@ public:
bool registerService(::google::protobuf::Service *service, bool registerService(::google::protobuf::Service *service,
quint16 tcpPortNum); quint16 tcpPortNum);
QString errorString(); QString errorString();
void done(::google::protobuf::Message *req, void done(PbRpcController *controller);
::google::protobuf::Message *resp);
private slots: private slots:
void when_newConnection(); void when_newConnection();

View File

@ -25,6 +25,9 @@ MyService::MyService()
MyService::~MyService() MyService::~MyService()
{ {
//! \todo Use a singleton destroyer instead
// http://www.research.ibm.com/designpatterns/pubs/ph-jun96.txt
delete PortManager::instance();
} }
void MyService::getPortIdList(::google::protobuf::RpcController* /*controller*/, void MyService::getPortIdList(::google::protobuf::RpcController* /*controller*/,

View File

@ -57,6 +57,7 @@ void PcapPort::init()
PcapPort::~PcapPort() PcapPort::~PcapPort()
{ {
qDebug("In %s", __FUNCTION__);
delete capturer_; delete capturer_;
delete transmitter_; delete transmitter_;
delete monitorTx_; delete monitorTx_;
@ -296,7 +297,8 @@ _restart:
if (ret < 0) if (ret < 0)
{ {
qDebug("error in sendQueueTransmit()"); qDebug("error %d in sendQueueTransmit()", ret);
stop_ = false;
return; return;
} }
} }
@ -312,7 +314,8 @@ _restart:
void PcapPort::PortTransmitter::stop() void PcapPort::PortTransmitter::stop()
{ {
stop_ = true; if (isRunning())
stop_ = true;
} }
int PcapPort::PortTransmitter::sendQueueTransmit(pcap_t *p, int PcapPort::PortTransmitter::sendQueueTransmit(pcap_t *p,
@ -332,7 +335,6 @@ int PcapPort::PortTransmitter::sendQueueTransmit(pcap_t *p,
if (stop_) if (stop_)
{ {
stop_ = false;
return -2; return -2;
} }
@ -453,7 +455,6 @@ void PcapPort::PortCapturer::run()
if (stop_) if (stop_)
{ {
qDebug("user requested capture stop\n"); qDebug("user requested capture stop\n");
stop_ = false;
break; break;
} }
} }
@ -461,11 +462,13 @@ void PcapPort::PortCapturer::run()
pcap_close(handle_); pcap_close(handle_);
dumpHandle_ = NULL; dumpHandle_ = NULL;
handle_ = NULL; handle_ = NULL;
stop_ = false;
} }
void PcapPort::PortCapturer::stop() void PcapPort::PortCapturer::stop()
{ {
stop_ = true; if (isRunning())
stop_ = true;
} }
QFile* PcapPort::PortCapturer::captureFile() QFile* PcapPort::PortCapturer::captureFile()

View File

@ -95,7 +95,7 @@ protected:
AbstractPort::PortStats *stats_; AbstractPort::PortStats *stats_;
bool usingInternalHandle_; bool usingInternalHandle_;
pcap_t *handle_; pcap_t *handle_;
bool stop_; volatile bool stop_;
}; };
class PortCapturer: public QThread class PortCapturer: public QThread
@ -109,7 +109,7 @@ protected:
private: private:
QString device_; QString device_;
bool stop_; volatile bool stop_;
QTemporaryFile capFile_; QTemporaryFile capFile_;
pcap_t *handle_; pcap_t *handle_;
pcap_dumper_t *dumpHandle_; pcap_dumper_t *dumpHandle_;

View File

@ -28,8 +28,6 @@ WinPcapPort::WinPcapPort(int id, const char *device)
WinPcapPort::~WinPcapPort() WinPcapPort::~WinPcapPort()
{ {
delete monitorRx_;
delete monitorTx_;
} }
OstProto::LinkState WinPcapPort::linkState() OstProto::LinkState WinPcapPort::linkState()