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 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 * 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_window_scaling = (gint)WindowScaling_NotKnown;
static gint tcp_default_override_analysis = (gint)OverrideAnalysis_0;
static int proto_tcp = -1; static int proto_tcp = -1;
static int proto_ip = -1; static int proto_ip = -1;
static int proto_icmp = -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 * Guide: docbook/wsug_src/WSUG_chapter_advanced.adoc
*/ */
static void 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 *ual=NULL;
tcp_unacked_t *prevual=NULL; tcp_unacked_t *prevual=NULL;
@ -2534,6 +2548,53 @@ finished_fwd:
finished_checking_retransmission_type: 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; nextseq = seq+seglen;
if ((seglen || flags&(TH_SYN|TH_FIN)) && tcpd->fwd->tcp_analyze_seq_info->segment_count < TCP_MAX_UNACKED_SEGMENTS) { 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 /* 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); 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 * 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. * 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 */ /* handle TCP seq# analysis parse all new segments we see */
if(tcp_analyze_seq) { if(tcp_analyze_seq) {
if(!(pinfo->fd->visited)) { 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) { if(tcpd && tcp_relative_seq) {
(tcph->th_seq) -= tcpd->fwd->base_seq; (tcph->th_seq) -= tcpd->fwd->base_seq;
@ -9351,6 +9418,15 @@ proto_register_tcp(void)
{NULL, NULL, -1} {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[] = { 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_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 }}, { &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. " "Make the TCP dissector use relative sequence numbers instead of absolute ones. "
"To use this option you must also enable \"Analyze TCP sequence numbers\". ", "To use this option you must also enable \"Analyze TCP sequence numbers\". ",
&tcp_relative_seq); &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", prefs_register_enum_preference(tcp_module, "default_window_scaling",
"Scaling factor to use when not available from capture", "Scaling factor to use when not available from capture",
"Make the TCP dissector use this scaling factor for streams where the signalled scaling factor " "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 { struct tcp_per_packet_data_t {
nstime_t ts_del; nstime_t ts_del;
guint8 tcp_snd_manual_analysis;
}; };
/* Structure that keeps per packet data. Some operations are cpu-intensive and are /* 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->ref_time = 0;
fdata->ignored = 0; fdata->ignored = 0;
fdata->has_ts = (rec->presence_flags & WTAP_HAS_TS) ? 1 : 0; fdata->has_ts = (rec->presence_flags & WTAP_HAS_TS) ? 1 : 0;
fdata->tcp_snd_manual_analysis = 0;
switch (rec->rec_type) { switch (rec->rec_type) {
case REC_TYPE_PACKET: 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 */ 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 frame_ref_num; /**< Previous reference frame (0 if this is one) */
guint32 prev_dis_num; /**< Previous displayed frame (0 if first 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; } frame_data;
DIAG_ON_PEDANTIC 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_DECODE_AS_RANGE (1u << 13) /* use and not as a generic protocol preference */
#define PREF_OPEN_FILENAME (1u << 14) #define PREF_OPEN_FILENAME (1u << 14)
#define PREF_PASSWORD (1u << 15) /* like string, but never saved to prefs file */ #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 { typedef enum {
GUI_ALL, GUI_ALL,

View File

@ -354,6 +354,9 @@ free_pref(gpointer data, gpointer user_data _U_)
pref->stashed_val.boolval = TRUE; pref->stashed_val.boolval = TRUE;
pref->custom_cbs.free_cb(pref); pref->custom_cbs.free_cb(pref);
break; break;
/* non-generic preferences */
case PREF_PROTO_TCP_SNDAMB_ENUM:
break;
} }
g_free(pref); 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. * Register a (internal) "Decode As" preference with a ranged value.
*/ */
@ -2023,6 +2048,7 @@ pref_stash(pref_t *pref, gpointer unused _U_)
break; break;
case PREF_ENUM: case PREF_ENUM:
case PREF_PROTO_TCP_SNDAMB_ENUM:
pref->stashed_val.enumval = *pref->varp.enump; pref->stashed_val.enumval = *pref->varp.enump;
break; break;
@ -2112,6 +2138,15 @@ pref_unstash(pref_t *pref, gpointer unstash_data_p)
} }
break; 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_STRING:
case PREF_SAVE_FILENAME: case PREF_SAVE_FILENAME:
case PREF_OPEN_FILENAME: case PREF_OPEN_FILENAME:
@ -2216,6 +2251,7 @@ reset_stashed_pref(pref_t *pref) {
break; break;
case PREF_ENUM: case PREF_ENUM:
case PREF_PROTO_TCP_SNDAMB_ENUM:
pref->stashed_val.enumval = pref->default_val.enumval; pref->stashed_val.enumval = pref->default_val.enumval;
break; break;
@ -2262,6 +2298,7 @@ pref_clean_stash(pref_t *pref, gpointer unused _U_)
break; break;
case PREF_ENUM: case PREF_ENUM:
case PREF_PROTO_TCP_SNDAMB_ENUM:
break; break;
case PREF_STRING: case PREF_STRING:
@ -4257,6 +4294,7 @@ reset_pref(pref_t *pref)
break; break;
case PREF_ENUM: case PREF_ENUM:
case PREF_PROTO_TCP_SNDAMB_ENUM:
/* /*
* For now, we save the "description" value, so that if we * For now, we save the "description" value, so that if we
* save the preferences older versions of Wireshark can at * 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; break;
case PREF_ENUM: case PREF_ENUM:
case PREF_PROTO_TCP_SNDAMB_ENUM:
/* XXX - give an error if it doesn't match? */ /* XXX - give an error if it doesn't match? */
enum_val = find_val_for_string(value, pref->info.enum_info.enumvals, enum_val = find_val_for_string(value, pref->info.enum_info.enumvals,
*pref->varp.enump); *pref->varp.enump);
@ -6197,6 +6236,7 @@ prefs_pref_type_name(pref_t *pref)
break; break;
case PREF_ENUM: case PREF_ENUM:
case PREF_PROTO_TCP_SNDAMB_ENUM:
type_name = "Choice"; type_name = "Choice";
break; break;
@ -6332,6 +6372,7 @@ prefs_pref_type_description(pref_t *pref)
break; break;
case PREF_ENUM: case PREF_ENUM:
case PREF_PROTO_TCP_SNDAMB_ENUM:
{ {
const enum_val_t *enum_valp = pref->info.enum_info.enumvals; const enum_val_t *enum_valp = pref->info.enum_info.enumvals;
GString *enum_str = g_string_new("One of: "); GString *enum_str = g_string_new("One of: ");
@ -6433,6 +6474,7 @@ prefs_pref_is_default(pref_t *pref)
break; break;
case PREF_ENUM: case PREF_ENUM:
case PREF_PROTO_TCP_SNDAMB_ENUM:
if (pref->default_val.enumval == *pref->varp.enump) if (pref->default_val.enumval == *pref->varp.enump)
return TRUE; return TRUE;
break; break;
@ -6538,6 +6580,7 @@ prefs_pref_to_str(pref_t *pref, pref_source_t source) {
return g_strdup((*(gboolean *) valp) ? "TRUE" : "FALSE"); return g_strdup((*(gboolean *) valp) ? "TRUE" : "FALSE");
case PREF_ENUM: case PREF_ENUM:
case PREF_PROTO_TCP_SNDAMB_ENUM:
{ {
gint pref_enumval = *(gint *) valp; 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, WS_DLL_PUBLIC void prefs_register_obsolete_preference(module_t *module,
const char *name); 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, * Mark a preference that affects fields change. This works for bool, enum,
* int, string (containing filename), range preferences. UAT is not included, * int, string (containing filename), range preferences. UAT is not included,

View File

@ -2856,11 +2856,3 @@ void LograyMainWindow::setMwFileName(QString fileName)
mwFileName_ = fileName; mwFileName_ = fileName;
return; 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(); QString getMwFileName();
void setMwFileName(QString fileName); void setMwFileName(QString fileName);
frame_data * frameDataForRow(int row) const;
protected: protected:
virtual bool eventFilter(QObject *obj, QEvent *event); virtual bool eventFilter(QObject *obj, QEvent *event);
virtual bool event(QEvent *event); virtual bool event(QEvent *event);

View File

@ -47,6 +47,14 @@ QList<int> MainWindow::selectedRows(bool useFrameNum)
return QList<int>(); 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) void MainWindow::insertColumn(QString name, QString abbrev, gint pos)
{ {
gint colnr = 0; gint colnr = 0;

View File

@ -12,6 +12,11 @@
#include <epan/prefs.h> #include <epan/prefs.h>
#include <epan/stat_groups.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" #include "filter_action.h"
@ -40,6 +45,7 @@ public:
QList<int> selectedRows(bool useFrameNum = false); QList<int> selectedRows(bool useFrameNum = false);
void insertColumn(QString name, QString abbrev, gint pos = -1); void insertColumn(QString name, QString abbrev, gint pos = -1);
void gotoFrame(int packet_num); void gotoFrame(int packet_num);
frame_data* frameDataForRow(int) const;
QString getFilter(); QString getFilter();
MainStatusBar *statusBar(); MainStatusBar *statusBar();

View File

@ -172,6 +172,16 @@ void RelatedPacketDelegate::paint(QPainter *painter, const QStyleOptionViewItem
other_pen.setStyle(Qt::DashLine); other_pen.setStyle(Qt::DashLine);
painter->setPen(other_pen); 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->drawLine(0, 0, 0, height);
painter->restore(); painter->restore();
break; break;
@ -184,6 +194,18 @@ void RelatedPacketDelegate::paint(QPainter *painter, const QStyleOptionViewItem
QPoint(0, 0) QPoint(0, 0)
}; };
painter->drawPolyline(end_line, 3); 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; break;
} }
default: default:

View File

@ -14,6 +14,7 @@
#include <ui/qt/utils/qt_ui_utils.h> #include <ui/qt/utils/qt_ui_utils.h>
#include "uat_dialog.h" #include "uat_dialog.h"
#include "main_application.h" #include "main_application.h"
#include "ui/qt/main_window.h"
#include <ui/qt/utils/variant_pointer.h> #include <ui/qt/utils/variant_pointer.h>
@ -28,6 +29,7 @@
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QLabel> #include <QLabel>
#include <QLineEdit> #include <QLineEdit>
#include <QMainWindow>
#include <QPushButton> #include <QPushButton>
#include <QRadioButton> #include <QRadioButton>
#include <QScrollBar> #include <QScrollBar>
@ -240,6 +242,50 @@ pref_show(pref_t *pref, gpointer user_data)
// color picker similar to the Font and Colors prefs. // color picker similar to the Font and Colors prefs.
break; 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: default:
break; 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 *>()) { foreach (QPushButton *pb, findChildren<QPushButton *>()) {
pref_t *pref = VariantPointer<pref_t>::asPtr(pb->property(pref_prop_)); pref_t *pref = VariantPointer<pref_t>::asPtr(pb->property(pref_prop_));
if (!pref) continue; 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(); 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 saveFilenamePushButtonClicked();
void openFilenamePushButtonClicked(); void openFilenamePushButtonClicked();
void dirnamePushButtonClicked(); void dirnamePushButtonClicked();
void enumComboBoxCurrentIndexChanged_PROTO_TCP(int index);
}; };
#endif // MODULE_PREFERENCES_SCROLL_AREA_H #endif // MODULE_PREFERENCES_SCROLL_AREA_H

View File

@ -26,8 +26,10 @@
#include <ui/qt/utils/qt_ui_utils.h> #include <ui/qt/utils/qt_ui_utils.h>
#include "uat_dialog.h" #include "uat_dialog.h"
#include "main_application.h" #include "main_application.h"
#include "main_window.h"
#include <QActionGroup> #include <QActionGroup>
#include <QMainWindow>
// To do: // To do:
// - Elide really long items? // - Elide really long items?
@ -79,6 +81,32 @@ private:
int enumval_; 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 class UatPreferenceAction : public QAction
{ {
public: public:
@ -90,7 +118,7 @@ public:
} }
void showUatDialog() { 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())); connect(uat_dlg, SIGNAL(destroyed(QObject*)), mainApp, SLOT(flushAppSignals()));
uat_dlg->setWindowModality(Qt::ApplicationModal); uat_dlg->setWindowModality(Qt::ApplicationModal);
uat_dlg->setAttribute(Qt::WA_DeleteOnClose); uat_dlg->setAttribute(Qt::WA_DeleteOnClose);
@ -259,6 +287,47 @@ void ProtocolPreferencesMenu::addMenuItem(preference *pref)
case PREF_STATIC_TEXT: case PREF_STATIC_TEXT:
case PREF_OBSOLETE: case PREF_OBSOLETE:
break; 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: default:
// A type we currently don't handle. Just open the prefs dialog. // A type we currently don't handle. Just open the prefs dialog.
QString title = QString("%1" UTF8_HORIZONTAL_ELLIPSIS).arg(prefs_get_title(pref)); 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() void ProtocolPreferencesMenu::uatPreferenceTriggered()
{ {
UatPreferenceAction *upa = static_cast<UatPreferenceAction *>(QObject::sender()); UatPreferenceAction *upa = static_cast<UatPreferenceAction *>(QObject::sender());

View File

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

View File

@ -2997,14 +2997,6 @@ void WiresharkMainWindow::setMwFileName(QString fileName)
return; 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 // Finds rtp id for selected stream and adds it to stream_ids
// If reverse is set, tries to find reverse stream too // If reverse is set, tries to find reverse stream too
// Return error string if error happens // Return error string if error happens

View File

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