TCP: Overriding of the automatic SEQ Analysis

This commit is contained in:
Eugène Adell 2022-11-01 10:01:35 +00:00 committed by AndersBroman
parent 891716800b
commit 6759377b93
18 changed files with 377 additions and 23 deletions

View File

@ -95,6 +95,18 @@ static gboolean tcp_check_checksum = FALSE;
WindowScaling_14
};
/*
* Analysis overriding values to be used when not satisfied by the automatic
* result. (Accessed through preferences but not stored as a preference)
*/
enum override_analysis_value {
OverrideAnalysis_0=0,
OverrideAnalysis_1,
OverrideAnalysis_2,
OverrideAnalysis_3,
OverrideAnalysis_4
};
/*
* Using enum instead of boolean make API easier
*/
@ -122,6 +134,8 @@ static const value_string mp_tcprst_reasons[] = {
static gint tcp_default_window_scaling = (gint)WindowScaling_NotKnown;
static gint tcp_default_override_analysis = (gint)OverrideAnalysis_0;
static int proto_tcp = -1;
static int proto_ip = -1;
static int proto_icmp = -1;
@ -2108,7 +2122,7 @@ tcp_analyze_get_acked_struct(guint32 frame, guint32 seq, guint32 ack, gboolean c
* Guide: docbook/wsug_src/WSUG_chapter_advanced.adoc
*/
static void
tcp_analyze_sequence_number(packet_info *pinfo, guint32 seq, guint32 ack, guint32 seglen, guint16 flags, guint32 window, struct tcp_analysis *tcpd)
tcp_analyze_sequence_number(packet_info *pinfo, guint32 seq, guint32 ack, guint32 seglen, guint16 flags, guint32 window, struct tcp_analysis *tcpd, struct tcp_per_packet_data_t *tcppd)
{
tcp_unacked_t *ual=NULL;
tcp_unacked_t *prevual=NULL;
@ -2534,6 +2548,53 @@ finished_fwd:
finished_checking_retransmission_type:
/* Override the TCP sequence analysis with the value given
* manually by the user. This only applies to flagged packets.
*/
if(tcppd && tcpd->ta &&
(tcppd->tcp_snd_manual_analysis>0) &&
(tcpd->ta->flags & TCP_A_RETRANSMISSION ||
tcpd->ta->flags & TCP_A_OUT_OF_ORDER ||
tcpd->ta->flags & TCP_A_FAST_RETRANSMISSION ||
tcpd->ta->flags & TCP_A_SPURIOUS_RETRANSMISSION)) {
/* clean flags set during the automatic analysis */
tcpd->ta->flags &= ~(TCP_A_RETRANSMISSION|
TCP_A_OUT_OF_ORDER|
TCP_A_FAST_RETRANSMISSION|
TCP_A_SPURIOUS_RETRANSMISSION);
/* set the corresponding flag chosen by the user */
switch(tcppd->tcp_snd_manual_analysis) {
case 0:
/* the user asked for an empty overriding, which
* means removing any previous value, thus restoring
* the automatic analysis.
*/
break;
case 1:
tcpd->ta->flags|=TCP_A_OUT_OF_ORDER;
break;
case 2:
tcpd->ta->flags|=TCP_A_RETRANSMISSION;
break;
case 3:
tcpd->ta->flags|=TCP_A_FAST_RETRANSMISSION;
break;
case 4:
tcpd->ta->flags|=TCP_A_SPURIOUS_RETRANSMISSION;
break;
default:
/* there is no expected default case */
break;
}
}
nextseq = seq+seglen;
if ((seglen || flags&(TH_SYN|TH_FIN)) && tcpd->fwd->tcp_analyze_seq_info->segment_count < TCP_MAX_UNACKED_SEGMENTS) {
/* Add this new sequence number to the fwd list. But only if there
@ -7695,6 +7756,12 @@ dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
tcp_calculate_timestamps(pinfo, tcpd, tcppd);
}
/* is there any manual analysis waiting ? */
if(pinfo->fd->tcp_snd_manual_analysis > 0) {
tcppd = (struct tcp_per_packet_data_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_tcp, pinfo->curr_layer_num);
tcppd->tcp_snd_manual_analysis = pinfo->fd->tcp_snd_manual_analysis;
}
/*
* If we've been handed an IP fragment, we don't know how big the TCP
* segment is, so don't do anything that requires that we know that.
@ -7731,7 +7798,7 @@ dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
/* handle TCP seq# analysis parse all new segments we see */
if(tcp_analyze_seq) {
if(!(pinfo->fd->visited)) {
tcp_analyze_sequence_number(pinfo, tcph->th_seq, tcph->th_ack, tcph->th_seglen, tcph->th_flags, tcph->th_win, tcpd);
tcp_analyze_sequence_number(pinfo, tcph->th_seq, tcph->th_ack, tcph->th_seglen, tcph->th_flags, tcph->th_win, tcpd, tcppd);
}
if(tcpd && tcp_relative_seq) {
(tcph->th_seq) -= tcpd->fwd->base_seq;
@ -9351,6 +9418,15 @@ proto_register_tcp(void)
{NULL, NULL, -1}
};
static const enum_val_t override_analysis_vals[] = {
{"0", "0 (none)", OverrideAnalysis_0},
{"1", "1 (Out-of-Order)", OverrideAnalysis_1},
{"2", "2 (Retransmission)", OverrideAnalysis_2},
{"3", "3 (Fast Retransmission)", OverrideAnalysis_3},
{"4", "4 (Spurious Retransmission)",OverrideAnalysis_4},
{NULL, NULL, -1}
};
static ei_register_info ei[] = {
{ &ei_tcp_opt_len_invalid, { "tcp.option.len.invalid", PI_SEQUENCE, PI_NOTE, "Invalid length for option", EXPFILL }},
{ &ei_tcp_analysis_retransmission, { "tcp.analysis.retransmission", PI_SEQUENCE, PI_NOTE, "This frame is a (suspected) retransmission", EXPFILL }},
@ -9556,6 +9632,12 @@ proto_register_tcp(void)
"Make the TCP dissector use relative sequence numbers instead of absolute ones. "
"To use this option you must also enable \"Analyze TCP sequence numbers\". ",
&tcp_relative_seq);
prefs_register_custom_preference_TCP_Analysis(tcp_module, "default_override_analysis",
"Force interpretation to selected packet(s)",
"Override the default analysis with this value for the selected packet",
&tcp_default_override_analysis, override_analysis_vals, FALSE);
prefs_register_enum_preference(tcp_module, "default_window_scaling",
"Scaling factor to use when not available from capture",
"Make the TCP dissector use this scaling factor for streams where the signalled scaling factor "

View File

@ -506,6 +506,7 @@ struct tcp_analysis {
*/
struct tcp_per_packet_data_t {
nstime_t ts_del;
guint8 tcp_snd_manual_analysis;
};
/* Structure that keeps per packet data. Some operations are cpu-intensive and are

View File

@ -167,6 +167,7 @@ frame_data_init(frame_data *fdata, guint32 num, const wtap_rec *rec,
fdata->ref_time = 0;
fdata->ignored = 0;
fdata->has_ts = (rec->presence_flags & WTAP_HAS_TS) ? 1 : 0;
fdata->tcp_snd_manual_analysis = 0;
switch (rec->rec_type) {
case REC_TYPE_PACKET:

View File

@ -91,6 +91,7 @@ typedef struct _frame_data {
nstime_t shift_offset; /**< How much the abs_tm of the frame is shifted */
guint32 frame_ref_num; /**< Previous reference frame (0 if this is one) */
guint32 prev_dis_num; /**< Previous displayed frame (0 if first one) */
guint8 tcp_snd_manual_analysis; /**< TCP SEQ Analysis Overriding, 0 = none, 1 = OOO, 2 = RET , 3 = Fast RET, 4 = Spurious RET */
} frame_data;
DIAG_ON_PEDANTIC

View File

@ -102,6 +102,11 @@ struct pref_custom_cbs {
#define PREF_DECODE_AS_RANGE (1u << 13) /* use and not as a generic protocol preference */
#define PREF_OPEN_FILENAME (1u << 14)
#define PREF_PASSWORD (1u << 15) /* like string, but never saved to prefs file */
/**
* Dedicated to TCP PROTOCOL for handling manual SEQ interpretation,
* and allow users manage the sender traffic ambiguities
*/
#define PREF_PROTO_TCP_SNDAMB_ENUM (1u << 16)
typedef enum {
GUI_ALL,

View File

@ -354,6 +354,9 @@ free_pref(gpointer data, gpointer user_data _U_)
pref->stashed_val.boolval = TRUE;
pref->custom_cbs.free_cb(pref);
break;
/* non-generic preferences */
case PREF_PROTO_TCP_SNDAMB_ENUM:
break;
}
g_free(pref);
@ -1884,6 +1887,28 @@ prefs_register_custom_preference(module_t *module, const char *name,
*/
}
/*
* Register a dedicated TCP preference for SEQ analysis overriding.
* We are reusing the data structure from enum preference, as they are
* similar in practice.
*/
void
prefs_register_custom_preference_TCP_Analysis(module_t *module, const char *name,
const char *title, const char *description,
gint *var, const enum_val_t *enumvals,
gboolean radio_buttons)
{
pref_t *preference;
preference = register_preference(module, name, title, description,
PREF_PROTO_TCP_SNDAMB_ENUM);
preference->varp.enump = var;
preference->default_val.enumval = *var;
preference->info.enum_info.enumvals = enumvals;
preference->info.enum_info.radio_buttons = radio_buttons;
}
/*
* Register a (internal) "Decode As" preference with a ranged value.
*/
@ -2023,6 +2048,7 @@ pref_stash(pref_t *pref, gpointer unused _U_)
break;
case PREF_ENUM:
case PREF_PROTO_TCP_SNDAMB_ENUM:
pref->stashed_val.enumval = *pref->varp.enump;
break;
@ -2112,6 +2138,15 @@ pref_unstash(pref_t *pref, gpointer unstash_data_p)
}
break;
case PREF_PROTO_TCP_SNDAMB_ENUM:
/*if (*pref->varp.enump != pref->stashed_val.enumval) {
unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
//unstash_data->module->prefs_changed_flags = 1;
*pref->varp.enump = pref->stashed_val.enumval;
}*/
unstash_data->module->prefs_changed_flags = 1;
break;
case PREF_STRING:
case PREF_SAVE_FILENAME:
case PREF_OPEN_FILENAME:
@ -2216,6 +2251,7 @@ reset_stashed_pref(pref_t *pref) {
break;
case PREF_ENUM:
case PREF_PROTO_TCP_SNDAMB_ENUM:
pref->stashed_val.enumval = pref->default_val.enumval;
break;
@ -2262,6 +2298,7 @@ pref_clean_stash(pref_t *pref, gpointer unused _U_)
break;
case PREF_ENUM:
case PREF_PROTO_TCP_SNDAMB_ENUM:
break;
case PREF_STRING:
@ -4257,6 +4294,7 @@ reset_pref(pref_t *pref)
break;
case PREF_ENUM:
case PREF_PROTO_TCP_SNDAMB_ENUM:
/*
* For now, we save the "description" value, so that if we
* save the preferences older versions of Wireshark can at
@ -6037,6 +6075,7 @@ set_pref(gchar *pref_name, const gchar *value, void *private_data _U_,
break;
case PREF_ENUM:
case PREF_PROTO_TCP_SNDAMB_ENUM:
/* XXX - give an error if it doesn't match? */
enum_val = find_val_for_string(value, pref->info.enum_info.enumvals,
*pref->varp.enump);
@ -6197,6 +6236,7 @@ prefs_pref_type_name(pref_t *pref)
break;
case PREF_ENUM:
case PREF_PROTO_TCP_SNDAMB_ENUM:
type_name = "Choice";
break;
@ -6332,6 +6372,7 @@ prefs_pref_type_description(pref_t *pref)
break;
case PREF_ENUM:
case PREF_PROTO_TCP_SNDAMB_ENUM:
{
const enum_val_t *enum_valp = pref->info.enum_info.enumvals;
GString *enum_str = g_string_new("One of: ");
@ -6433,6 +6474,7 @@ prefs_pref_is_default(pref_t *pref)
break;
case PREF_ENUM:
case PREF_PROTO_TCP_SNDAMB_ENUM:
if (pref->default_val.enumval == *pref->varp.enump)
return TRUE;
break;
@ -6538,6 +6580,7 @@ prefs_pref_to_str(pref_t *pref, pref_source_t source) {
return g_strdup((*(gboolean *) valp) ? "TRUE" : "FALSE");
case PREF_ENUM:
case PREF_PROTO_TCP_SNDAMB_ENUM:
{
gint pref_enumval = *(gint *) valp;
/*

View File

@ -776,6 +776,30 @@ WS_DLL_PUBLIC void prefs_register_password_preference(module_t *module, const ch
WS_DLL_PUBLIC void prefs_register_obsolete_preference(module_t *module,
const char *name);
/**
* Register a preference with an enumerated value.
* @param module the preferences module returned by prefs_register_protocol() or
* prefs_register_protocol_subtree()
* @param name the preference's identifier. This is appended to the name of the
* protocol, with a "." between them, to create a unique identifier.
* The identifier should not include the protocol name, as the name in
* the preference file will already have it. Make sure that
* only lower-case ASCII letters, numbers, underscores and
* dots appear in the preference name.
* @param title Field's title in the preferences dialog
* @param description description to include in the preferences file
* and shown as tooltip in the GUI, or NULL
* @param var pointer to the storage location that is updated when the
* field is changed in the preference dialog box
* @param enumvals a null-terminated array of enum_val_t structures
* @param radio_buttons TRUE if the field is to be displayed in the
* preferences dialog as a set of radio buttons,
* FALSE if it is to be displayed as an option menu
*/
WS_DLL_PUBLIC void prefs_register_custom_preference_TCP_Analysis(module_t *module, const char *name,
const char *title, const char *description, gint *var,
const enum_val_t *enumvals, gboolean radio_buttons);
/**
* Mark a preference that affects fields change. This works for bool, enum,
* int, string (containing filename), range preferences. UAT is not included,

View File

@ -2856,11 +2856,3 @@ void LograyMainWindow::setMwFileName(QString fileName)
mwFileName_ = fileName;
return;
}
frame_data * LograyMainWindow::frameDataForRow(int row) const
{
if (packet_list_)
return packet_list_->getFDataForRow(row);
return Q_NULLPTR;
}

View File

@ -124,8 +124,6 @@ public:
QString getMwFileName();
void setMwFileName(QString fileName);
frame_data * frameDataForRow(int row) const;
protected:
virtual bool eventFilter(QObject *obj, QEvent *event);
virtual bool event(QEvent *event);

View File

@ -47,6 +47,14 @@ QList<int> MainWindow::selectedRows(bool useFrameNum)
return QList<int>();
}
frame_data* MainWindow::frameDataForRow(int row) const
{
if (packet_list_)
return packet_list_->getFDataForRow(row);
return Q_NULLPTR;
}
void MainWindow::insertColumn(QString name, QString abbrev, gint pos)
{
gint colnr = 0;

View File

@ -12,6 +12,11 @@
#include <epan/prefs.h>
#include <epan/stat_groups.h>
#include <epan/frame_data.h>
// frame_data also available with this include in the original wireshark_main_window code
//#include "follow_stream_dialog.h"
#include "filter_action.h"
@ -40,6 +45,7 @@ public:
QList<int> selectedRows(bool useFrameNum = false);
void insertColumn(QString name, QString abbrev, gint pos = -1);
void gotoFrame(int packet_num);
frame_data* frameDataForRow(int) const;
QString getFilter();
MainStatusBar *statusBar();

View File

@ -172,6 +172,16 @@ void RelatedPacketDelegate::paint(QPainter *painter, const QStyleOptionViewItem
other_pen.setStyle(Qt::DashLine);
painter->setPen(other_pen);
}
// analysis overriding mark (three horizontal lines)
if(fd->tcp_snd_manual_analysis) {
int wbound = (en_w - 1) / 2;
painter->drawLine(-wbound, 1, wbound, 1);
painter->drawLine(-wbound, height / 2, wbound, height / 2);
painter->drawLine(-wbound, height - 2, wbound, height - 2);
}
painter->drawLine(0, 0, 0, height);
painter->restore();
break;
@ -184,6 +194,18 @@ void RelatedPacketDelegate::paint(QPainter *painter, const QStyleOptionViewItem
QPoint(0, 0)
};
painter->drawPolyline(end_line, 3);
/* analysis overriding on the last packet of the conversation,
* we mark it with an additional horizontal line only.
* See issue 10725 for example.
*/
// analysis overriding mark (three horizontal lines)
if(fd->tcp_snd_manual_analysis) {
int wbound = (en_w - 1) / 2;
painter->drawLine(-wbound, 1, wbound, 1);
painter->drawLine(-wbound, height / 2, wbound, height / 2);
}
break;
}
default:

View File

@ -14,6 +14,7 @@
#include <ui/qt/utils/qt_ui_utils.h>
#include "uat_dialog.h"
#include "main_application.h"
#include "ui/qt/main_window.h"
#include <ui/qt/utils/variant_pointer.h>
@ -28,6 +29,7 @@
#include <QHBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QMainWindow>
#include <QPushButton>
#include <QRadioButton>
#include <QScrollBar>
@ -240,6 +242,50 @@ pref_show(pref_t *pref, gpointer user_data)
// color picker similar to the Font and Colors prefs.
break;
}
case PREF_PROTO_TCP_SNDAMB_ENUM:
{
const enum_val_t *ev;
ev = prefs_get_enumvals(pref);
if (!ev || !ev->description)
return 0;
if (prefs_get_enum_radiobuttons(pref)) {
QLabel *label = new QLabel(prefs_get_title(pref));
label->setToolTip(tooltip);
vb->addWidget(label);
QButtonGroup *enum_bg = new QButtonGroup(vb);
while (ev->description) {
QRadioButton *enum_rb = new QRadioButton(title_to_shortcut(ev->description));
enum_rb->setToolTip(tooltip);
QStyleOption style_opt;
enum_rb->setProperty(pref_prop_, VariantPointer<pref_t>::asQVariant(pref));
enum_rb->setStyleSheet(QString(
"QRadioButton {"
" margin-left: %1px;"
"}"
)
.arg(enum_rb->style()->subElementRect(QStyle::SE_CheckBoxContents, &style_opt).left()));
enum_bg->addButton(enum_rb, ev->value);
vb->addWidget(enum_rb);
ev++;
}
} else {
QHBoxLayout *hb = new QHBoxLayout();
QComboBox *enum_cb = new QComboBox();
enum_cb->setToolTip(tooltip);
enum_cb->setProperty(pref_prop_, VariantPointer<pref_t>::asQVariant(pref));
for (ev = prefs_get_enumvals(pref); ev && ev->description; ev++) {
enum_cb->addItem(ev->description, QVariant(ev->value));
}
QLabel * lbl = new QLabel(prefs_get_title(pref));
lbl->setToolTip(tooltip);
hb->addWidget(lbl);
hb->addWidget(enum_cb);
hb->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum));
vb->addLayout(hb);
}
break;
}
default:
break;
}
@ -326,6 +372,16 @@ ModulePreferencesScrollArea::ModulePreferencesScrollArea(module_t *module, QWidg
}
}
foreach (QComboBox *combo, findChildren<QComboBox *>()) {
pref_t *pref = VariantPointer<pref_t>::asPtr(combo->property(pref_prop_));
if (!pref) continue;
if (prefs_get_type(pref) == PREF_PROTO_TCP_SNDAMB_ENUM && !prefs_get_enum_radiobuttons(pref)) {
connect(combo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
this, &ModulePreferencesScrollArea::enumComboBoxCurrentIndexChanged_PROTO_TCP);
}
}
foreach (QPushButton *pb, findChildren<QPushButton *>()) {
pref_t *pref = VariantPointer<pref_t>::asPtr(pb->property(pref_prop_));
if (!pref) continue;
@ -413,6 +469,12 @@ void ModulePreferencesScrollArea::updateWidgets()
}
}
}
if (prefs_get_type(pref) == PREF_PROTO_TCP_SNDAMB_ENUM && !prefs_get_enum_radiobuttons(pref)) {
MainWindow* topWidget = dynamic_cast<MainWindow*> (mainApp->mainWindow());
frame_data * fdata = topWidget->frameDataForRow((topWidget->selectedRows()).at(0));
enum_cb->setCurrentIndex(fdata->tcp_snd_manual_analysis);
}
}
}
@ -563,3 +625,32 @@ void ModulePreferencesScrollArea::dirnamePushButtonClicked()
updateWidgets();
}
}
/*
* Dedicated event handling for TCP SEQ Analysis overriding.
*/
void ModulePreferencesScrollArea::enumComboBoxCurrentIndexChanged_PROTO_TCP(int index)
{
QComboBox *enum_cb = qobject_cast<QComboBox*>(sender());
if (!enum_cb) return;
pref_t *pref = VariantPointer<pref_t>::asPtr(enum_cb->property(pref_prop_));
if (!pref) return;
MainWindow* topWidget = dynamic_cast<MainWindow*> (mainApp->mainWindow());
// method 1 : apply to one single packet
/* frame_data * fdata = topWidget->frameDataForRow((topWidget->selectedRows()).at(0));
fdata->tcp_snd_manual_analysis = enum_cb->itemData(index).toInt();*/
// method 2 : we can leverage the functionality by allowing multiple selections
QList<int> rows = topWidget->selectedRows();
foreach (int row, rows) {
frame_data * fdata = topWidget->frameDataForRow(row);
fdata->tcp_snd_manual_analysis = enum_cb->itemData(index).toInt();
}
prefs_set_enum_value(pref, enum_cb->itemData(index).toInt(), pref_current);
//prefs_set_enum_value(pref, enum_cb->itemData(index).toInt(), pref_stashed);
updateWidgets();
}

View File

@ -53,6 +53,7 @@ private slots:
void saveFilenamePushButtonClicked();
void openFilenamePushButtonClicked();
void dirnamePushButtonClicked();
void enumComboBoxCurrentIndexChanged_PROTO_TCP(int index);
};
#endif // MODULE_PREFERENCES_SCROLL_AREA_H

View File

@ -26,8 +26,10 @@
#include <ui/qt/utils/qt_ui_utils.h>
#include "uat_dialog.h"
#include "main_application.h"
#include "main_window.h"
#include <QActionGroup>
#include <QMainWindow>
// To do:
// - Elide really long items?
@ -79,6 +81,32 @@ private:
int enumval_;
};
class EnumCustomTCPOverridePreferenceAction : public QAction
{
public:
EnumCustomTCPOverridePreferenceAction(pref_t *pref, const char *title, int enumval, QActionGroup *ag, QObject *parent=0) :
QAction(parent),
pref_(pref),
enumval_(enumval)
{
setText(title);
setActionGroup(ag);
setCheckable(true);
}
unsigned int setEnumValue() {
return prefs_set_enum_value(pref_, enumval_, pref_current);
}
int getEnumValue() { return enumval_; }
pref_t *getPref() { return pref_; }
private:
pref_t *pref_;
int enumval_;
};
class UatPreferenceAction : public QAction
{
public:
@ -90,7 +118,7 @@ public:
}
void showUatDialog() {
UatDialog *uat_dlg = new UatDialog(qobject_cast<QWidget *>(parent()), prefs_get_uat_value(pref_));
UatDialog *uat_dlg = new UatDialog(parentWidget(), prefs_get_uat_value(pref_));
connect(uat_dlg, SIGNAL(destroyed(QObject*)), mainApp, SLOT(flushAppSignals()));
uat_dlg->setWindowModality(Qt::ApplicationModal);
uat_dlg->setAttribute(Qt::WA_DeleteOnClose);
@ -259,6 +287,47 @@ void ProtocolPreferencesMenu::addMenuItem(preference *pref)
case PREF_STATIC_TEXT:
case PREF_OBSOLETE:
break;
case PREF_PROTO_TCP_SNDAMB_ENUM:
{
int override_id = -1;
MainWindow* topWidget = dynamic_cast<MainWindow*> (QApplication::topLevelAt(parentWidget()->mapToGlobal(QPoint())));
// the very first call does not have access to topWidget
if (topWidget) {
frame_data * fdata = topWidget->frameDataForRow((topWidget->selectedRows()).at(0));
if (fdata) {
// read stored value from frame
override_id = fdata->tcp_snd_manual_analysis;
}
else {
/* unexpected case */
}
}
QMenu *enum_menu = addMenu(prefs_get_title(pref));
const enum_val_t *enum_valp = prefs_get_enumvals(pref);
if (enum_valp && enum_valp->name) {
QActionGroup *ag = new QActionGroup(this);
while (enum_valp->name) {
EnumCustomTCPOverridePreferenceAction *epa = new EnumCustomTCPOverridePreferenceAction(pref, enum_valp->description, enum_valp->value, ag, this);
if (override_id>=0) {
if(override_id==enum_valp->value)
epa->setChecked(true);
}
else {
if(enum_valp->value == 0)
epa->setChecked(true);
}
enum_menu->addAction(epa);
//connect(epa, SIGNAL(triggered(bool)), this, SLOT(enumPreferenceTriggered()));
connect(epa, SIGNAL(triggered(bool)), this, SLOT(enumCustomTCPOverridePreferenceTriggered()));
enum_valp++;
}
}
break;
}
default:
// A type we currently don't handle. Just open the prefs dialog.
QString title = QString("%1" UTF8_HORIZONTAL_ELLIPSIS).arg(prefs_get_title(pref));
@ -331,6 +400,25 @@ void ProtocolPreferencesMenu::enumPreferenceTriggered()
}
}
void ProtocolPreferencesMenu::enumCustomTCPOverridePreferenceTriggered()
{
EnumCustomTCPOverridePreferenceAction *epa = static_cast<EnumCustomTCPOverridePreferenceAction *>(QObject::sender());
if (!epa) return;
MainWindow* topWidget = dynamic_cast<MainWindow*> (QApplication::topLevelAt(parentWidget()->mapToGlobal(QPoint())));
frame_data * fdata = topWidget->frameDataForRow((topWidget->selectedRows()).at(0));
if (! fdata)
return;
if (fdata->tcp_snd_manual_analysis != epa->getEnumValue()) { // Changed
fdata->tcp_snd_manual_analysis = epa->getEnumValue();
/* Protocol preference changes almost always affect dissection,
so don't bother checking flags */
mainApp->emitAppSignal(MainApplication::FieldsChanged);
mainApp->emitAppSignal(MainApplication::PacketDissectionChanged);
}
}
void ProtocolPreferencesMenu::uatPreferenceTriggered()
{
UatPreferenceAction *upa = static_cast<UatPreferenceAction *>(QObject::sender());

View File

@ -43,6 +43,7 @@ private slots:
void boolPreferenceTriggered();
void enumPreferenceTriggered();
void uatPreferenceTriggered();
void enumCustomTCPOverridePreferenceTriggered();
};
#endif // __PROTOCOL_PREFERENCES_MENU_H__

View File

@ -2997,14 +2997,6 @@ void WiresharkMainWindow::setMwFileName(QString fileName)
return;
}
frame_data * WiresharkMainWindow::frameDataForRow(int row) const
{
if (packet_list_)
return packet_list_->getFDataForRow(row);
return Q_NULLPTR;
}
// Finds rtp id for selected stream and adds it to stream_ids
// If reverse is set, tries to find reverse stream too
// Return error string if error happens

View File

@ -130,8 +130,6 @@ public:
QString getMwFileName();
void setMwFileName(QString fileName);
frame_data * frameDataForRow(int row) const;
protected:
virtual bool eventFilter(QObject *obj, QEvent *event);
virtual bool event(QEvent *event);