ostinato/server/winpcapport.cpp

147 lines
4.1 KiB
C++
Raw Normal View History

#include "winpcapport.h"
#ifdef Q_OS_WIN32
const uint OID_GEN_MEDIA_CONNECT_STATUS = 0x00010114;
WinPcapPort::WinPcapPort(int id, const char *device)
: PcapPort(id, device)
{
delete monitorRx_;
delete monitorTx_;
monitorRx_ = new PortMonitor(device, kDirectionRx, &stats_);
monitorTx_ = new PortMonitor(device, kDirectionTx, &stats_);
adapter_ = PacketOpenAdapter((CHAR*)device);
if (!adapter_)
qFatal("Unable to open adapter %s", device);
linkStateOid_ = (PPACKET_OID_DATA) malloc(sizeof(PACKET_OID_DATA) +
sizeof(uint));
if (!linkStateOid_)
qFatal("failed to alloc oidData");
}
WinPcapPort::~WinPcapPort()
{
}
OstProto::LinkState WinPcapPort::linkState()
{
memset(linkStateOid_, 0, sizeof(PACKET_OID_DATA) + sizeof(uint));
linkStateOid_->Oid = OID_GEN_MEDIA_CONNECT_STATUS;
linkStateOid_->Length = sizeof(uint);
if (PacketRequest(adapter_, 0, linkStateOid_))
{
uint state;
if (linkStateOid_->Length == sizeof(state))
{
memcpy((void*)&state, (void*)linkStateOid_->Data,
linkStateOid_->Length);
if (state == 0)
linkState_ = OstProto::LinkStateUp;
else if (state == 1)
linkState_ = OstProto::LinkStateDown;
}
}
return linkState_;
}
WinPcapPort::PortMonitor::PortMonitor(const char *device, Direction direction,
AbstractPort::PortStats *stats)
: PcapPort::PortMonitor(device, direction, stats)
{
pcap_setmode(handle(), MODE_STAT);
}
void WinPcapPort::PortMonitor::run()
{
struct timeval lastTs;
quint64 lastTxPkts = 0;
quint64 lastTxBytes = 0;
qWarning("in %s", __PRETTY_FUNCTION__);
lastTs.tv_sec = 0;
lastTs.tv_usec = 0;
while (1)
{
int ret;
struct pcap_pkthdr *hdr;
const uchar *data;
ret = pcap_next_ex(handle(), &hdr, &data);
switch (ret)
{
case 1:
{
quint64 pkts = *((quint64*)(data + 0));
quint64 bytes = *((quint64*)(data + 8));
// TODO: is it 12 or 16?
bytes -= pkts * 12;
uint usec = (hdr->ts.tv_sec - lastTs.tv_sec) * 1000000 +
(hdr->ts.tv_usec - lastTs.tv_usec);
switch (direction())
{
case kDirectionRx:
stats_->rxPkts += pkts;
stats_->rxBytes += bytes;
stats_->rxPps = (pkts * 1000000) / usec;
stats_->rxBps = (bytes * 1000000) / usec;
break;
case kDirectionTx:
if (isDirectional())
{
stats_->txPkts += pkts;
stats_->txBytes += bytes;
}
else
{
// Assuming stats_->txXXX are updated externally
quint64 txPkts = stats_->txPkts;
quint64 txBytes = stats_->txBytes;
pkts = txPkts - lastTxPkts;
bytes = txBytes - lastTxBytes;
lastTxPkts = txPkts;
lastTxBytes = txBytes;
}
stats_->txPps = (pkts * 1000000) / usec;
stats_->txBps = (bytes * 1000000) / usec;
break;
default:
Q_ASSERT(false);
}
break;
}
case 0:
//qDebug("%s: timeout. continuing ...", __PRETTY_FUNCTION__);
continue;
case -1:
qWarning("%s: error reading packet (%d): %s",
__PRETTY_FUNCTION__, ret, pcap_geterr(handle()));
break;
case -2:
default:
qFatal("%s: Unexpected return value %d", __PRETTY_FUNCTION__, ret);
}
lastTs.tv_sec = hdr->ts.tv_sec;
lastTs.tv_usec = hdr->ts.tv_usec;
QThread::msleep(1000);
}
}
#endif