summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerald Combs <gerald@wireshark.org>2013-09-04 23:15:59 +0000
committerGerald Combs <gerald@wireshark.org>2013-09-04 23:15:59 +0000
commit03fd39d7f0c409a45e422d9142b48536ec5c8647 (patch)
treee8c1be0562459e4d302310d65cfd367b929e5564
parent1abd5a5965e3542c7dfcf6ec258daffe1d9fb504 (diff)
downloadwireshark-03fd39d7f0c409a45e422d9142b48536ec5c8647.tar.gz
Throughput graph updates.
GTK+: Fix what appears to be an off-by-one error in the MA period (21 segments instead of 20). Throw away our initial segment length instead of subtracting it from the moving sum, which skews the sum. Qt: Add the througput graph. Use bits/s for the throughput y axis. Let the user switch between graph types. The dialog hangs when doing this. I haven't been able to track down the cause. Remove some unused code. Both: Tell the user that we're using a 20 segment moving average. Move more routines to tap-tcp-stream.[ch]. svn path=/trunk/; revision=51759
-rw-r--r--ui/gtk/tcp_graph.c80
-rw-r--r--ui/qt/main_window.h2
-rw-r--r--ui/qt/main_window.ui9
-rw-r--r--ui/qt/main_window_slots.cpp16
-rw-r--r--ui/qt/tcp_stream_dialog.cpp285
-rw-r--r--ui/qt/tcp_stream_dialog.h16
-rw-r--r--ui/qt/tcp_stream_dialog.ui8
-rw-r--r--ui/tap-tcp-stream.c38
-rw-r--r--ui/tap-tcp-stream.h4
9 files changed, 331 insertions, 127 deletions
diff --git a/ui/gtk/tcp_graph.c b/ui/gtk/tcp_graph.c
index a085a12c57..157075accc 100644
--- a/ui/gtk/tcp_graph.c
+++ b/ui/gtk/tcp_graph.c
@@ -168,7 +168,7 @@ struct style_tseq_stevens {
struct style_tput {
int width, height;
- int nsegs;
+ int ma_size;
int flags;
};
@@ -387,8 +387,6 @@ static void callback_graph_init_on_typechg(GtkWidget * , gpointer );
static void callback_create_help(GtkWidget * , gpointer );
static void get_mouse_position(GtkWidget *, int *pointer_x, int *pointer_y, GdkModifierType *mask);
static void update_zoom_spins(struct gtk_graph * );
-static int get_num_dsegs(struct gtk_graph * );
-static int get_num_acks(struct gtk_graph *, int * );
static void graph_type_dependent_initialize(struct gtk_graph * );
static struct gtk_graph *graph_new(void);
static void graph_destroy(struct gtk_graph * );
@@ -3615,41 +3613,6 @@ static void restore_initial_graph_view(struct gtk_graph *g)
}
}
-static int get_num_dsegs(struct gtk_graph *g)
-{
- int count;
- struct segment *tmp;
-
- for (tmp=g->tg.segments, count=0; tmp; tmp=tmp->next) {
- if (compare_headers(&g->tg.src_address, &g->tg.dst_address,
- g->tg.src_port, g->tg.dst_port,
- &tmp->ip_src, &tmp->ip_dst,
- tmp->th_sport, tmp->th_dport,
- COMPARE_CURR_DIR)) {
- count++;
- }
- }
- return count;
-}
-
-static int get_num_acks(struct gtk_graph *g, int *num_sack_ranges)
-{
- int count;
- struct segment *tmp;
-
- for (tmp = g->tg.segments, count=0; tmp; tmp = tmp->next) {
- if (!compare_headers(&g->tg.src_address, &g->tg.dst_address,
- g->tg.src_port, g->tg.dst_port,
- &tmp->ip_src, &tmp->ip_dst,
- tmp->th_sport, tmp->th_dport,
- COMPARE_CURR_DIR)) {
- count++;
- *num_sack_ranges += tmp->num_sack_ranges;
- }
- }
- return count;
-}
-
/*
* Stevens-style time-sequence grapH
*/
@@ -3810,7 +3773,7 @@ static void tseq_stevens_make_elmtlist(struct gtk_graph *g)
debug(DBS_FENTRY) puts("tseq_stevens_make_elmtlist()");
if (g->elists->elements == NULL) {
- int n = 1 + get_num_dsegs(g);
+ int n = 1 + get_num_dsegs(&g->tg);
e = elements = (struct element * )g_malloc(n*sizeof(struct element));
} else
e = elements = g->elists->elements;
@@ -3936,7 +3899,7 @@ static void tseq_tcptrace_make_elmtlist(struct gtk_graph *g)
if (g->elists->elements == NULL ) {
/* 3 elements per data segment */
- int n = 1 + 3*get_num_dsegs(g);
+ int n = 1 + 3*get_num_dsegs(&g->tg);
e0 = elements0 = (struct element * )g_malloc(n * sizeof(struct element));
} else {
/* Existing array */
@@ -3945,7 +3908,7 @@ static void tseq_tcptrace_make_elmtlist(struct gtk_graph *g)
if (g->elists->next->elements == NULL) {
/* 4 elements per ACK, but only one for each SACK range */
- int n = 1 + 4*get_num_acks(g, &num_sack_ranges);
+ int n = 1 + 4*get_num_acks(&g->tg, &num_sack_ranges);
n += num_sack_ranges;
e1 = elements1 = (struct element * )g_malloc(n * sizeof(struct element));
} else {
@@ -4140,18 +4103,18 @@ static void tput_make_elmtlist(struct gtk_graph *g)
int num_sack_ranges;
if (g->elists->elements == NULL) {
- int n = 1 + get_num_dsegs(g) + get_num_acks(g, &num_sack_ranges);
+ int n = 1 + get_num_dsegs(&g->tg) + get_num_acks(&g->tg, &num_sack_ranges);
e = elements = (struct element * )g_malloc(n * sizeof(struct element));
} else
e = elements = g->elists->elements;
- for (oldest=g->tg.segments, tmp=g->tg.segments->next, i=0; tmp; tmp=tmp->next, i++) {
+ for (oldest=g->tg.segments, tmp=g->tg.segments->next, i=1; tmp; tmp=tmp->next, i++) {
double time_val = tmp->rel_secs + tmp->rel_usecs/1000000.0;
- dtime = time_val - (oldest->rel_secs + oldest->rel_usecs/1000000.0);
- if (i>g->s.tput.nsegs) {
- sum -= oldest->th_seglen;
+ if (i>g->s.tput.ma_size) {
oldest = oldest->next;
+ sum -= oldest->th_seglen;
}
+ dtime = time_val - (oldest->rel_secs + oldest->rel_usecs/1000000.0);
sum += tmp->th_seglen;
tput = sum / dtime;
/* debug(DBS_TPUT_ELMTS) printf("tput=%f\n", tput); */
@@ -4173,8 +4136,8 @@ static void tput_make_elmtlist(struct gtk_graph *g)
* - call setup routine for style struct */
static void tput_initialize(struct gtk_graph *g)
{
- struct segment *tmp, *oldest/*, *last*/;
- int i, sum = 0;
+ struct segment *tmp, *oldest = g->tg.segments/*, *last*/;
+ int i, sum = oldest->th_seglen;
double dtime, tput, tputmax = 0;
double t, t0, tmax = 0, yy0, ymax;
@@ -4182,16 +4145,13 @@ static void tput_initialize(struct gtk_graph *g)
tput_read_config(g);
-#if 0
- for (last=g->tg.segments; last->next; last=last->next); /* XXX: does nothing useful ? */
-#endif
- for (oldest=g->tg.segments, tmp=g->tg.segments->next, i=0; tmp; tmp=tmp->next, i++) {
- dtime = tmp->rel_secs + tmp->rel_usecs/1000000.0 -
- (oldest->rel_secs + oldest->rel_usecs/1000000.0);
- if (i > g->s.tput.nsegs) {
- sum -= oldest->th_seglen;
+ for (tmp=g->tg.segments->next, i=1; tmp; tmp=tmp->next, i++) {
+ if (i > g->s.tput.ma_size) {
oldest = oldest->next;
+ sum -= oldest->th_seglen;
}
+ dtime = tmp->rel_secs + tmp->rel_usecs/1000000.0 -
+ (oldest->rel_secs + oldest->rel_usecs/1000000.0);
sum += tmp->th_seglen;
tput = sum / dtime;
debug(DBS_TPUT_ELMTS) printf("tput=%f\n", tput);
@@ -4220,10 +4180,10 @@ static void tput_read_config(struct gtk_graph *g)
g->s.tput.width = 4;
g->s.tput.height = 4;
- g->s.tput.nsegs = 20;
+ g->s.tput.ma_size = 20;
g->title = (const char ** )g_malloc(2 * sizeof(char *));
- g->title[0] = "Throughput Graph";
+ g->title[0] = "Throughput (20 segment MA)";
g->title[1] = NULL;
g->y_axis->label = (const char ** )g_malloc(3 * sizeof(char * ));
g->y_axis->label[0] = "[B/s]";
@@ -4400,7 +4360,7 @@ static void rtt_make_elmtlist(struct gtk_graph *g)
debug(DBS_FENTRY) puts("rtt_make_elmtlist()");
if (g->elists->elements == NULL) {
- int n = 1 + get_num_dsegs(g);
+ int n = 1 + get_num_dsegs(&g->tg);
e = elements = (struct element * )g_malloc(n * sizeof(struct element));
} else {
e = elements = g->elists->elements;
@@ -4548,7 +4508,7 @@ static void wscale_make_elmtlist(struct gtk_graph *g)
/* Allocate memory for elements if not already done */
if (g->elists->elements == NULL)
{
- int n = 1 + get_num_dsegs(g);
+ int n = 1 + get_num_dsegs(&g->tg);
e = elements = (struct element*)g_malloc(n*sizeof(struct element));
}
else
diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h
index 0f68a9b863..bdbf1bc168 100644
--- a/ui/qt/main_window.h
+++ b/ui/qt/main_window.h
@@ -298,7 +298,9 @@ private slots:
void on_actionStopCapture_triggered();
void on_actionSummary_triggered();
+ void openTcpStreamDialog(int graph_type);
void on_actionStatisticsTcpStreamStevens_triggered();
+ void on_actionStatisticsTcpStreamThroughput_triggered();
};
diff --git a/ui/qt/main_window.ui b/ui/qt/main_window.ui
index 536093cef6..fdbeb811b9 100644
--- a/ui/qt/main_window.ui
+++ b/ui/qt/main_window.ui
@@ -320,6 +320,7 @@
<string>TCP Stream Graphs</string>
</property>
<addaction name="actionStatisticsTcpStreamStevens"/>
+ <addaction name="actionStatisticsTcpStreamThroughput"/>
</widget>
<addaction name="actionSummary"/>
<addaction name="actionProtocol_Hierarchy"/>
@@ -1256,6 +1257,14 @@
<string>TCP time sequence graph (Stevens)</string>
</property>
</action>
+ <action name="actionStatisticsTcpStreamThroughput">
+ <property name="text">
+ <string>Throughput</string>
+ </property>
+ <property name="toolTip">
+ <string>TCP througput</string>
+ </property>
+ </action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp
index ef927e020a..82f2b264ee 100644
--- a/ui/qt/main_window_slots.cpp
+++ b/ui/qt/main_window_slots.cpp
@@ -1689,14 +1689,26 @@ void MainWindow::on_actionAnalyzePAFOrNotSelected_triggered()
// Statistics Menu
-void MainWindow::on_actionStatisticsTcpStreamStevens_triggered()
+
+void MainWindow::openTcpStreamDialog(int graph_type)
{
- TCPStreamDialog stream_dialog(this, cap_file_, GRAPH_TSEQ_STEVENS);
+ TCPStreamDialog stream_dialog(this, cap_file_, (tcp_graph_type)graph_type);
connect(&stream_dialog, SIGNAL(goToPacket(int)),
packet_list_, SLOT(goToPacket(int)));
+ connect(this, SIGNAL(setCaptureFile(capture_file*)),
+ &stream_dialog, SLOT(setCaptureFile(capture_file*)));
stream_dialog.exec();
}
+void MainWindow::on_actionStatisticsTcpStreamStevens_triggered()
+{
+ openTcpStreamDialog(GRAPH_TSEQ_STEVENS);
+}
+
+void MainWindow::on_actionStatisticsTcpStreamThroughput_triggered()
+{
+ openTcpStreamDialog(GRAPH_THROUGHPUT);
+}
// Help Menu
void MainWindow::on_actionHelpContents_triggered() {
diff --git a/ui/qt/tcp_stream_dialog.cpp b/ui/qt/tcp_stream_dialog.cpp
index 5eec0faca9..36b4ffcd51 100644
--- a/ui/qt/tcp_stream_dialog.cpp
+++ b/ui/qt/tcp_stream_dialog.cpp
@@ -37,11 +37,20 @@
#include <QDebug>
+const int moving_avg_period_ = 20;
+const QRgb graph_color_1 = tango_sky_blue_5;
+const QRgb graph_color_2 = tango_butter_6;
+
+Q_DECLARE_METATYPE(tcp_graph_type)
+
TCPStreamDialog::TCPStreamDialog(QWidget *parent, capture_file *cf, tcp_graph_type graph_type) :
QDialog(parent),
ui(new Ui::TCPStreamDialog),
cap_file_(cf),
- tracer_(NULL)
+ tracer_(NULL),
+ num_dsegs_(-1),
+ num_acks_(-1),
+ num_sack_ranges_(-1)
{
struct segment current;
@@ -55,74 +64,42 @@ TCPStreamDialog::TCPStreamDialog(QWidget *parent, capture_file *cf, tcp_graph_ty
// ui->hintLabel->setAttribute(Qt::WA_MacSmallSize, true);
//#endif
+ ui->graphTypeComboBox->setUpdatesEnabled(false);
+ ui->graphTypeComboBox->addItem(tr("Time / Sequence (Stevens)"), qVariantFromValue(GRAPH_TSEQ_STEVENS));
+ ui->graphTypeComboBox->addItem(tr("Throughput"), qVariantFromValue(GRAPH_THROUGHPUT));
+ ui->graphTypeComboBox->setCurrentIndex(-1);
+ ui->graphTypeComboBox->setUpdatesEnabled(true);
+
memset (&graph_, 0, sizeof(graph_));
graph_.type = graph_type;
- graph_segment_list_get(cap_file_, &graph_, FALSE);
-
- QString dlg_title = QString(tr("TCP Graph %1 %2:%3 %4 %5:%6"))
- .arg(cf_get_display_name(cap_file_))
- .arg(ep_address_to_str(&graph_.src_address))
- .arg(graph_.src_port)
- .arg(UTF8_RIGHTWARDS_ARROW)
- .arg(ep_address_to_str(&graph_.dst_address))
- .arg(graph_.dst_port);
- setWindowTitle(dlg_title);
-
- QVector<double> rel_time, seq;
- double rel_time_min = QCPRange::maxRange, rel_time_max = QCPRange::minRange;
- double seq_min = QCPRange::maxRange, seq_max = QCPRange::minRange;
- for (struct segment *seg = graph_.segments; seg != NULL; seg = seg->next) {
- if (!compareHeaders(seg)) {
- continue;
- }
-
- double rt_val = seg->rel_secs + seg->rel_usecs / 1000000.0;
-
- rel_time.append(rt_val);
- if (rel_time_min > rt_val) rel_time_min = rt_val;
- if (rel_time_max < rt_val) rel_time_max = rt_val;
-
- seq.append(seg->th_seq);
- if (seq_min > seg->th_seq) seq_min = seg->th_seq;
- if (seq_max < seg->th_seq) seq_max = seg->th_seq;
-
- segment_map_.insertMulti(rt_val, seg);
- }
QCustomPlot *sp = ui->streamPlot;
+ title_ = new QCPPlotTitle(sp);
+ tracer_ = new QCPItemTracer(sp);
sp->plotLayout()->insertRow(0);
- sp->plotLayout()->addElement(0, 0, new QCPPlotTitle(sp, dlg_title));
- sp->addGraph();
- sp->graph(0)->setData(rel_time, seq);
+ sp->plotLayout()->addElement(0, 0, title_);
+ sp->addGraph(); // 0 - All: Selectable segments
+ sp->addGraph(sp->xAxis, sp->yAxis2); // 1 - Throughput: Moving average
+ sp->addItem(tracer_);
+
+ // Fills the graph
+ ui->graphTypeComboBox->setCurrentIndex(ui->graphTypeComboBox->findData(qVariantFromValue(graph_type)));
+
sp->setInteractions(
QCP::iRangeDrag |
QCP::iRangeZoom
);
sp->setMouseTracking(true);
- // True Stevens-style graphs don't have lines but I like them - gcc
- sp->graph(0)->setPen(QPen(QBrush(tango_sky_blue_5), 0.25));
- sp->graph(0)->setLineStyle(QCPGraph::lsStepLeft);
+ sp->graph(0)->setPen(QPen(QBrush(graph_color_1), 0.25));
sp->graph(0)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssDisc, 5));
sp->xAxis->setLabel(tr("Time (s)"));
- double range_pad = (rel_time_max - rel_time_min) * 0.05;
- data_range_.setLeft(rel_time_min - range_pad);
- data_range_.setRight(rel_time_max + range_pad);
- sp->xAxis->setRange(data_range_.left(), data_range_.right());
- sp->yAxis->setLabel(tr("Sequence number (B)"));
- range_pad = (seq_max - seq_min) * 0.05;
- data_range_.setBottom(seq_min - range_pad);
- data_range_.setTop(seq_max + range_pad);
- sp->yAxis->setRange(data_range_.bottom(), data_range_.top());
+ sp->yAxis->setTickLabelColor(QColor(graph_color_1));
- tracer_ = new QCPItemTracer(sp);
tracer_->setVisible(false);
- tracer_->setGraph(sp->graph(0));
- tracer_->setInterpolating(false);
- sp->addItem(tracer_);
toggleTracerStyle(true);
- // XXX - QCustomPlot doesn't seem to draw any sort of focus indicator.
+ // XXX QCustomPlot doesn't seem to draw any sort of focus indicator.
sp->setFocus();
QPushButton *save_bt = ui->buttonBox->button(QDialogButtonBox::Save);
@@ -130,7 +107,10 @@ TCPStreamDialog::TCPStreamDialog(QWidget *parent, capture_file *cf, tcp_graph_ty
connect(sp, SIGNAL(mousePress(QMouseEvent*)), this, SLOT(graphClicked(QMouseEvent*)));
connect(sp, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(mouseMoved(QMouseEvent*)));
+ connect(sp->yAxis, SIGNAL(rangeChanged(QCPRange)), this, SLOT(translateYRange(QCPRange)));
disconnect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
+
+ mouseMoved(NULL);
}
TCPStreamDialog::~TCPStreamDialog()
@@ -189,9 +169,7 @@ void TCPStreamDialog::keyPressEvent(QKeyEvent *event)
case Qt::Key_ParenRight: // Shifted 0 on U.S. keyboards
case Qt::Key_R:
case Qt::Key_Home:
- sp->xAxis->setRange(data_range_.left(), data_range_.right());
- sp->yAxis->setRange(data_range_.bottom(), data_range_.top());
- sp->replot();
+ resetAxes();
break;
// Alas, there is no Blade Runner-style Qt::Key_Ehance
}
@@ -216,6 +194,177 @@ void TCPStreamDialog::keyPressEvent(QKeyEvent *event)
QDialog::keyPressEvent(event);
}
+void TCPStreamDialog::fillGraph()
+{
+ QCustomPlot *sp = ui->streamPlot;
+
+ if (sp->graphCount() < 1) return;
+
+ segment_map_.clear();
+ graph_segment_list_free(&graph_);
+ graph_segment_list_get(cap_file_, &graph_, FALSE);
+
+ for (struct segment *seg = graph_.segments; seg != NULL; seg = seg->next) {
+ if (!compareHeaders(seg)) {
+ continue;
+ }
+ double rt_val = seg->rel_secs + seg->rel_usecs / 1000000.0;
+ segment_map_.insertMulti(rt_val, seg);
+ }
+
+ tracer_->setGraph(NULL);
+ // We need at least one graph, so don't bother deleting the first one.
+ for (int i = 0; i < sp->graphCount(); i++) {
+ sp->graph(i)->clearData();
+ sp->graph(i)->setVisible(i == 0 ? true : false);
+ }
+ sp->yAxis2->setVisible(false);
+ sp->yAxis2->setLabel(QString());
+
+ if (!cap_file_) {
+ QString dlg_title = QString(tr("No capture file"));
+ setWindowTitle(dlg_title);
+ title_->setText(dlg_title);
+ sp->setEnabled(false);
+ } else {
+ switch (graph_.type) {
+ case GRAPH_TSEQ_STEVENS:
+ initializeStevens();
+ break;
+ case GRAPH_THROUGHPUT:
+ initializeThroughput();
+ break;
+ default:
+ break;
+ }
+ sp->setEnabled(true);
+ }
+ resetAxes();
+ tracer_->setGraph(sp->graph(0));
+}
+
+void TCPStreamDialog::resetAxes()
+{
+ QCustomPlot *sp = ui->streamPlot;
+
+ y_translate_mul_ = 0.0;
+
+ sp->graph(0)->rescaleAxes(false, true);
+ for (int i = 1; i < sp->graphCount(); i++) {
+ sp->graph(i)->rescaleValueAxis(false, true);
+ }
+
+ double range_pad = (sp->xAxis->range().upper - sp->xAxis->range().lower) * 0.05;
+ sp->xAxis->setRange(sp->xAxis->range().lower - range_pad,
+ sp->xAxis->range().upper + range_pad);
+
+ range_pad = (sp->yAxis->range().upper - sp->yAxis->range().lower) * 0.05;
+ sp->yAxis->setRange(sp->yAxis->range().lower - range_pad,
+ sp->yAxis->range().upper + range_pad);
+
+ range_pad = (sp->yAxis2->range().upper - sp->yAxis2->range().lower) * 0.05;
+ sp->yAxis2->setRange(sp->yAxis2->range().lower - range_pad,
+ sp->yAxis2->range().upper + range_pad);
+
+ y_translate_mul_ = (sp->yAxis2->range().upper - sp->yAxis2->range().lower)
+ / (sp->yAxis->range().upper - sp->yAxis->range().lower);
+
+ sp->replot();
+}
+
+void TCPStreamDialog::initializeStevens()
+{
+ QString dlg_title = QString(tr("TCP Graph ")) + streamDescription();
+ setWindowTitle(dlg_title);
+ title_->setText(dlg_title);
+
+ QCustomPlot *sp = ui->streamPlot;
+ // True Stevens-style graphs don't have lines but I like them - gcc
+ sp->graph(0)->setLineStyle(QCPGraph::lsStepLeft);
+
+ QVector<double> rel_time, seq;
+ for (struct segment *seg = graph_.segments; seg != NULL; seg = seg->next) {
+ if (!compareHeaders(seg)) {
+ continue;
+ }
+
+ double rt_val = seg->rel_secs + seg->rel_usecs / 1000000.0;
+ rel_time.append(rt_val);
+ seq.append(seg->th_seq);
+ }
+ sp->graph(0)->setData(rel_time, seq);
+ sp->yAxis->setLabel(tr("Sequence number (B)"));
+}
+
+void TCPStreamDialog::initializeThroughput()
+{
+ QString dlg_title = QString(tr("Throughput "))
+ + streamDescription()
+ + QString(tr(" (%1 segment MA)")).arg(moving_avg_period_);
+ setWindowTitle(dlg_title);
+ title_->setText(dlg_title);
+
+ QCustomPlot *sp = ui->streamPlot;
+ sp->graph(0)->setLineStyle(QCPGraph::lsNone);
+ sp->graph(1)->setVisible(true);
+ sp->graph(1)->setPen(QPen(QBrush(graph_color_2), 0.5));
+ sp->graph(1)->setLineStyle(QCPGraph::lsLine);
+
+ if (!graph_.segments || !graph_.segments->next) {
+ dlg_title.append(tr(" [not enough data]"));
+ return;
+ }
+
+ QVector<double> rel_time, seg_len, tput;
+ struct segment *oldest_seg = graph_.segments;
+ int i = 1, sum = 0;
+ // Financial charts don't show MA data until a full period has elapsed.
+ // The Rosetta Code MA examples start spitting out values immediately.
+ // For now use not-really-correct initial values just to keep our vector
+ // lengths the same.
+ for (struct segment *seg = graph_.segments->next; seg != NULL; seg = seg->next) {
+ double rt_val = seg->rel_secs + seg->rel_usecs / 1000000.0;
+
+ if (i > moving_avg_period_) {
+ oldest_seg = oldest_seg->next;
+ sum -= oldest_seg->th_seglen;
+ }
+ i++;
+
+ double dtime = rt_val - (oldest_seg->rel_secs + oldest_seg->rel_usecs / 1000000.0);
+ double av_tput;
+ sum += seg->th_seglen;
+ if (dtime > 0.0) {
+ av_tput = sum * 8.0 / dtime;
+ } else {
+ av_tput = 0.0;
+ }
+
+ rel_time.append(rt_val);
+ seg_len.append(seg->th_seglen);
+ tput.append(av_tput);
+ }
+ sp->graph(0)->setData(rel_time, seg_len);
+ sp->graph(1)->setData(rel_time, tput);
+
+ sp->yAxis->setLabel(tr("Segment length (B)"));
+
+ sp->yAxis2->setLabel(tr("Avg througput (bits/s)"));
+ sp->yAxis2->setTickLabelColor(QColor(graph_color_2));
+ sp->yAxis2->setVisible(true);
+}
+
+QString TCPStreamDialog::streamDescription()
+{
+ return QString(tr("%1 %2:%3 %4 %5:%6"))
+ .arg(cf_get_display_name(cap_file_))
+ .arg(ep_address_to_str(&graph_.src_address))
+ .arg(graph_.src_port)
+ .arg(UTF8_RIGHTWARDS_ARROW)
+ .arg(ep_address_to_str(&graph_.dst_address))
+ .arg(graph_.dst_port);
+}
+
bool TCPStreamDialog::compareHeaders(segment *seg)
{
return (compare_headers(&graph_.src_address, &graph_.dst_address,
@@ -265,11 +414,10 @@ void TCPStreamDialog::graphClicked(QMouseEvent *event)
// using a QTimer instead.
void TCPStreamDialog::mouseMoved(QMouseEvent *event)
{
- QRect spr = ui->streamPlot->axisRect()->rect();
struct segment *packet_seg = NULL;
packet_num_ = 0;
- if (spr.contains(event->pos())) {
+ if (event && tracer_->graph() && tracer_->position->axisRect()->rect().contains(event->pos())) {
double ts = tracer_->position->key();
packet_seg = segment_map_.value(ts, NULL);
}
@@ -294,6 +442,16 @@ void TCPStreamDialog::mouseMoved(QMouseEvent *event)
ui->streamPlot->replot();
}
+void TCPStreamDialog::translateYRange(const QCPRange &y_range1)
+{
+ if (y_translate_mul_ <= 0.0) return;
+
+ QCustomPlot *sp = ui->streamPlot;
+
+ sp->yAxis2->setRangeUpper(y_range1.upper * y_translate_mul_);
+ sp->yAxis2->setRangeLower(y_range1.lower * y_translate_mul_);
+}
+
void TCPStreamDialog::on_buttonBox_accepted()
{
QString file_name, extension;
@@ -331,6 +489,19 @@ void TCPStreamDialog::on_buttonBox_accepted()
}
}
+void TCPStreamDialog::on_graphTypeComboBox_currentIndexChanged(int index)
+{
+ if (index < 0) return;
+ graph_.type = ui->graphTypeComboBox->itemData(index).value<tcp_graph_type>();
+ fillGraph();
+}
+
+void TCPStreamDialog::setCaptureFile(capture_file *cf)
+{
+ cap_file_ = cf;
+ fillGraph();
+}
+
/*
* Editor modelines
*
diff --git a/ui/qt/tcp_stream_dialog.h b/ui/qt/tcp_stream_dialog.h
index 129c1b9345..f9b874a9dd 100644
--- a/ui/qt/tcp_stream_dialog.h
+++ b/ui/qt/tcp_stream_dialog.h
@@ -52,6 +52,9 @@ public:
signals:
void goToPacket(int packet_num);
+public slots:
+ void setCaptureFile(capture_file *cf);
+
protected:
void keyPressEvent(QKeyEvent *event);
@@ -60,18 +63,29 @@ private:
capture_file *cap_file_;
QMap<double, struct segment *> segment_map_;
struct tcp_graph graph_;
- QRectF data_range_;
+ QCPPlotTitle *title_;
QCPItemTracer *tracer_;
guint32 packet_num_;
+ double y_translate_mul_;
+ int num_dsegs_;
+ int num_acks_;
+ int num_sack_ranges_;
+ void fillGraph();
+ void resetAxes();
+ void initializeStevens();
+ void initializeThroughput();
+ QString streamDescription();
bool compareHeaders(struct segment *seg);
void toggleTracerStyle(bool force_default = false);
private slots:
void graphClicked(QMouseEvent *event);
void mouseMoved(QMouseEvent *event);
+ void translateYRange(const QCPRange &y_range1);
void on_buttonBox_accepted();
+ void on_graphTypeComboBox_currentIndexChanged(int index);
};
#endif // TCP_STREAM_DIALOG_H
diff --git a/ui/qt/tcp_stream_dialog.ui b/ui/qt/tcp_stream_dialog.ui
index 12a09c5982..fb37550ea3 100644
--- a/ui/qt/tcp_stream_dialog.ui
+++ b/ui/qt/tcp_stream_dialog.ui
@@ -64,13 +64,7 @@
</widget>
</item>
<item>
- <widget class="QComboBox" name="graphTypeComboBox">
- <item>
- <property name="text">
- <string>Time / Sequence (Stevens)</string>
- </property>
- </item>
- </widget>
+ <widget class="QComboBox" name="graphTypeComboBox"/>
</item>
<item>
<spacer name="horizontalSpacer">
diff --git a/ui/tap-tcp-stream.c b/ui/tap-tcp-stream.c
index 4be31f4c4e..dffa6cd15d 100644
--- a/ui/tap-tcp-stream.c
+++ b/ui/tap-tcp-stream.c
@@ -176,6 +176,44 @@ compare_headers(address *saddr1, address *daddr1, guint16 sport1, guint16 dport1
}
}
+int
+get_num_dsegs(struct tcp_graph *tg)
+{
+ int count;
+ struct segment *tmp;
+
+ for (tmp=tg->segments, count=0; tmp; tmp=tmp->next) {
+ if (compare_headers(&tg->src_address, &tg->dst_address,
+ tg->src_port, tg->dst_port,
+ &tmp->ip_src, &tmp->ip_dst,
+ tmp->th_sport, tmp->th_dport,
+ COMPARE_CURR_DIR)) {
+ count++;
+ }
+ }
+ return count;
+}
+
+int
+get_num_acks(struct tcp_graph *tg, int *num_sack_ranges)
+{
+ int count;
+ struct segment *tmp;
+
+ for (tmp = tg->segments, count=0; tmp; tmp = tmp->next) {
+ if (!compare_headers(&tg->src_address, &tg->dst_address,
+ tg->src_port, tg->dst_port,
+ &tmp->ip_src, &tmp->ip_dst,
+ tmp->th_sport, tmp->th_dport,
+ COMPARE_CURR_DIR)) {
+ count++;
+ *num_sack_ranges += tmp->num_sack_ranges;
+ }
+ }
+ return count;
+}
+
+
typedef struct _th_t {
int num_hdrs;
diff --git a/ui/tap-tcp-stream.h b/ui/tap-tcp-stream.h
index 71f9a5c0f6..551b09af15 100644
--- a/ui/tap-tcp-stream.h
+++ b/ui/tap-tcp-stream.h
@@ -84,8 +84,12 @@ void graph_segment_list_free(struct tcp_graph * );
int compare_headers(address *saddr1, address *daddr1, guint16 sport1, guint16 dport1, const address *saddr2, const address *daddr2, guint16 sport2, guint16 dport2, int dir);
+int get_num_dsegs(struct tcp_graph * );
+int get_num_acks(struct tcp_graph *, int * );
+
struct tcpheader *select_tcpip_session(capture_file *, struct segment * );
+
#ifdef __cplusplus
}
#endif /* __cplusplus */