forked from osmocom/wireshark
TCP: Overriding of the automatic SEQ Analysis
This commit is contained in:
parent
891716800b
commit
6759377b93
|
@ -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 "
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
43
epan/prefs.c
43
epan/prefs.c
|
@ -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;
|
||||
/*
|
||||
|
|
24
epan/prefs.h
24
epan/prefs.h
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ private slots:
|
|||
void saveFilenamePushButtonClicked();
|
||||
void openFilenamePushButtonClicked();
|
||||
void dirnamePushButtonClicked();
|
||||
void enumComboBoxCurrentIndexChanged_PROTO_TCP(int index);
|
||||
};
|
||||
|
||||
#endif // MODULE_PREFERENCES_SCROLL_AREA_H
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -43,6 +43,7 @@ private slots:
|
|||
void boolPreferenceTriggered();
|
||||
void enumPreferenceTriggered();
|
||||
void uatPreferenceTriggered();
|
||||
void enumCustomTCPOverridePreferenceTriggered();
|
||||
};
|
||||
|
||||
#endif // __PROTOCOL_PREFERENCES_MENU_H__
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue