diff options
Diffstat (limited to 'ui/qt/tcp_stream_dialog.cpp')
-rw-r--r-- | ui/qt/tcp_stream_dialog.cpp | 162 |
1 files changed, 145 insertions, 17 deletions
diff --git a/ui/qt/tcp_stream_dialog.cpp b/ui/qt/tcp_stream_dialog.cpp index 9bde33e478..d7b4a06b06 100644 --- a/ui/qt/tcp_stream_dialog.cpp +++ b/ui/qt/tcp_stream_dialog.cpp @@ -98,9 +98,11 @@ TCPStreamDialog::TCPStreamDialog(QWidget *parent, capture_file *cf, tcp_graph_ty packet_num_(0), mouse_drags_(true), rubber_band_(NULL), + graph_update_timer_(NULL), num_dsegs_(-1), num_acks_(-1), - num_sack_ranges_(-1) + num_sack_ranges_(-1), + ma_window_size_(1.0) { struct segment current; int graph_idx = -1; @@ -184,11 +186,21 @@ TCPStreamDialog::TCPStreamDialog(QWidget *parent, capture_file *cf, tcp_graph_ty graph_.stream = header->th_stream; findStream(); + showWidgetsForGraphType(); + ui->streamNumberSpinBox->blockSignals(true); ui->streamNumberSpinBox->setMaximum(get_tcp_stream_count() - 1); ui->streamNumberSpinBox->setValue(graph_.stream); ui->streamNumberSpinBox->blockSignals(false); +#ifdef MA_1_SECOND + ui->maWindowSizeSpinBox->blockSignals(true); + ui->maWindowSizeSpinBox->setDecimals(6); + ui->maWindowSizeSpinBox->setMinimum(0.000001); + ui->maWindowSizeSpinBox->setValue(ma_window_size_); + ui->maWindowSizeSpinBox->blockSignals(false); +#endif + QCustomPlot *sp = ui->streamPlot; QCPPlotTitle *file_title = new QCPPlotTitle(sp, cf_get_display_name(cap_file_)); file_title->setFont(sp->xAxis->labelFont()); @@ -202,7 +214,7 @@ TCPStreamDialog::TCPStreamDialog(QWidget *parent, capture_file *cf, tcp_graph_ty base_graph_->setPen(QPen(QBrush(graph_color_1), 0.25)); tput_graph_ = sp->addGraph(sp->xAxis, sp->yAxis2); // Throughput: Moving average tput_graph_->setPen(QPen(QBrush(graph_color_2), 0.5)); - tput_graph_->setLineStyle(QCPGraph::lsLine); + tput_graph_->setLineStyle(QCPGraph::lsStepLeft); seg_graph_ = sp->addGraph(); // tcptrace: fwd segments seg_graph_->setErrorType(QCPGraph::etValue); seg_graph_->setLineStyle(QCPGraph::lsNone); @@ -264,6 +276,17 @@ void TCPStreamDialog::keyPressEvent(QKeyEvent *event) { int pan_pixels = event->modifiers() & Qt::ShiftModifier ? 1 : 10; + if ((event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) && + ui->maWindowSizeSpinBox->hasFocus()) { + + // If user was editing maWindowSize, then just use the new value + // clear the focus and accept the event + // (don't propagate to default close button) + ui->maWindowSizeSpinBox->clearFocus(); + event->accept(); + return; + } + // XXX - This differs from the main window but matches other applications (e.g. Mozilla and Safari) switch(event->key()) { case Qt::Key_Minus: @@ -379,7 +402,7 @@ void TCPStreamDialog::findStream() connect(sp, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(mouseMoved(QMouseEvent*))); } -void TCPStreamDialog::fillGraph() +void TCPStreamDialog::fillGraph(bool reset_axes, bool set_focus) { QCustomPlot *sp = ui->streamPlot; @@ -424,17 +447,25 @@ void TCPStreamDialog::fillGraph() time_stamp_map_.clear(); for (struct segment *seg = graph_.segments; seg != NULL; seg = seg->next) { + // NOTE - adding both forward and reverse packets to time_stamp_map_ + // so that both data and acks are selectable + // (this is important especially in selecting particular SACK pkts) if (!compareHeaders(seg)) { bytes_rev += seg->th_seglen; pkts_rev++; - continue; + } else { + bytes_fwd += seg->th_seglen; + pkts_fwd++; } - bytes_fwd += seg->th_seglen; - pkts_fwd++; double ts = seg->rel_secs + seg->rel_usecs / 1000000.0; if (first) { if (ts_origin_conn_) ts_offset_ = ts; - if (seq_origin_zero_) seq_offset_ = seg->th_seq; + if (seq_origin_zero_) { + if (compareHeaders(seg)) + seq_offset_ = seg->th_seq; + else + seq_offset_ = seg->th_ack; + } first = false; } time_stamp_map_.insertMulti(ts - ts_offset_, seg); @@ -469,11 +500,37 @@ void TCPStreamDialog::fillGraph() .arg(gchar_free_to_qstring(format_size(pkts_rev, format_size_unit_none|format_size_prefix_si))) .arg(gchar_free_to_qstring(format_size(bytes_rev, format_size_unit_bytes|format_size_prefix_si))); mouseMoved(NULL); - resetAxes(); + if (reset_axes) + resetAxes(); + else + sp->replot(); tracer_->setGraph(base_graph_); // XXX QCustomPlot doesn't seem to draw any sort of focus indicator. - sp->setFocus(); + if (set_focus) + sp->setFocus(); +} + +void TCPStreamDialog::showWidgetsForGraphType() +{ +#ifdef MA_1_SECOND + if (graph_.type == GRAPH_THROUGHPUT) { + ui->maWindowSizeLabel->setVisible(true); + ui->maWindowSizeSpinBox->setVisible(true); + } else { + ui->maWindowSizeLabel->setVisible(false); + ui->maWindowSizeSpinBox->setVisible(false); + } +#else + ui->maWindowSizeLabel->setVisible(false); + ui->maWindowSizeSpinBox->setVisible(false); +#endif + + if (graph_.type == GRAPH_TSEQ_TCPTRACE) { + ui->selectAcksCheckBox->setVisible(true); + } else { + ui->selectAcksCheckBox->setVisible(false); + } } void TCPStreamDialog::zoomAxes(bool in) @@ -597,6 +654,8 @@ void TCPStreamDialog::fillTcptrace() setWindowTitle(dlg_title); title_->setText(dlg_title); + bool allow_ack_select = ui->selectAcksCheckBox->isChecked(); + QCustomPlot *sp = ui->streamPlot; sp->yAxis->setLabel(sequence_number_label_); @@ -606,13 +665,14 @@ void TCPStreamDialog::fillTcptrace() ack_graph_->setVisible(true); rwin_graph_->setVisible(true); - QVector<double> seq_time, seq, sb_time, sb_center, sb_span, ackrwin_time, ack, rwin; + QVector<double> pkt_time, pkt_seqnums, sb_time, sb_center, sb_span, ackrwin_time, ack, rwin; for (struct segment *seg = graph_.segments; seg != NULL; seg = seg->next) { double ts = (seg->rel_secs + seg->rel_usecs / 1000000.0) - ts_offset_; if (compareHeaders(seg)) { + // Add forward direction to base_graph_ (to select data packets) // Forward direction: seq + data - seq_time.append(ts); - seq.append(seg->th_seq - seq_offset_); + pkt_time.append(ts); + pkt_seqnums.append(seg->th_seq - seq_offset_); // QCP doesn't have a segment graph type. For now, fake // it with error bars. @@ -629,12 +689,18 @@ void TCPStreamDialog::fillTcptrace() continue; } double ackno = seg->th_ack - seq_offset_; + if (allow_ack_select) { + // Add reverse direction to base_graph_ (to select ACK packets) + pkt_time.append(ts); + pkt_seqnums.append(ackno); + } + // Also add reverse packets to the ack_graph_ ackrwin_time.append(ts); ack.append(ackno); rwin.append(ackno + seg->th_win); } } - base_graph_->setData(seq_time, seq); + base_graph_->setData(pkt_time, pkt_seqnums); seg_graph_->setDataValueError(sb_time, sb_center, sb_span); ack_graph_->setData(ackrwin_time, ack); rwin_graph_->setData(ackrwin_time, rwin); @@ -644,7 +710,7 @@ void TCPStreamDialog::fillThroughput() { QString dlg_title = QString(tr("Throughput")) + streamDescription(); #ifdef MA_1_SECOND - dlg_title.append(tr(" (1s MA)")); + dlg_title.append(tr(" (MA)")); #else dlg_title.append(QString(tr(" (%1 Segment MA)")).arg(moving_avg_period_)); #endif @@ -660,7 +726,11 @@ void TCPStreamDialog::fillThroughput() tput_graph_->setVisible(true); +#ifdef MA_1_SECOND + if (!graph_.segments) { +#else if (!graph_.segments || !graph_.segments->next) { +#endif dlg_title.append(tr(" [not enough data]")); return; } @@ -669,10 +739,20 @@ void TCPStreamDialog::fillThroughput() int oldest = 0; guint64 sum = 0; // Financial charts don't show MA data until a full period has elapsed. + // [ NOTE - this is because they assume that there's old data that they + // don't have access to - but in our case we know that there's NO + // data prior to the first packet in the stream - so it's fine to + // spit out the MA immediately... ] // 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. +#ifdef MA_1_SECOND + // NOTE that for the time-based MA case, you certainly can start with the + // first segment! + for (struct segment *seg = graph_.segments; seg != NULL; seg = seg->next) { +#else for (struct segment *seg = graph_.segments->next; seg != NULL; seg = seg->next) { +#endif if (!compareHeaders(seg)) { continue; } @@ -683,8 +763,12 @@ void TCPStreamDialog::fillThroughput() seg_len.append(seg->th_seglen); #ifdef MA_1_SECOND - while (ts - rel_time[oldest] > 1.0 && oldest < rel_time.size()) { + while (ts - rel_time[oldest] > ma_window_size_ && oldest < rel_time.size()) { sum -= seg_len[oldest]; + // append points where a packet LEAVES the MA window + // (as well as, below, where they ENTER the MA window) + tput.append(sum * 8.0 / ma_window_size_); + tput_time.append(rel_time[oldest] + ma_window_size_); oldest++; } #else @@ -694,14 +778,19 @@ void TCPStreamDialog::fillThroughput() } #endif - double dtime = ts - rel_time[oldest]; double av_tput; sum += seg->th_seglen; +#ifdef MA_1_SECOND + // for time-based MA, delta_t is constant + av_tput = sum * 8.0 / ma_window_size_; +#else + double dtime = ts - rel_time[oldest]; if (dtime > 0.0) { av_tput = sum * 8.0 / dtime; } else { av_tput = 0.0; } +#endif // Add a data point only if our time window has advanced. Otherwise // update the most recent point. (We might want to show a warning @@ -1087,6 +1176,7 @@ void TCPStreamDialog::on_graphTypeComboBox_currentIndexChanged(int index) { if (index < 0) return; graph_.type = static_cast<tcp_graph_type>(ui->graphTypeComboBox->itemData(index).toInt()); + showWidgetsForGraphType(); fillGraph(); } @@ -1102,6 +1192,21 @@ void TCPStreamDialog::setCaptureFile(capture_file *cf) } } +void TCPStreamDialog::updateGraph() +{ + + // graph_update_timer_ is created only when there's a pending + // parameter change, and deleted when an update consumes that change. + // Therefore lack of an update timer means nothing to update. + if (graph_update_timer_) { + if (graph_update_timer_->isActive()) + graph_update_timer_->stop(); + delete graph_update_timer_; + graph_update_timer_ = NULL; + fillGraph(/*reset_axes=*/false, /*set_focus=*/false); + } +} + void TCPStreamDialog::on_streamNumberSpinBox_valueChanged(int new_stream) { if (new_stream >= 0 && new_stream < int(get_tcp_stream_count())) { @@ -1109,10 +1214,33 @@ void TCPStreamDialog::on_streamNumberSpinBox_valueChanged(int new_stream) clear_address(&graph_.src_address); clear_address(&graph_.dst_address); findStream(); - fillGraph(); + fillGraph(/*reset_axes=*/true, /*set_focus=*/false); + } +} + +void TCPStreamDialog::on_maWindowSizeSpinBox_valueChanged(double new_ma_size) +{ + if (new_ma_size > 0.0) { + ma_window_size_ = new_ma_size; + if (!graph_update_timer_) { + graph_update_timer_ = new QTimer(this); + graph_update_timer_->setSingleShot(true); + connect(graph_update_timer_, SIGNAL(timeout()), this, SLOT(updateGraph())); + } + graph_update_timer_->start(1000); } } +void TCPStreamDialog::on_maWindowSizeSpinBox_editingFinished() +{ + updateGraph(); +} + +void TCPStreamDialog::on_selectAcksCheckBox_stateChanged(int /* state */) +{ + fillGraph(/*reset_axes=*/false, /*set_focus=*/true); +} + void TCPStreamDialog::on_otherDirectionButton_clicked() { on_actionSwitchDirection_triggered(); |