Skip to content
Open
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
7849d60
testing
marre914 Mar 26, 2019
9073804
Started on monitoring network jitter
marre914 Mar 26, 2019
5b25632
Now measures IAT standard deviation. Working on adding it to UI
marre914 Mar 28, 2019
503fed6
Now displaying IAT standard deviation, however clears all other
marre914 Apr 2, 2019
162b789
µs IAT deviation now visible in UI under stream info!
marre914 Apr 3, 2019
d2ca29d
IAT deviation now working for TS
marre914 Apr 3, 2019
4b76707
Started working on implementing graph on recordwidget. There is now a
marre914 Apr 11, 2019
51f6c8f
Graph now generates one new point after it recieves signal. Possible
marre914 Apr 11, 2019
f969ad2
It nows draws a relative line of bitrate with max value as range max.
marre914 Apr 15, 2019
3fa8561
Bitrate graph now looks OK according to marre914
marre914 Apr 15, 2019
a2621fd
Experimenting with another chart class
marre914 May 3, 2019
7146ef9
Currently graph is working, showing 20 values. Working on implementing
marre914 May 8, 2019
fd1d283
Can now scroll and zoom graph.
marre914 May 15, 2019
0b9aba6
Graph now updates every 200ms, very nice!
marre914 May 22, 2019
b63f00a
Minor changes for bitrate signal. Lots of things to fix
marre914 May 23, 2019
954a6cd
Minor cleanup
marre914 May 23, 2019
85aafe6
Zoom and scroll focus now working properly for keyboard. +- and arrow
marre914 May 28, 2019
ead0469
Graph is now pretty ok! Updates properly and you can easily zoom and
marre914 May 28, 2019
d73abb0
Now displays time on x-axis in "m:s" format as well as being able to see
marre914 Jun 12, 2019
d1112a7
Graph window resizes better, focus doesn't get lost. DateTimeAxis now
marre914 Jun 12, 2019
96ffb05
Working on avg bitrate line for graph. Avg bitrate data over time is now
marre914 Jun 13, 2019
674b68f
Changed graph data selection.
marre914 Jun 14, 2019
83f97cf
Graph now working for ts files as well
marre914 Jun 17, 2019
c489eb8
Std iat deviation now kind of works for multiple stream only problem is
marre914 Jun 19, 2019
5145150
You can now select in QTreeWidget, sigsev faults occuring randomly and
marre914 Jun 20, 2019
f9e7ad2
You can now choose which stream to display in graph, crashes need to be
marre914 Jun 25, 2019
71b6fe8
Fixed crash issue, lag when plotting needs to fixed thou
marre914 Jun 26, 2019
35af210
Things are working, it's messy thou
marre914 Jun 27, 2019
b2358fa
Working on changeStream() things are working fine
marre914 Jun 27, 2019
c8508fe
Multiple streams now working properly for pcap. Able to switch between
marre914 Jul 1, 2019
26e45a4
Currently graph is working fine for bitrate in pcapfiles. Need to fix Y-
marre914 Jul 2, 2019
2457816
Graph is now working for ts files as well. IAT now works with
marre914 Jul 3, 2019
10cb2eb
Going to start messing around with playbackwidget, this state is
marre914 Jul 3, 2019
f602a7f
Fixed some bugs for RecordWidgetGraph.
marre914 Jul 8, 2019
d802e0f
Now printing csv file
marre914 Jul 11, 2019
67fd4ed
Now generates csv file per stream
marre914 Jul 11, 2019
b9ab2ba
CSV files working properly.
marre914 Jul 12, 2019
8502c32
Now exits program when closing window. Minor cleanup and working on
marre914 Jul 12, 2019
467c78a
fixes issue #33
marre914 Jul 12, 2019
cb3269c
Bug fixing, dropping off some redundant/ non realized features for
marre914 Aug 12, 2019
cb5058a
Fixed scaling when switching between data sets
marre914 Aug 14, 2019
879e8f5
Changed default size of window
marre914 Aug 14, 2019
e08aec3
Bug fixing
marre914 Aug 15, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions IPTVUtils.pro
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#-------------------------------------------------

QT += core gui network
QT += core gui charts

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

Expand Down Expand Up @@ -61,7 +62,11 @@ SOURCES += \
Analyzer/tsanalyzer.cpp \
playbackwidget.cpp \
recordwidget.cpp \
convertwidget.cpp
convertwidget.cpp \
Middleware/networkjitter.cpp \
recordwidgetgraph.cpp \
chart.cpp \
recordtxtprinter.cpp

HEADERS += \
mainwindow.h \
Expand Down Expand Up @@ -110,7 +115,11 @@ HEADERS += \
recordwidget.h \
convertwidget.h \
Status/streamid.h \
Status/workerstatus.h
Status/workerstatus.h \
Middleware/networkjitter.h \
recordwidgetgraph.h \
chart.h \
recordtxtprinter.h

FORMS += \
mainwindow.ui \
Expand Down
74 changes: 51 additions & 23 deletions Middleware/analyzerpcapmiddleware.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ void AnalyzerPcapMiddleware::init() {
this->moveToThread(&runnerThread);
connect(&runnerThread, &QThread::started, this, &AnalyzerPcapMiddleware::run);
connect(this, &AnalyzerPcapMiddleware::finished, &runnerThread, &QThread::quit);

}

void AnalyzerPcapMiddleware::start() {
Expand All @@ -34,9 +35,10 @@ void AnalyzerPcapMiddleware::run() {
this->thread()->quit();
}


// Buffers packets
void AnalyzerPcapMiddleware::bufferProducts() {
QElapsedTimer statusTimer;
QTime statusTimer;
statusTimer.start();
packetNumber = 0;

Expand All @@ -56,7 +58,10 @@ void AnalyzerPcapMiddleware::bufferProducts() {

PcapProduct input;


while (!stopping) {


input = prevProvider->getProduct();
if (input.type == PcapProduct::NORMAL && !hasLooped) {
PacketParser parser((pcap_pkthdr*)input.header.data(), (const u_char*)input.data.data());
Expand All @@ -65,28 +70,27 @@ void AnalyzerPcapMiddleware::bufferProducts() {
if (startTime == -1) {
startTime = ((pcap_pkthdr*)input.header.data())->ts.tv_sec * 1000; // convert to ms
startTime += ((pcap_pkthdr*)input.header.data())->ts.tv_usec/1000; // convert to ms
lastDuration = 0;
}
else {
endTime = ((pcap_pkthdr*)input.header.data())->ts.tv_sec*1000;
endTime += ((pcap_pkthdr*)input.header.data())->ts.tv_usec/1000; // convert to ms
duration = endTime - startTime;
if (lastDuration == 0)
lastDuration = duration;
}

// 1 second of trafic, calculate bitrate for that second

if (duration - lastDuration >= 1000) {
bitrate = (bytes - lastSecondBytes)*8*1000/(duration - lastDuration);
lastSecondBytes = bytes;
lastDuration = duration;
// 1 second of trafic, calculate bitrate for that second

if (duration - lastDuration >= emitFrequency) {
bitrate = (bytes - lastSecondBytes)*8*1000/(duration - lastDuration);
lastSecondBytes = bytes;
// lastDuration = duration;

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't use lastDuration in two places like this. Not sure this is actually run.

emitFrequency should mean that this is run every emit, in that case just move it to the other "emit" code below.

}
}

// sanity check, prevents analyzation of packets that do not contain ts-packets
if (parser.data_len % 188 == 0 && parser.ih->proto == 17 && parser.data_len != 0) {


tsPerIp = parser.data_len/188;

// For now, assume the only existing protocols
Expand All @@ -112,13 +116,14 @@ void AnalyzerPcapMiddleware::bufferProducts() {
else
stream.bitrateMode = StreamInfo::BitrateMode::VBR;

stream.id = StreamId(streamId);
stream.bytes += parser.data_len;
stream.tsPerIp = tsPerIp;
stream.currentTime = duration;

tsAnalyzer.setStream(&stream.tsErrors, &stream.pidMap);
//if (duration - stream.lastDuration >= 200)
stream.id = StreamId(streamId);
stream.bytes += parser.data_len;
stream.tsPerIp = tsPerIp;
stream.currentTime = duration;

tsAnalyzer.setStream(&stream.tsErrors, &stream.pidMap);
// }
// Analyze every TsPacket
for (quint8 i = 0; i < tsPerIp; i++) {
tsParser.parse((quint8*)(parser.data+i*188));
Expand All @@ -135,15 +140,12 @@ void AnalyzerPcapMiddleware::bufferProducts() {
}
else {


}
}

// case 1: sanity check true
buffer.push(input);
packetNumber++;


}
else {

Expand All @@ -153,7 +155,7 @@ void AnalyzerPcapMiddleware::bufferProducts() {
}

}
else if (input.type == PcapProduct::LOOP) {
else if (input.type == PcapProduct::LOOP || input.type == PcapProduct::END) {
hasLooped = true;

buffer.push(input);
Expand All @@ -162,10 +164,36 @@ void AnalyzerPcapMiddleware::bufferProducts() {
}


if (statusTimer.elapsed() >= 200) {





if (lastDuration > 1000000000){

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this check?

lastDuration = 0;
}


if (duration - lastDuration >= emitFrequency) {

lastDuration = duration;

for (auto &stream : streams) {

stream.avgBitrate = ((double)stream.bytes*8*1000.0/stream.currentTime) /1000000.0;
stream.currentBitrate = (double)(stream.bytes - stream.lastSecondBytes)*8*1000/(duration - stream.lastDuration) / 1000000;
stream.lastSecondBytes = stream.bytes;
stream.lastDuration = duration;
}

emit status(AnalyzerStatus(Status::STATUS_PERIODIC, bytes, duration, bitrate, duration, pidMap, tsErrors, proto, tsPerIp));
emit workerStatus(WorkerStatus(WorkerStatus::STATUS_PERIODIC, streams));
if(bitrate / 1000000 < 100){

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't need this check

emit bitrateStatus((double) bitrate /1000000, duration );

}

statusTimer.restart();
emit workerStatus(WorkerStatus(WorkerStatus::STATUS_PERIODIC, streams), false);
}

if (input.type == PcapProduct::END || input.type == PcapProduct::STOP) {
Expand All @@ -175,12 +203,12 @@ void AnalyzerPcapMiddleware::bufferProducts() {
qInfo("Analyzer done, processed %lli packets", packetNumber-1);
emit status(AnalyzerStatus(Status::STATUS_FINISHED, bytes, duration, bitrate, duration, pidMap, tsErrors, proto, tsPerIp));

emit workerStatus(WorkerStatus(WorkerStatus::STATUS_FINISHED, streams));
emit workerStatus(WorkerStatus(WorkerStatus::STATUS_FINISHED, streams), false);
if (input.type == PcapProduct::END &&
(config.getWorkerMode() == WorkerConfiguration::ANALYSIS_MODE_LIVE ||
config.getWorkerMode() == WorkerConfiguration::ANALYSIS_MODE_OFFLINE)) {

emit workerStatus(WorkerStatus(WorkerStatus::STATUS_ANALYZED_ENTIRE, streams));
emit workerStatus(WorkerStatus(WorkerStatus::STATUS_ANALYZED_ENTIRE, streams), false);
}
}

Expand Down
3 changes: 3 additions & 0 deletions Middleware/analyzerpcapmiddleware.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ class AnalyzerPcapMiddleware : public PcapMiddleware
{
Q_OBJECT
private:
double currentIatDev;
qint64 currentIatDevTimestamp;
ConcurrentQueue<PcapProduct> buffer;
TsParser tsParser;
TsAnalyzer tsAnalyzer;
Expand All @@ -41,6 +43,7 @@ class AnalyzerPcapMiddleware : public PcapMiddleware

signals:
void status(AnalyzerStatus status);
void bitrateStatus(double bitrate, qint64 duration);

protected slots:
void run();
Expand Down
160 changes: 160 additions & 0 deletions Middleware/networkjitter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
#include "networkjitter.h"
#include <QElapsedTimer>

#include <iostream>
#include "Status/streamid.h"
#include "Status/streaminfo.h"
#include "packetparser.h"
#include "tsparser.h"
#include <QDebug>
#include <QtMath>

//This class is for measuring network jitter

void NetworkJitter::init() {
this->moveToThread(&runnerThread);
connect(&runnerThread, &QThread::started, this, &NetworkJitter::run);
connect(this, &NetworkJitter::finished, &runnerThread, &QThread::quit);
}


void NetworkJitter::run(){

emit started();
QElapsedTimer statusTimer;
statusTimer.start();

packetNumber = 0;


qint64 inputTs = 0;
qint64 previousInputTs = 0;
qint64 difference = 0;
qint64 differencePerSec = 0;
qint64 packetCounter = 0;
qint16 diffratePerSec = 0;

qint64 diffSum = 0;
qint64 finalSum = 0;
qint64 startTime = -1;
qint64 endTime = -1;


QList<qint16> distanceList;
qint64 bytes = 0;
PcapProduct input;

PcapProduct previousInput = prevProvider->getProduct();

buffer.push(previousInput);

while (!stopping) {
PacketParser parser((pcap_pkthdr*)input.header.data(), (const u_char*)input.data.data());
bytes += parser.data_len;
input = prevProvider->getProduct();

{

PacketParser parser((pcap_pkthdr*)input.header.data(), (const u_char*)input.data.data());
bytes += parser.data_len;

// Takes packet Timestamp and compares it to the previous one to calculate difference.
inputTs = ((pcap_pkthdr*)input.header.data())->ts.tv_sec * 1000000;
inputTs += ((pcap_pkthdr*)input.header.data())->ts.tv_usec;

previousInputTs = ((pcap_pkthdr*)previousInput.header.data())->ts.tv_sec * 1000000;
previousInputTs += ((pcap_pkthdr*)previousInput.header.data())->ts.tv_usec;



if (startTime == -1) {
startTime = ((pcap_pkthdr*)input.header.data())->ts.tv_sec * 1000; // convert to ms
startTime += ((pcap_pkthdr*)input.header.data())->ts.tv_usec/1000; // convert to ms
}
else {
endTime = ((pcap_pkthdr*)input.header.data())->ts.tv_sec*1000;
endTime += ((pcap_pkthdr*)input.header.data())->ts.tv_usec/1000; // convert to ms
duration = endTime - startTime;

}





difference = inputTs - previousInputTs;
differencePerSec += difference;
distanceList.append(difference);

//Calculate average diff per second and IAT standard deviation per millisecond

if(statusTimer.elapsed() >= emitFrequency){
// If no packages recieved, wait(?)
if(packetCounter != 0){
diffratePerSec = differencePerSec/packetCounter;
}

for( int a = 0; a < distanceList.length(); a = a + 1 ) {

diffSum += ((distanceList[a] - diffratePerSec) * (distanceList[a] - diffratePerSec));
}

// sqrt of finalSum is equal to the IAT dev

finalSum = diffSum/ distanceList.length();



quint64 streamId = StreamId::calcId(parser.ih->daddr, parser.dport);
StreamInfo &stream = streams[streamId];


stream.iatDeviation = sqrt(finalSum);

emit iatStatus(sqrt(finalSum), duration);

emit workerStatus(WorkerStatus(WorkerStatus::STATUS_PERIODIC, streams), true);



packetCounter = 0;
diffSum = 0;
finalSum = 0;
distanceList.clear();


differencePerSec = 0;
statusTimer.restart();

}

}
previousInput = input;
buffer.push(input);
packetNumber++;
packetCounter ++;

if (input.type == PcapProduct::END || input.type == PcapProduct::STOP) {
break;
}

}
emit finished();
}



void NetworkJitter::start() {
runnerThread.start();
}


PcapProduct NetworkJitter::getProduct() {
return buffer.pop();
}


void NetworkJitter::stop() {
stopping = true;
buffer.stop();
}
Loading