forked from osmocom/wireshark
Qt: Initial VoIP Calls dialog.
Add Telephony menu items for VoIP Calls and SIP Flows. Put VoIP Calls at the top, since that seems to be the primary item. Add configure-time checks for QtMultimediaWidgets in anticipation of adding a VoIP playback dialog. Add an icon for the playback button. (Yes, I've been avoiding GNOME-level gratuitous icons so far but this is one of the rare occiasions where it makes sense.) Add a help link define for the VoIP calls dialog. Change-Id: I5d0799685c598ad9af76fe9667f8ea7d14b66050 Reviewed-on: https://code.wireshark.org/review/5674 Petri-Dish: Gerald Combs <gerald@wireshark.org> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Gerald Combs <gerald@wireshark.org>
This commit is contained in:
parent
3147087de3
commit
4921e55990
|
@ -529,7 +529,12 @@ if(BUILD_wireshark)
|
|||
set( QT5_DLL_PATH "${QT5_BASE_PATH}/bin" )
|
||||
set( WS_ALL_LIBS ${WS_ALL_LIBS} ${QT5_DLL_PATH} )
|
||||
endif()
|
||||
set(PACKAGELIST ${PACKAGELIST} Qt5Widgets Qt5PrintSupport Qt5LinguistTools)
|
||||
set(PACKAGELIST ${PACKAGELIST}
|
||||
Qt5LinguistTools
|
||||
Qt5MultimediaWidgets
|
||||
Qt5PrintSupport
|
||||
Qt5Widgets
|
||||
)
|
||||
if (APPLE)
|
||||
set(PACKAGELIST ${PACKAGELIST} Qt5MacExtras)
|
||||
endif()
|
||||
|
@ -732,6 +737,11 @@ if (Qt5Widgets_FOUND)
|
|||
endif()
|
||||
set (QT_FOUND ON)
|
||||
set (QT_LIBRARIES ${Qt5Widgets_LIBRARIES} ${Qt5PrintSupport_LIBRARIES})
|
||||
if(Qt5MultimediaWidgets_FOUND)
|
||||
set (QT_LIBRARIES ${QT_LIBRARIES} ${Qt5MultimediaWidgets_LIBRARIES})
|
||||
# That's the name autofoo uses
|
||||
set(QT_MULTIMEDIAWIDGETS_LIB 1)
|
||||
endif()
|
||||
if(Qt5MacExtras_FOUND)
|
||||
set (QT_LIBRARIES ${QT_LIBRARIES} ${Qt5MacExtras_LIBRARIES})
|
||||
# That's the name autofoo uses
|
||||
|
|
|
@ -2121,6 +2121,13 @@ AC_DEFUN([AC_WIRESHARK_QT_CHECK],
|
|||
#
|
||||
AC_WIRESHARK_QT_MODULE_CHECK(PrintSupport, $1)
|
||||
|
||||
#
|
||||
# Qt 5.0 added multimedia widgets in the Qt
|
||||
# MultimediaWidgets module.
|
||||
#
|
||||
AC_WIRESHARK_QT_MODULE_CHECK(MultimediaWidgets, $1,
|
||||
AC_DEFINE(QT_MULTIMEDIAWIDGETS_LIB, 1, [Define if we have QtMultimediaWidgets]))
|
||||
|
||||
#
|
||||
# While we're at it, look for QtMacExtras. (Presumably
|
||||
# if we're not building for OS X, it won't be present.)
|
||||
|
|
|
@ -368,6 +368,9 @@
|
|||
/* Define if we are using version of of the Portaudio library API */
|
||||
#cmakedefine PORTAUDIO_API_1 1
|
||||
|
||||
/* Define if we have QtMultimediaWidgets */
|
||||
#cmakedefine QT_MULTIMEDIAWIDGETS_LIB 1
|
||||
|
||||
/* Define if we have QtMacExtras */
|
||||
#cmakedefine QT_MACEXTRAS_LIB 1
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ reassembled packets.
|
|||
description to be shown in the status bar.
|
||||
** An Italian translation has been added.
|
||||
** The Summary dialog has been updated and renamed to Capture File Properties.
|
||||
** The VoIP Calls and SIP Flows dialogs have been added.
|
||||
|
||||
The following features are new (or have been significantly updated)
|
||||
since version 1.12.0:
|
||||
|
|
|
@ -1720,7 +1720,7 @@ endif()
|
|||
|
||||
ABICHECK(libwireshark)
|
||||
|
||||
file(GLOB COLUMN_INFO_HEADER column-info.h)
|
||||
file(GLOB EPAN_HEADERS *.h)
|
||||
file(GLOB CRYPT_HEADERS crypt/*.h)
|
||||
file(GLOB COMPRESS_HEADERS compress/*.h)
|
||||
file(GLOB DFILTER_HEADERS dfilter/*.h ../tools/lemon/cppmagic.h)
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
<file>copy-8.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="/icons">
|
||||
<file>toolbar/12x12/media-playback-start.png</file>
|
||||
<file>toolbar/12x12/media-playback-start@2x.png</file>
|
||||
<file>toolbar/16x16/edit-find.png</file>
|
||||
<file>toolbar/16x16/edit-find@2x.png</file>
|
||||
<file>toolbar/16x16/go-first.png</file>
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 256 B |
|
@ -0,0 +1,185 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="12"
|
||||
height="12"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.2 r9819"
|
||||
sodipodi:docname="media-playback-start.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
id="linearGradient4324">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0.15686275;"
|
||||
offset="0"
|
||||
id="stop4326" />
|
||||
<stop
|
||||
style="stop-color:#fffffd;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop4328" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4316">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0.15686275;"
|
||||
offset="0"
|
||||
id="stop4318" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop4320" />
|
||||
</linearGradient>
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 526.18109 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||
id="perspective10" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4316"
|
||||
id="linearGradient4322"
|
||||
x1="3"
|
||||
y1="3.9245384"
|
||||
x2="0"
|
||||
y2="1.0377871"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4324"
|
||||
id="linearGradient4330"
|
||||
x1="-1"
|
||||
y1="-0.8867138"
|
||||
x2="2"
|
||||
y2="2.0000374"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="44.416667"
|
||||
inkscape:cx="6"
|
||||
inkscape:cy="6"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:window-width="1261"
|
||||
inkscape:window-height="702"
|
||||
inkscape:window-x="1701"
|
||||
inkscape:window-y="76"
|
||||
inkscape:window-maximized="0">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid2983"
|
||||
empspacing="2"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-1040.3622)">
|
||||
<path
|
||||
inkscape:transform-center-y="-3.9e-05"
|
||||
inkscape:transform-center-x="-1.25"
|
||||
transform="matrix(1,0,0,1.0392305,3,1044.2837)"
|
||||
d="m 7,2 -7.5,4.330127 0,-8.660254 z"
|
||||
inkscape:randomized="0"
|
||||
inkscape:rounded="0"
|
||||
inkscape:flatsided="true"
|
||||
sodipodi:arg2="1.0471976"
|
||||
sodipodi:arg1="0"
|
||||
sodipodi:r2="2.5"
|
||||
sodipodi:r1="5"
|
||||
sodipodi:cy="2"
|
||||
sodipodi:cx="2"
|
||||
sodipodi:sides="3"
|
||||
id="path3802"
|
||||
style="fill:#888a85;fill-opacity:1;stroke:#555753;stroke-width:0.98094367999999998;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
sodipodi:type="star" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#888a85;fill-opacity:1;stroke:#555753;stroke-width:0.98094367999999998;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="path4312"
|
||||
sodipodi:sides="3"
|
||||
sodipodi:cx="2"
|
||||
sodipodi:cy="2"
|
||||
sodipodi:r1="5"
|
||||
sodipodi:r2="2.5"
|
||||
sodipodi:arg1="0"
|
||||
sodipodi:arg2="1.0471976"
|
||||
inkscape:flatsided="true"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 7,2 -7.5,4.330127 0,-8.660254 z"
|
||||
transform="matrix(1,0,0,1.0392305,3,1044.2837)"
|
||||
inkscape:transform-center-x="-1.25"
|
||||
inkscape:transform-center-y="-3.9e-05" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:url(#linearGradient4330);fill-opacity:1;stroke:#555753;stroke-width:0.98094367999999998;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="path3760"
|
||||
sodipodi:sides="3"
|
||||
sodipodi:cx="2"
|
||||
sodipodi:cy="2"
|
||||
sodipodi:r1="5"
|
||||
sodipodi:r2="2.5"
|
||||
sodipodi:arg1="0"
|
||||
sodipodi:arg2="1.0471976"
|
||||
inkscape:flatsided="true"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 7,2 -7.5,4.330127 0,-8.660254 z"
|
||||
transform="matrix(1,0,0,1.0392305,3,1044.2837)"
|
||||
inkscape:transform-center-x="-1.25"
|
||||
inkscape:transform-center-y="-3.9e-05" />
|
||||
<path
|
||||
inkscape:transform-center-y="-3.9e-05"
|
||||
inkscape:transform-center-x="-1.25"
|
||||
transform="matrix(1,0,0,1.0392305,3,1044.2837)"
|
||||
d="m 7,2 -7.5,4.330127 0,-8.660254 z"
|
||||
inkscape:randomized="0"
|
||||
inkscape:rounded="0"
|
||||
inkscape:flatsided="true"
|
||||
sodipodi:arg2="1.0471976"
|
||||
sodipodi:arg1="0"
|
||||
sodipodi:r2="2.5"
|
||||
sodipodi:r1="5"
|
||||
sodipodi:cy="2"
|
||||
sodipodi:cx="2"
|
||||
sodipodi:sides="3"
|
||||
id="path4314"
|
||||
style="fill:url(#linearGradient4322);fill-opacity:1;stroke:#555753;stroke-width:0.98094367999999998;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
sodipodi:type="star" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 5.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 443 B |
|
@ -43,10 +43,6 @@ set_source_svgs() {
|
|||
if [ ! -f ${TWO_X_SVG} ] ; then
|
||||
TWO_X_SVG=$ONE_X_SVG
|
||||
fi
|
||||
if [ ! -f ${ONE_X_SVG} ] ; then
|
||||
>&2 echo "Can't find ${ONE_X_SVG}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
ICONS="
|
||||
|
@ -56,6 +52,7 @@ ICONS="
|
|||
go-last
|
||||
go-next
|
||||
go-previous
|
||||
media-playback-start
|
||||
x-capture-file-close
|
||||
x-capture-file-save
|
||||
x-capture-file-reload
|
||||
|
@ -75,7 +72,7 @@ ICONS="
|
|||
QRC_FILES=""
|
||||
|
||||
# XXX Add support for 16 pixel icons.
|
||||
for SIZE in 16 24 ; do
|
||||
for SIZE in 12 16 24 ; do
|
||||
SIZE_DIR=${SIZE}x${SIZE}
|
||||
|
||||
TWO_X_SIZE=`expr $SIZE \* 2`
|
||||
|
@ -87,6 +84,11 @@ for SIZE in 16 24 ; do
|
|||
for ICON in $ICONS ; do
|
||||
set_source_svgs $ICON
|
||||
|
||||
if [ ! -f ${ONE_X_SVG} ] ; then
|
||||
>&2 echo "Skipping ${ONE_X_SVG}"
|
||||
continue
|
||||
fi
|
||||
|
||||
ONE_X_PNG=${ICON}.png
|
||||
TWO_X_PNG=${ICON}@2x.png
|
||||
|
||||
|
@ -100,15 +102,15 @@ for SIZE in 16 24 ; do
|
|||
--file=$TWO_X_SVG --export-png=$TWO_X_PNG || exit 1
|
||||
fi
|
||||
|
||||
QRC_FILES="${QRC_FILES} ${ONE_X_PNG} ${TWO_X_PNG}"
|
||||
QRC_FILES="${QRC_FILES} ${SIZE_DIR}/${ONE_X_PNG} ${SIZE_DIR}/${TWO_X_PNG}"
|
||||
done
|
||||
|
||||
cd ..
|
||||
|
||||
|
||||
done
|
||||
|
||||
for QRC_FILE in $QRC_FILES ; do
|
||||
echo " <file>toolbar/${SIZE_DIR}/${QRC_FILE}</file>"
|
||||
echo " <file>toolbar/${QRC_FILE}</file>"
|
||||
done
|
||||
|
||||
#
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
#include <epan/epan.h>
|
||||
#include <epan/packet.h>
|
||||
#include "wsutil/filesystem.h"
|
||||
#include <epan/tap.h>
|
||||
#include <epan/stat_tap_ui.h>
|
||||
#include <epan/to_str.h>
|
||||
#include <epan/address.h>
|
||||
|
@ -125,7 +124,8 @@ voip_calls_get_info(void)
|
|||
{
|
||||
/* the one and only global voip_calls_tapinfo_t structure */
|
||||
static voip_calls_tapinfo_t the_tapinfo_struct =
|
||||
{voip_calls_dlg_reset, voip_calls_dlg_packet, voip_calls_dlg_draw,
|
||||
{
|
||||
voip_calls_dlg_reset, voip_calls_dlg_packet, voip_calls_dlg_draw, NULL,
|
||||
0, NULL, {0}, 0, NULL, 0, 0, 0, NULL, NULL,
|
||||
0, NULL, /* rtp */
|
||||
0, 0, FALSE, /* rtp evt */
|
||||
|
@ -332,22 +332,6 @@ voip_calls_on_select_all(GtkButton *button _U_, gpointer user_data _U_)
|
|||
gtk_tree_selection_select_all(selection);
|
||||
}
|
||||
|
||||
/* compare two list entries by packet no */
|
||||
static gint
|
||||
graph_analysis_sort_compare(gconstpointer a, gconstpointer b, gpointer user_data _U_)
|
||||
{
|
||||
const seq_analysis_item_t *entry_a = (const seq_analysis_item_t *)a;
|
||||
const seq_analysis_item_t *entry_b = (const seq_analysis_item_t *)b;
|
||||
|
||||
if(entry_a->fd->num < entry_b->fd->num)
|
||||
return -1;
|
||||
|
||||
if(entry_a->fd->num > entry_b->fd->num)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
static void
|
||||
on_graph_bt_clicked(GtkButton *button _U_, gpointer user_data _U_)
|
||||
|
@ -361,7 +345,7 @@ on_graph_bt_clicked(GtkButton *button _U_, gpointer user_data _U_)
|
|||
if(!tapinfo->graph_analysis){
|
||||
return;
|
||||
}
|
||||
g_queue_sort(tapinfo->graph_analysis->items, graph_analysis_sort_compare, NULL);
|
||||
sequence_analysis_list_sort(tapinfo->graph_analysis);
|
||||
|
||||
/* reset the "display" parameter in graph analysis */
|
||||
listb = g_queue_peek_nth_link(tapinfo->graph_analysis->items, 0);
|
||||
|
|
|
@ -333,6 +333,9 @@ topic_action_url(topic_action_e action)
|
|||
case(HELP_FILTER_SAVE_DIALOG):
|
||||
url = user_guide_url("ChWorkFilterSaveSection.html");
|
||||
break;
|
||||
case(HELP_TELEPHONY_VOIP_CALLS_DIALOG):
|
||||
url = user_guide_url("ChTelVoipCalls.html");
|
||||
break;
|
||||
|
||||
case(TOPIC_ACTION_NONE):
|
||||
default:
|
||||
|
|
|
@ -109,7 +109,8 @@ typedef enum {
|
|||
HELP_MERGE_WIN32_DIALOG,
|
||||
HELP_SAVE_WIN32_DIALOG,
|
||||
HELP_TIME_SHIFT_DIALOG,
|
||||
HELP_FILTER_SAVE_DIALOG
|
||||
HELP_FILTER_SAVE_DIALOG,
|
||||
HELP_TELEPHONY_VOIP_CALLS_DIALOG
|
||||
} topic_action_e;
|
||||
|
||||
/** Given a filename return a filesystem URL. Relative paths are prefixed with
|
||||
|
|
|
@ -97,6 +97,7 @@ set(WIRESHARK_QT_HEADERS
|
|||
time_shift_dialog.h
|
||||
traffic_table_dialog.h
|
||||
uat_dialog.h
|
||||
voip_calls_dialog.h
|
||||
wireshark_application.h
|
||||
)
|
||||
|
||||
|
@ -194,6 +195,7 @@ set(WIRESHARK_QT_SRC
|
|||
time_shift_dialog.cpp
|
||||
traffic_table_dialog.cpp
|
||||
uat_dialog.cpp
|
||||
voip_calls_dialog.cpp
|
||||
wireshark_application.cpp
|
||||
)
|
||||
|
||||
|
@ -267,6 +269,7 @@ set(WIRESHARK_QT_UI
|
|||
time_shift_dialog.ui
|
||||
traffic_table_dialog.ui
|
||||
uat_dialog.ui
|
||||
voip_calls_dialog.ui
|
||||
)
|
||||
|
||||
if(HAVE_PCAP_REMOTE)
|
||||
|
|
|
@ -214,6 +214,8 @@ traffic_table_dialog.cpp traffic_table_dialog.h: ui_traffic_table_dialog.h
|
|||
|
||||
uat_dialog.cpp uat_dialog.h: ui_uat_dialog.h
|
||||
|
||||
voip_calls_dialog.cpp voip_calls_dialog.h: ui_voip_calls_dialog.h
|
||||
|
||||
doxygen:
|
||||
if HAVE_DOXYGEN
|
||||
$(DOXYGEN) doxygen.cfg
|
||||
|
|
|
@ -75,7 +75,8 @@ NODIST_GENERATED_HEADER_FILES = \
|
|||
ui_tcp_stream_dialog.h \
|
||||
ui_time_shift_dialog.h \
|
||||
ui_traffic_table_dialog.h \
|
||||
ui_uat_dialog.h
|
||||
ui_uat_dialog.h \
|
||||
ui_voip_calls_dialog.h
|
||||
|
||||
# Generated C source files that we want in the distribution.
|
||||
GENERATED_C_FILES = \
|
||||
|
@ -190,6 +191,7 @@ MOC_HDRS = \
|
|||
time_shift_dialog.h \
|
||||
traffic_table_dialog.h \
|
||||
uat_dialog.h \
|
||||
voip_calls_dialog.h \
|
||||
wireshark_application.h
|
||||
|
||||
|
||||
|
@ -243,7 +245,8 @@ UI_FILES = \
|
|||
tcp_stream_dialog.ui \
|
||||
time_shift_dialog.ui \
|
||||
traffic_table_dialog.ui \
|
||||
uat_dialog.ui
|
||||
uat_dialog.ui \
|
||||
voip_calls_dialog.ui
|
||||
|
||||
#
|
||||
# The .moc.cpp files generated from them.
|
||||
|
@ -386,6 +389,7 @@ WIRESHARK_QT_SRC = \
|
|||
time_shift_dialog.cpp \
|
||||
traffic_table_dialog.cpp \
|
||||
uat_dialog.cpp \
|
||||
voip_calls_dialog.cpp \
|
||||
wireshark_application.cpp
|
||||
|
||||
WIRESHARK_QT_TAP_SRC = \
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
isEqual(QT_MAJOR_VERSION, 4) {
|
||||
QT += core gui
|
||||
} else {
|
||||
QT += core widgets printsupport
|
||||
QT += core widgets printsupport multimediawidgets
|
||||
}
|
||||
|
||||
isEqual(QT_MAJOR_VERSION, 5): greaterThan(QT_MINOR_VERSION, 1): win32 {
|
||||
|
@ -252,7 +252,8 @@ FORMS += \
|
|||
tcp_stream_dialog.ui \
|
||||
time_shift_dialog.ui \
|
||||
traffic_table_dialog.ui \
|
||||
uat_dialog.ui
|
||||
uat_dialog.ui \
|
||||
voip_calls_dialog.ui
|
||||
|
||||
|
||||
HEADERS += $$HEADERS_WS_C \
|
||||
|
@ -302,7 +303,8 @@ HEADERS += $$HEADERS_WS_C \
|
|||
tango_colors.h \
|
||||
tcp_stream_dialog.h \
|
||||
traffic_table_dialog.h \
|
||||
uat_dialog.h
|
||||
uat_dialog.h \
|
||||
voip_calls_dialog.h
|
||||
|
||||
win32 {
|
||||
OBJECTS_WS_C = $$SOURCES_WS_C
|
||||
|
@ -423,7 +425,7 @@ win32 {
|
|||
EXTRA_DLLS = QtCored4 QtGuid4
|
||||
} else: lessThan(QT_MINOR_VERSION, 3) {
|
||||
# The QT lib parts are copied by windeployqt post 5.3
|
||||
EXTRA_DLLS = Qt5Cored Qt5Guid Qt5Widgetsd Qt5PrintSupportd
|
||||
EXTRA_DLLS = Qt5Cored Qt5Guid Qt5Widgetsd Qt5PrintSupportd Qt5MultimediaWidgetsd
|
||||
EXTRA_PLATFORM_DLLS = qwindowsd
|
||||
QMAKE_POST_LINK +=$$quote($(CHK_DIR_EXISTS) $${PLATFORM_DLL_DIR} $(MKDIR) $${PLATFORM_DLL_DIR}$$escape_expand(\\n\\t))
|
||||
}
|
||||
|
@ -433,7 +435,7 @@ win32 {
|
|||
EXTRA_DLLS = QtCore4 QtGui4
|
||||
} else: lessThan(QT_MINOR_VERSION, 3) {
|
||||
# The QT lib parts are copied by windeployqt post 5.3
|
||||
EXTRA_DLLS = Qt5Core Qt5Gui Qt5Widgets Qt5PrintSupport
|
||||
EXTRA_DLLS = Qt5Core Qt5Gui Qt5Widgets Qt5PrintSupport Qt5MultimediaWidgets
|
||||
EXTRA_PLATFORM_DLLS = qwindows
|
||||
QMAKE_POST_LINK +=$$quote($(CHK_DIR_EXISTS) $${PLATFORM_DLL_DIR} $(MKDIR) $${PLATFORM_DLL_DIR}$$escape_expand(\\n\\t))
|
||||
}
|
||||
|
@ -667,4 +669,5 @@ SOURCES += \
|
|||
time_shift_dialog.cpp \
|
||||
traffic_table_dialog.cpp \
|
||||
uat_dialog.cpp \
|
||||
voip_calls_dialog.cpp \
|
||||
wireshark_application.cpp
|
||||
|
|
|
@ -607,7 +607,6 @@ void FollowStreamDialog::setCaptureFile(capture_file *cf)
|
|||
// / (slash), Ctrl-F - Focus and highlight the search box
|
||||
// Ctrl-G, Ctrl-N, F3 - Find next
|
||||
// Should we make it so that typing any text starts searching?
|
||||
#include <QDebug>
|
||||
bool FollowStreamDialog::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
Q_UNUSED(obj);
|
||||
|
|
|
@ -409,10 +409,13 @@ private slots:
|
|||
void on_actionStatisticsIOGraph_triggered();
|
||||
void on_actionStatisticsSametime_triggered();
|
||||
|
||||
void openVoipCallsDialog(bool all_flows = false);
|
||||
void on_actionTelephonyVoipCalls_triggered();
|
||||
void on_actionTelephonyISUPMessages_triggered();
|
||||
void on_actionTelephonyRTSPPacketCounter_triggered();
|
||||
void on_actionTelephonySMPPOperations_triggered();
|
||||
void on_actionTelephonyUCPMessages_triggered();
|
||||
void on_actionTelephonySipFlows_triggered();
|
||||
|
||||
void changeEvent(QEvent* event);
|
||||
};
|
||||
|
|
|
@ -435,10 +435,12 @@
|
|||
</property>
|
||||
<addaction name="actionTelephonyRTSPPacketCounter"/>
|
||||
</widget>
|
||||
<addaction name="actionTelephonyVoipCalls"/>
|
||||
<addaction name="actionTelephonyISUPMessages"/>
|
||||
<addaction name="menuRTSP"/>
|
||||
<addaction name="actionTelephonySMPPOperations"/>
|
||||
<addaction name="actionTelephonyUCPMessages"/>
|
||||
<addaction name="actionTelephonySipFlows"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuEdit">
|
||||
<property name="title">
|
||||
|
@ -2136,6 +2138,22 @@
|
|||
<string>Bytes</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionTelephonyVoipCalls">
|
||||
<property name="text">
|
||||
<string>&VoIP Calls</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>All VoIP Calls</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionTelephonySipFlows">
|
||||
<property name="text">
|
||||
<string>SIP &Flows</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>SIP Flows</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<customwidgets>
|
||||
|
|
|
@ -96,6 +96,7 @@
|
|||
#include "stats_tree_dialog.h"
|
||||
#include "tcp_stream_dialog.h"
|
||||
#include "time_shift_dialog.h"
|
||||
#include "voip_calls_dialog.h"
|
||||
#include "wireshark_application.h"
|
||||
|
||||
#include <QClipboard>
|
||||
|
@ -2342,6 +2343,23 @@ void MainWindow::on_actionStatisticsSametime_triggered()
|
|||
|
||||
// Telephony Menu
|
||||
|
||||
void MainWindow::openVoipCallsDialog(bool all_flows)
|
||||
{
|
||||
VoipCallsDialog *voip_calls_dialog = new VoipCallsDialog(this, cap_file_, all_flows);
|
||||
connect(voip_calls_dialog, SIGNAL(goToPacket(int)),
|
||||
packet_list_, SLOT(goToPacket(int)));
|
||||
connect(voip_calls_dialog, SIGNAL(updateFilter(QString&, bool)),
|
||||
this, SLOT(filterPackets(QString&, bool)));
|
||||
connect(this, SIGNAL(setCaptureFile(capture_file*)),
|
||||
voip_calls_dialog, SLOT(setCaptureFile(capture_file*)));
|
||||
voip_calls_dialog->show();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionTelephonyVoipCalls_triggered()
|
||||
{
|
||||
openVoipCallsDialog();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionTelephonyISUPMessages_triggered()
|
||||
{
|
||||
openStatisticsTreeDialog("isup_msg");
|
||||
|
@ -2362,6 +2380,11 @@ void MainWindow::on_actionTelephonyUCPMessages_triggered()
|
|||
openStatisticsTreeDialog("ucp_messages");
|
||||
}
|
||||
|
||||
void MainWindow::on_actionTelephonySipFlows_triggered()
|
||||
{
|
||||
openVoipCallsDialog(true);
|
||||
}
|
||||
|
||||
// Help Menu
|
||||
void MainWindow::on_actionHelpContents_triggered() {
|
||||
|
||||
|
|
|
@ -31,8 +31,6 @@
|
|||
#include <QPen>
|
||||
#include <QPointF>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
const int max_comment_em_width_ = 20;
|
||||
|
||||
// UML-like network node sequence diagrams.
|
||||
|
@ -98,8 +96,9 @@ SequenceDiagram::SequenceDiagram(QCPAxis *keyAxis, QCPAxis *valueAxis, QCPAxis *
|
|||
void SequenceDiagram::setData(seq_analysis_info_t *sainfo)
|
||||
{
|
||||
data_->clear();
|
||||
sainfo_ = sainfo;
|
||||
if (!sainfo) return;
|
||||
|
||||
WSCPSeqData new_data;
|
||||
double cur_key = 0.0;
|
||||
QVector<double> key_ticks, val_ticks;
|
||||
QVector<QString> key_labels, val_labels, com_labels;
|
||||
|
@ -108,6 +107,7 @@ void SequenceDiagram::setData(seq_analysis_info_t *sainfo)
|
|||
|
||||
for (GList *cur = g_queue_peek_nth_link(sainfo->items, 0); cur; cur = g_list_next(cur)) {
|
||||
seq_analysis_item_t *sai = (seq_analysis_item_t *) cur->data;
|
||||
WSCPSeqData new_data;
|
||||
|
||||
new_data.key = cur_key;
|
||||
new_data.value = sai;
|
||||
|
@ -120,7 +120,6 @@ void SequenceDiagram::setData(seq_analysis_info_t *sainfo)
|
|||
|
||||
cur_key++;
|
||||
}
|
||||
sainfo_ = sainfo;
|
||||
|
||||
for (unsigned int i = 0; i < sainfo_->num_nodes; i++) {
|
||||
val_ticks.append(i);
|
||||
|
@ -193,7 +192,7 @@ void SequenceDiagram::draw(QCPPainter *painter)
|
|||
WSCPSeqDataMap::const_iterator it;
|
||||
for (it = data_->constBegin(); it != data_->constEnd(); ++it) {
|
||||
double cur_key = it.key();
|
||||
seq_analysis_item_t *sai = (seq_analysis_item_t *) it.value().value;
|
||||
seq_analysis_item_t *sai = it.value().value;
|
||||
QPen fg_pen(mainPen());
|
||||
|
||||
if (sai->fd->num == selected_packet_) {
|
||||
|
|
|
@ -64,7 +64,7 @@ public:
|
|||
seq_analysis_item_t *itemForPosY(int ypos);
|
||||
|
||||
// reimplemented virtual methods:
|
||||
virtual void clearData() {}
|
||||
virtual void clearData() { data_->clear(); }
|
||||
virtual double selectTest(const QPointF &pos, bool onlySelectable, QVariant *details=0) const;
|
||||
|
||||
public slots:
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include "wsutil/nstime.h"
|
||||
|
||||
#include "sequence_diagram.h"
|
||||
#include "wireshark_application.h"
|
||||
|
||||
#include <QDir>
|
||||
|
@ -33,8 +34,6 @@
|
|||
#include <QFontMetrics>
|
||||
#include <QPoint>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
// To do:
|
||||
// - Add UTF8 to text dump
|
||||
// - Save to XMI? http://www.umlgraph.org/
|
||||
|
@ -46,10 +45,11 @@
|
|||
// - Create WSGraph subclasses with common behavior.
|
||||
// - Help button and text
|
||||
|
||||
SequenceDialog::SequenceDialog(QWidget *parent, capture_file *cf, SequenceType type) :
|
||||
SequenceDialog::SequenceDialog(QWidget *parent, capture_file *cf, seq_analysis_info_t *sainfo) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::SequenceDialog),
|
||||
cap_file_(cf),
|
||||
sainfo_(sainfo),
|
||||
num_items_(0),
|
||||
packet_num_(0),
|
||||
node_label_w_(20)
|
||||
|
@ -57,6 +57,14 @@ SequenceDialog::SequenceDialog(QWidget *parent, capture_file *cf, SequenceType t
|
|||
ui->setupUi(this);
|
||||
QCustomPlot *sp = ui->sequencePlot;
|
||||
|
||||
if (!sainfo_) {
|
||||
sainfo_ = sequence_analysis_info_new();
|
||||
sainfo_->type = SEQ_ANALYSIS_ANY;
|
||||
sainfo_->all_packets = TRUE;
|
||||
} else {
|
||||
num_items_ = sequence_analysis_get_nodes(sainfo_);
|
||||
}
|
||||
|
||||
seq_diagram_ = new SequenceDiagram(sp->yAxis, sp->xAxis2, sp->yAxis2);
|
||||
sp->addPlottable(seq_diagram_);
|
||||
sp->axisRect()->setRangeDragAxes(sp->xAxis2, sp->yAxis);
|
||||
|
@ -90,8 +98,6 @@ SequenceDialog::SequenceDialog(QWidget *parent, capture_file *cf, SequenceType t
|
|||
ctx_menu_.addSeparator();
|
||||
ctx_menu_.addAction(ui->actionGoToPacket);
|
||||
|
||||
memset (&seq_analysis_, 0, sizeof(seq_analysis_));
|
||||
|
||||
ui->showComboBox->blockSignals(true);
|
||||
ui->showComboBox->setCurrentIndex(0);
|
||||
ui->showComboBox->blockSignals(false);
|
||||
|
@ -104,23 +110,13 @@ SequenceDialog::SequenceDialog(QWidget *parent, capture_file *cf, SequenceType t
|
|||
fcb->addItem(ui->actionFlowTcp->text(), SEQ_ANALYSIS_TCP);
|
||||
|
||||
ui->flowComboBox->blockSignals(true);
|
||||
switch (type) {
|
||||
case any:
|
||||
seq_analysis_.type = SEQ_ANALYSIS_ANY;
|
||||
ui->flowComboBox->setCurrentIndex(SEQ_ANALYSIS_ANY);
|
||||
break;
|
||||
case tcp:
|
||||
seq_analysis_.type = SEQ_ANALYSIS_TCP;
|
||||
ui->flowComboBox->setCurrentIndex(SEQ_ANALYSIS_TCP);
|
||||
break;
|
||||
case voip:
|
||||
seq_analysis_.type = SEQ_ANALYSIS_VOIP;
|
||||
ui->flowComboBox->hide();
|
||||
ui->flowLabel->hide();
|
||||
break;
|
||||
ui->flowComboBox->setCurrentIndex(sainfo_->type);
|
||||
|
||||
if (sainfo_->type == SEQ_ANALYSIS_VOIP) {
|
||||
ui->controlFrame->hide();
|
||||
} else {
|
||||
ui->flowComboBox->blockSignals(false);
|
||||
}
|
||||
ui->flowComboBox->blockSignals(false);
|
||||
seq_analysis_.all_packets = TRUE;
|
||||
|
||||
QPushButton *save_bt = ui->buttonBox->button(QDialogButtonBox::Save);
|
||||
save_bt->setText(tr("Save As..."));
|
||||
|
@ -146,6 +142,9 @@ SequenceDialog::SequenceDialog(QWidget *parent, capture_file *cf, SequenceType t
|
|||
|
||||
SequenceDialog::~SequenceDialog()
|
||||
{
|
||||
if (sainfo_->type != SEQ_ANALYSIS_VOIP) {
|
||||
sequence_analysis_info_free(sainfo_);
|
||||
}
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
@ -279,8 +278,12 @@ void SequenceDialog::mouseMoved(QMouseEvent *event)
|
|||
}
|
||||
|
||||
if (hint.isEmpty()) {
|
||||
hint += tr("%Ln node(s)", "", seq_analysis_.num_nodes) + QString(", ")
|
||||
+ tr("%Ln item(s)", "", num_items_);
|
||||
if (!sainfo_) {
|
||||
hint += tr("No data");
|
||||
} else {
|
||||
hint += tr("%Ln node(s)", "", sainfo_->num_nodes) + QString(", ")
|
||||
+ tr("%Ln item(s)", "", num_items_);
|
||||
}
|
||||
}
|
||||
|
||||
hint.prepend("<small><i>");
|
||||
|
@ -329,8 +332,8 @@ void SequenceDialog::on_buttonBox_accepted()
|
|||
save_ok = ui->sequencePlot->saveBmp(file_name);
|
||||
} else if (extension.compare(jpeg_filter) == 0) {
|
||||
save_ok = ui->sequencePlot->saveJpg(file_name);
|
||||
} else if (extension.compare(ascii_filter) == 0 && cap_file_) {
|
||||
save_ok = sequence_analysis_dump_to_file(file_name.toUtf8().constData(), &seq_analysis_, cap_file_, 0);
|
||||
} else if (extension.compare(ascii_filter) == 0 && cap_file_ && sainfo_) {
|
||||
save_ok = sequence_analysis_dump_to_file(file_name.toUtf8().constData(), sainfo_, cap_file_, 0);
|
||||
}
|
||||
// else error dialog?
|
||||
if (save_ok) {
|
||||
|
@ -342,23 +345,24 @@ void SequenceDialog::on_buttonBox_accepted()
|
|||
|
||||
void SequenceDialog::fillDiagram()
|
||||
{
|
||||
QCustomPlot *sp = ui->sequencePlot;
|
||||
seq_analysis_info_t new_sa;
|
||||
if (!sainfo_) return;
|
||||
|
||||
new_sa = seq_analysis_;
|
||||
new_sa.items = g_queue_new();
|
||||
new_sa.ht = NULL;
|
||||
new_sa.num_nodes = 0;
|
||||
sequence_analysis_list_get(cap_file_, &new_sa);
|
||||
num_items_ = sequence_analysis_get_nodes(&new_sa);
|
||||
seq_diagram_->setData(&new_sa);
|
||||
sequence_analysis_list_free(&seq_analysis_);
|
||||
seq_analysis_ = new_sa;
|
||||
QCustomPlot *sp = ui->sequencePlot;
|
||||
|
||||
if (sainfo_->type == SEQ_ANALYSIS_VOIP) {
|
||||
seq_diagram_->setData(sainfo_);
|
||||
} else {
|
||||
seq_diagram_->clearData();
|
||||
sequence_analysis_list_free(sainfo_);
|
||||
sequence_analysis_list_get(cap_file_, sainfo_);
|
||||
num_items_ = sequence_analysis_get_nodes(sainfo_);
|
||||
seq_diagram_->setData(sainfo_);
|
||||
}
|
||||
|
||||
QFontMetrics vfm = QFontMetrics(sp->xAxis2->labelFont());
|
||||
node_label_w_ = 0;
|
||||
for (guint i = 0; i < seq_analysis_.num_nodes; i++) {
|
||||
int label_w = vfm.width(ep_address_to_display(&(seq_analysis_.nodes[i])));
|
||||
for (guint i = 0; i < sainfo_->num_nodes; i++) {
|
||||
int label_w = vfm.width(ep_address_to_display(&(sainfo_->nodes[i])));
|
||||
if (node_label_w_ < label_w) {
|
||||
node_label_w_ = label_w;
|
||||
}
|
||||
|
@ -393,6 +397,8 @@ void SequenceDialog::panAxes(int x_pixels, int y_pixels)
|
|||
|
||||
void SequenceDialog::resetAxes(bool keep_lower)
|
||||
{
|
||||
if (!sainfo_) return;
|
||||
|
||||
QCustomPlot *sp = ui->sequencePlot;
|
||||
// Allow space for labels on the top and port numbers on the left.
|
||||
double top_pos = -1.0, left_pos = -0.5;
|
||||
|
@ -408,7 +414,7 @@ void SequenceDialog::resetAxes(bool keep_lower)
|
|||
sp->yAxis->setRange(top_pos, range_ratio + top_pos);
|
||||
|
||||
double rmin = sp->xAxis2->range().size() / 2;
|
||||
ui->horizontalScrollBar->setRange((rmin - 0.5) * 100, (seq_analysis_.num_nodes - 0.5 - rmin) * 100);
|
||||
ui->horizontalScrollBar->setRange((rmin - 0.5) * 100, (sainfo_->num_nodes - 0.5 - rmin) * 100);
|
||||
xAxisChanged(sp->xAxis2->range());
|
||||
|
||||
rmin = (sp->yAxis->range().size() / 2);
|
||||
|
@ -432,27 +438,32 @@ void SequenceDialog::on_actionGoToPacket_triggered()
|
|||
|
||||
void SequenceDialog::on_showComboBox_currentIndexChanged(int index)
|
||||
{
|
||||
if (!sainfo_) return;
|
||||
|
||||
if (index == 0) {
|
||||
seq_analysis_.all_packets = TRUE;
|
||||
sainfo_->all_packets = TRUE;
|
||||
} else {
|
||||
seq_analysis_.all_packets = FALSE;
|
||||
sainfo_->all_packets = FALSE;
|
||||
}
|
||||
fillDiagram();
|
||||
}
|
||||
|
||||
void SequenceDialog::on_flowComboBox_currentIndexChanged(int index)
|
||||
{
|
||||
if (index < 0) return;
|
||||
seq_analysis_.type = static_cast<seq_analysis_type>(ui->flowComboBox->itemData(index).toInt());
|
||||
if (!sainfo_ || sainfo_->type == SEQ_ANALYSIS_VOIP || index < 0) return;
|
||||
|
||||
sainfo_->type = static_cast<seq_analysis_type>(ui->flowComboBox->itemData(index).toInt());
|
||||
fillDiagram();
|
||||
}
|
||||
|
||||
void SequenceDialog::on_addressComboBox_currentIndexChanged(int index)
|
||||
{
|
||||
if (!sainfo_) return;
|
||||
|
||||
if (index == 0) {
|
||||
seq_analysis_.any_addr = TRUE;
|
||||
sainfo_->any_addr = TRUE;
|
||||
} else {
|
||||
seq_analysis_.any_addr = FALSE;
|
||||
sainfo_->any_addr = FALSE;
|
||||
}
|
||||
fillDiagram();
|
||||
}
|
||||
|
|
|
@ -30,7 +30,9 @@
|
|||
|
||||
#include "epan/packet.h"
|
||||
|
||||
#include "sequence_diagram.h"
|
||||
#include "ui/tap-sequence-analysis.h"
|
||||
|
||||
#include "qcustomplot.h"
|
||||
|
||||
#include <QDialog>
|
||||
#include <QMenu>
|
||||
|
@ -39,14 +41,14 @@ namespace Ui {
|
|||
class SequenceDialog;
|
||||
}
|
||||
|
||||
class SequenceDiagram;
|
||||
|
||||
class SequenceDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum SequenceType { any, tcp, voip };
|
||||
|
||||
explicit SequenceDialog(QWidget *parent = 0, capture_file *cf = NULL, SequenceType type = any);
|
||||
explicit SequenceDialog(QWidget *parent = 0, capture_file *cf = NULL, seq_analysis_info_t *sainfo = NULL);
|
||||
~SequenceDialog();
|
||||
|
||||
signals:
|
||||
|
@ -90,7 +92,7 @@ private:
|
|||
Ui::SequenceDialog *ui;
|
||||
SequenceDiagram *seq_diagram_;
|
||||
capture_file *cap_file_;
|
||||
seq_analysis_info_t seq_analysis_;
|
||||
seq_analysis_info_t *sainfo_;
|
||||
int num_items_;
|
||||
guint32 packet_num_;
|
||||
double one_em_;
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<property name="windowTitle">
|
||||
<string>Flow</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="1,0,0,0">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
|
@ -75,123 +75,137 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="controlHorizontalLayout" stretch="0,0,0,0,0,0,0,0,1">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Show:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="showComboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>All packets</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Displayed packets</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>13</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="flowLabel">
|
||||
<property name="text">
|
||||
<string>Flow type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="flowComboBox"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>13</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Addresses:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="addressComboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Any</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Network</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="resetButton">
|
||||
<property name="text">
|
||||
<string>Reset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<widget class="QFrame" name="controlFrame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Show:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="showComboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>All packets</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Displayed packets</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>13</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="flowLabel">
|
||||
<property name="text">
|
||||
<string>Flow type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="flowComboBox"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>13</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Addresses:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="addressComboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Any</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Network</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="resetButton">
|
||||
<property name="text">
|
||||
<string>Reset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
|
@ -345,6 +359,7 @@
|
|||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
|
|
|
@ -75,15 +75,16 @@ StockIcon::StockIcon(const char *icon_name) :
|
|||
#endif
|
||||
return;
|
||||
} else {
|
||||
QStringList types = QStringList() << "16x16" << "24x24";
|
||||
QStringList types = QStringList() << "12x12" << "16x16" << "24x24";
|
||||
foreach (QString type, types) {
|
||||
// Along with each name check for "<name>.on" to use for the on (checked) state.
|
||||
// XXX Add checks for each combination of QIcon::Mode + QIcon::State
|
||||
QString icon_path = path_pfx_ + QString("%1/%2.png").arg(type).arg(icon_name);
|
||||
QString icon_path_on = path_pfx_ + QString("%1/%2.on.png").arg(type).arg(icon_name);
|
||||
if (QFile::exists(icon_path)) {
|
||||
addFile(icon_path);
|
||||
}
|
||||
|
||||
// Along with each name check for "<name>.on" to use for the on (checked) state.
|
||||
// XXX Add checks for each combination of QIcon::Mode + QIcon::State
|
||||
QString icon_path_on = path_pfx_ + QString("%1/%2.on.png").arg(type).arg(icon_name);
|
||||
if (QFile::exists(icon_path_on)) {
|
||||
addFile(icon_path_on, QSize(), QIcon::Normal, QIcon::On);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,508 @@
|
|||
/* voip_calls_dialog.cpp
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "voip_calls_dialog.h"
|
||||
#include "ui_voip_calls_dialog.h"
|
||||
|
||||
#include "file.h"
|
||||
|
||||
#include "epan/addr_resolv.h"
|
||||
#include "epan/dissectors/packet-h225.h"
|
||||
|
||||
#include "ui/utf8_entities.h"
|
||||
|
||||
#include "sequence_dialog.h"
|
||||
#include "stock_icon.h"
|
||||
#include "wireshark_application.h"
|
||||
|
||||
#include <QContextMenuEvent>
|
||||
#include <QPushButton>
|
||||
|
||||
// To do:
|
||||
// - More context menu items
|
||||
// - Don't select on right click
|
||||
// - Player
|
||||
// - Add a screenshot to the user's guide
|
||||
|
||||
// Bugs:
|
||||
// - Preparing a filter overwrites the existing filter. The GTK+ UI appends.
|
||||
// We'll probably have to add an "append" parameter to MainWindow::filterPackets.
|
||||
|
||||
// VoipCallsTreeWidgetItem
|
||||
// QTreeWidgetItem subclass that allows sorting
|
||||
|
||||
const int start_time_col_ = 0;
|
||||
const int stop_time_col_ = 1;
|
||||
const int initial_speaker_col_ = 2;
|
||||
const int from_col_ = 3;
|
||||
const int to_col_ = 4;
|
||||
const int protocol_col_ = 5;
|
||||
const int packets_col_ = 6;
|
||||
const int state_col_ = 7;
|
||||
const int comments_col_ = 8;
|
||||
|
||||
Q_DECLARE_METATYPE(voip_calls_info_t*)
|
||||
|
||||
class VoipCallsTreeWidgetItem : public QTreeWidgetItem
|
||||
{
|
||||
public:
|
||||
VoipCallsTreeWidgetItem(QTreeWidget *tree, voip_calls_info_t *call_info) : QTreeWidgetItem(tree) {
|
||||
setData(0, Qt::UserRole, qVariantFromValue(call_info));
|
||||
drawData();
|
||||
}
|
||||
|
||||
void drawData() {
|
||||
voip_calls_info_t *call_info = data(0, Qt::UserRole).value<voip_calls_info_t*>();
|
||||
if (!call_info) {
|
||||
return;
|
||||
}
|
||||
|
||||
// XXX Pull digit count from capture file precision
|
||||
setText(start_time_col_, QString::number(nstime_to_sec(&(call_info->start_rel_ts)), 'f', 6));
|
||||
setText(stop_time_col_, QString::number(nstime_to_sec(&(call_info->stop_rel_ts)), 'f', 6));
|
||||
setText(initial_speaker_col_, ep_address_to_display(&(call_info->initial_speaker)));
|
||||
setText(from_col_, call_info->from_identity);
|
||||
setText(to_col_, call_info->to_identity);
|
||||
setText(protocol_col_, ((call_info->protocol == VOIP_COMMON) && call_info->protocol_name) ?
|
||||
call_info->protocol_name : voip_protocol_name[call_info->protocol]);
|
||||
setText(packets_col_, QString::number(call_info->npackets));
|
||||
setText(state_col_, voip_call_state_name[call_info->call_state]);
|
||||
|
||||
/* Add comments based on the protocol */
|
||||
QString call_comments;
|
||||
switch (call_info->protocol) {
|
||||
case VOIP_ISUP:
|
||||
{
|
||||
isup_calls_info_t *isup_info = (isup_calls_info_t *)call_info->prot_info;
|
||||
call_comments = QString("%1-%2 %3 %4-%5")
|
||||
.arg(isup_info->ni)
|
||||
.arg(isup_info->opc)
|
||||
.arg(UTF8_RIGHTWARDS_ARROW)
|
||||
.arg(isup_info->ni)
|
||||
.arg(isup_info->dpc);
|
||||
}
|
||||
break;
|
||||
case VOIP_H323:
|
||||
{
|
||||
h323_calls_info_t *h323_info = (h323_calls_info_t *)call_info->prot_info;
|
||||
gboolean flag = FALSE;
|
||||
static const QString on_str = QObject::tr("On");
|
||||
static const QString off_str = QObject::tr("Off");
|
||||
if (call_info->call_state == VOIP_CALL_SETUP) {
|
||||
flag = h323_info->is_faststart_Setup;
|
||||
} else {
|
||||
if ((h323_info->is_faststart_Setup) && (h323_info->is_faststart_Proc)) {
|
||||
flag = TRUE;
|
||||
}
|
||||
}
|
||||
call_comments = QObject::tr("Tunneling: %1 Fast Start: %2")
|
||||
.arg(h323_info->is_h245Tunneling ? on_str : off_str)
|
||||
.arg(flag ? on_str : off_str);
|
||||
}
|
||||
break;
|
||||
case VOIP_COMMON:
|
||||
default:
|
||||
call_comments = call_info->call_comment;
|
||||
break;
|
||||
}
|
||||
setText(comments_col_, call_comments);
|
||||
}
|
||||
|
||||
bool operator< (const QTreeWidgetItem &other) const
|
||||
{
|
||||
voip_calls_info_t *this_call_info = data(0, Qt::UserRole).value<voip_calls_info_t*>();
|
||||
voip_calls_info_t *other_call_info = other.data(0, Qt::UserRole).value<voip_calls_info_t*>();
|
||||
if (!this_call_info || !other_call_info) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (treeWidget()->sortColumn()) {
|
||||
case start_time_col_:
|
||||
return nstime_cmp(&(this_call_info->start_rel_ts), &(other_call_info->start_rel_ts)) < 0;
|
||||
break;
|
||||
case stop_time_col_:
|
||||
return nstime_cmp(&(this_call_info->stop_rel_ts), &(other_call_info->stop_rel_ts)) < 0;
|
||||
break;
|
||||
case initial_speaker_col_:
|
||||
return cmp_address(&(this_call_info->initial_speaker), &(other_call_info->initial_speaker)) < 0;
|
||||
break;
|
||||
case packets_col_:
|
||||
return this_call_info->npackets < other_call_info->npackets;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Fall back to string comparison
|
||||
return QTreeWidgetItem::operator <(other);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
VoipCallsDialog::VoipCallsDialog(QWidget *parent, capture_file *cf, bool all_flows) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::VoipCallsDialog),
|
||||
cap_file_(cf)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->callTreeWidget->sortByColumn(start_time_col_, Qt::AscendingOrder);
|
||||
|
||||
ctx_menu_.addActions(QList<QAction *>() << ui->actionSelect_All);
|
||||
|
||||
prepare_button_ = ui->buttonBox->addButton(tr("Prepare Filter"), QDialogButtonBox::ApplyRole);
|
||||
sequence_button_ = ui->buttonBox->addButton(tr("Flow Sequence"), QDialogButtonBox::ApplyRole);
|
||||
player_button_ = ui->buttonBox->addButton(tr("Play Call"), QDialogButtonBox::ApplyRole);
|
||||
player_button_->setIcon(StockIcon("media-playback-start"));
|
||||
|
||||
// XXX Use recent settings instead
|
||||
if (parent) {
|
||||
resize(parent->width() * 4 / 5, parent->height() * 2 / 3);
|
||||
}
|
||||
|
||||
memset (&tapinfo_, 0, sizeof(tapinfo_));
|
||||
tapinfo_.tap_packet = tapPacket;
|
||||
tapinfo_.tap_draw = tapDraw;
|
||||
tapinfo_.tap_data = this;
|
||||
tapinfo_.callsinfos = g_queue_new();
|
||||
tapinfo_.h225_cstype = H225_OTHER;
|
||||
tapinfo_.fs_option = all_flows ? FLOW_ALL : FLOW_ONLY_INVITES; /* flow show option */
|
||||
tapinfo_.graph_analysis = sequence_analysis_info_new();
|
||||
tapinfo_.graph_analysis->type = SEQ_ANALYSIS_VOIP;
|
||||
|
||||
voip_calls_init_all_taps(&tapinfo_);
|
||||
|
||||
updateWidgets();
|
||||
|
||||
if (cap_file_) {
|
||||
tapinfo_.session = cap_file_->epan;
|
||||
cf_retap_packets(cap_file_);
|
||||
}
|
||||
}
|
||||
|
||||
VoipCallsDialog::~VoipCallsDialog()
|
||||
{
|
||||
delete ui;
|
||||
|
||||
voip_calls_remove_all_tap_listeners(&tapinfo_);
|
||||
sequence_analysis_info_free(tapinfo_.graph_analysis);
|
||||
}
|
||||
|
||||
void VoipCallsDialog::setCaptureFile(capture_file *cf)
|
||||
{
|
||||
if (!cf) { // We only want to know when the file closes.
|
||||
voip_calls_remove_all_tap_listeners(&tapinfo_);
|
||||
cap_file_ = NULL;
|
||||
tapinfo_.session = NULL;
|
||||
}
|
||||
emit captureFileChanged(cap_file_);
|
||||
updateWidgets();
|
||||
}
|
||||
|
||||
void VoipCallsDialog::contextMenuEvent(QContextMenuEvent *event)
|
||||
{
|
||||
ctx_menu_.exec(event->globalPos());
|
||||
}
|
||||
|
||||
void VoipCallsDialog::changeEvent(QEvent *event)
|
||||
{
|
||||
if (0 != event)
|
||||
{
|
||||
switch (event->type())
|
||||
{
|
||||
case QEvent::LanguageChange:
|
||||
ui->retranslateUi(this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
QDialog::changeEvent(event);
|
||||
}
|
||||
|
||||
//void VoipCallsDialog::tapReset(void *tapinfo_ptr)
|
||||
//{
|
||||
// Q_UNUSED(tapinfo_ptr)
|
||||
// voip_calls_tapinfo_t *tapinfo = (voip_calls_tapinfo_t *) tapinfo_ptr;
|
||||
//}
|
||||
|
||||
gboolean VoipCallsDialog::tapPacket(void *tapinfo_ptr, packet_info *pinfo, epan_dissect_t *, const void *data)
|
||||
{
|
||||
Q_UNUSED(tapinfo_ptr)
|
||||
Q_UNUSED(pinfo)
|
||||
Q_UNUSED(data)
|
||||
#ifdef QT_MULTIMEDIAWIDGETS_LIB
|
||||
// voip_calls_tapinfo_t *tapinfo = (voip_calls_tapinfo_t *) tapinfo_ptr;
|
||||
// add_rtp_packet for voip player.
|
||||
// return TRUE;
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void VoipCallsDialog::tapDraw(void *tapinfo_ptr)
|
||||
{
|
||||
voip_calls_tapinfo_t *tapinfo = (voip_calls_tapinfo_t *) tapinfo_ptr;
|
||||
|
||||
if (!tapinfo || !tapinfo->redraw) {
|
||||
return;
|
||||
}
|
||||
|
||||
VoipCallsDialog *voip_calls_dialog = static_cast<VoipCallsDialog *>(tapinfo->tap_data);
|
||||
if (voip_calls_dialog) {
|
||||
voip_calls_dialog->updateCalls();
|
||||
}
|
||||
}
|
||||
|
||||
void VoipCallsDialog::updateCalls()
|
||||
{
|
||||
GList *cur_call = g_queue_peek_nth_link(tapinfo_.callsinfos, ui->callTreeWidget->topLevelItemCount());
|
||||
ui->callTreeWidget->setSortingEnabled(false);
|
||||
|
||||
// Add any missing items
|
||||
while (cur_call && cur_call->data) {
|
||||
voip_calls_info_t *call_info = (voip_calls_info_t*) cur_call->data;
|
||||
new VoipCallsTreeWidgetItem(ui->callTreeWidget, call_info);
|
||||
cur_call = g_list_next(cur_call);
|
||||
}
|
||||
|
||||
// Fill in the tree
|
||||
QTreeWidgetItemIterator iter(ui->callTreeWidget);
|
||||
while (*iter) {
|
||||
VoipCallsTreeWidgetItem *vcti = static_cast<VoipCallsTreeWidgetItem*>(*iter);
|
||||
vcti->drawData();
|
||||
++iter;
|
||||
}
|
||||
|
||||
// Resize columns
|
||||
for (int i = 0; i < ui->callTreeWidget->columnCount(); i++) {
|
||||
ui->callTreeWidget->resizeColumnToContents(i);
|
||||
}
|
||||
|
||||
ui->callTreeWidget->setSortingEnabled(true);
|
||||
|
||||
updateWidgets();
|
||||
}
|
||||
|
||||
void VoipCallsDialog::updateWidgets()
|
||||
{
|
||||
bool selected = ui->callTreeWidget->selectedItems().count() > 0 ? true : false;
|
||||
bool have_ga_items = false;
|
||||
|
||||
if (tapinfo_.graph_analysis && tapinfo_.graph_analysis->items) {
|
||||
have_ga_items = true;
|
||||
}
|
||||
|
||||
foreach (QMenu *submenu, ctx_menu_.findChildren<QMenu*>()) {
|
||||
submenu->setEnabled(selected);
|
||||
}
|
||||
prepare_button_->setEnabled(selected && have_ga_items);
|
||||
sequence_button_->setEnabled(selected && have_ga_items);
|
||||
#if defined(QT_MULTIMEDIAWIDGETS_LIB) && 0 // We don't have a playback dialog yet.
|
||||
player_button_->setEnabled(selected && have_ga_items);
|
||||
#else
|
||||
player_button_->setEnabled(false);
|
||||
player_button_->setText(tr("No Audio"));
|
||||
#endif
|
||||
}
|
||||
|
||||
void VoipCallsDialog::prepareFilter()
|
||||
{
|
||||
if (ui->callTreeWidget->selectedItems().count() < 1 || !tapinfo_.graph_analysis) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString filter_str;
|
||||
QSet<guint16> selected_calls;
|
||||
|
||||
/* Build a new filter based on frame numbers */
|
||||
const char *or_prepend = "";
|
||||
foreach (QTreeWidgetItem *ti, ui->callTreeWidget->selectedItems()) {
|
||||
voip_calls_info_t *call_info = ti->data(0, Qt::UserRole).value<voip_calls_info_t*>();
|
||||
selected_calls << call_info->call_num;
|
||||
}
|
||||
|
||||
GList *cur_ga_item = g_queue_peek_nth_link(tapinfo_.graph_analysis->items, 0);
|
||||
while (cur_ga_item && cur_ga_item->data) {
|
||||
seq_analysis_item_t *ga_item = (seq_analysis_item_t*) cur_ga_item->data;
|
||||
if (selected_calls.contains(ga_item->conv_num)) {
|
||||
filter_str += QString("%1frame.number == %2").arg(or_prepend).arg(ga_item->fd->num);
|
||||
or_prepend = " or ";
|
||||
}
|
||||
cur_ga_item = g_list_next(cur_ga_item);
|
||||
}
|
||||
|
||||
#if 0
|
||||
// XXX The GTK+ UI falls back to building a filter based on protocols if the filter
|
||||
// length is too long. Leaving this here for the time being in case we need to do
|
||||
// the same in the Qt UI.
|
||||
const sip_calls_info_t *sipinfo;
|
||||
const isup_calls_info_t *isupinfo;
|
||||
const h323_calls_info_t *h323info;
|
||||
const h245_address_t *h245_add = NULL;
|
||||
const gcp_ctx_t* ctx;
|
||||
|
||||
if (filter_length < max_filter_length) {
|
||||
gtk_editable_insert_text(GTK_EDITABLE(main_display_filter_widget), filter_string_fwd->str, -1, &pos);
|
||||
} else {
|
||||
g_string_free(filter_string_fwd, TRUE);
|
||||
filter_string_fwd = g_string_new(filter_prepend);
|
||||
|
||||
g_string_append_printf(filter_string_fwd, "(");
|
||||
is_first = TRUE;
|
||||
/* Build a new filter based on protocol fields */
|
||||
lista = g_queue_peek_nth_link(voip_calls_get_info()->callsinfos, 0);
|
||||
while (lista) {
|
||||
listinfo = (voip_calls_info_t *)lista->data;
|
||||
if (listinfo->selected) {
|
||||
if (!is_first)
|
||||
g_string_append_printf(filter_string_fwd, " or ");
|
||||
switch (listinfo->protocol) {
|
||||
case VOIP_SIP:
|
||||
sipinfo = (sip_calls_info_t *)listinfo->prot_info;
|
||||
g_string_append_printf(filter_string_fwd,
|
||||
"(sip.Call-ID == \"%s\")",
|
||||
sipinfo->call_identifier
|
||||
);
|
||||
break;
|
||||
case VOIP_ISUP:
|
||||
isupinfo = (isup_calls_info_t *)listinfo->prot_info;
|
||||
g_string_append_printf(filter_string_fwd,
|
||||
"(isup.cic == %i and frame.number >= %i and frame.number <= %i and mtp3.network_indicator == %i and ((mtp3.dpc == %i) and (mtp3.opc == %i)) or ((mtp3.dpc == %i) and (mtp3.opc == %i)))",
|
||||
isupinfo->cic, listinfo->start_fd->num,
|
||||
listinfo->stop_fd->num,
|
||||
isupinfo->ni, isupinfo->dpc, isupinfo->opc,
|
||||
isupinfo->opc, isupinfo->dpc
|
||||
);
|
||||
break;
|
||||
case VOIP_H323:
|
||||
h323info = (h323_calls_info_t *)listinfo->prot_info;
|
||||
g_string_append_printf(filter_string_fwd,
|
||||
"((h225.guid == %s || q931.call_ref == %x:%x || q931.call_ref == %x:%x)",
|
||||
guid_to_ep_str(&h323info->guid[0]),
|
||||
(guint8) (h323info->q931_crv & 0x00ff),
|
||||
(guint8)((h323info->q931_crv & 0xff00)>>8),
|
||||
(guint8) (h323info->q931_crv2 & 0x00ff),
|
||||
(guint8)((h323info->q931_crv2 & 0xff00)>>8));
|
||||
listb = g_list_first(h323info->h245_list);
|
||||
while (listb) {
|
||||
h245_add = (h245_address_t *)listb->data;
|
||||
g_string_append_printf(filter_string_fwd,
|
||||
" || (ip.addr == %s && tcp.port == %d && h245)",
|
||||
ip_to_str((guint8 *)(h245_add->h245_address.data)), h245_add->h245_port);
|
||||
listb = g_list_next(listb);
|
||||
}
|
||||
g_string_append_printf(filter_string_fwd, ")");
|
||||
break;
|
||||
case TEL_H248:
|
||||
ctx = (gcp_ctx_t *)listinfo->prot_info;
|
||||
g_string_append_printf(filter_string_fwd,
|
||||
"(h248.ctx == 0x%x)", ctx->id);
|
||||
break;
|
||||
default:
|
||||
/* placeholder to assure valid display filter expression */
|
||||
g_string_append_printf(filter_string_fwd,
|
||||
"(frame)");
|
||||
break;
|
||||
}
|
||||
is_first = FALSE;
|
||||
}
|
||||
lista = g_list_next(lista);
|
||||
}
|
||||
|
||||
g_string_append_printf(filter_string_fwd, ")");
|
||||
gtk_editable_insert_text(GTK_EDITABLE(main_display_filter_widget), filter_string_fwd->str, -1, &pos);
|
||||
}
|
||||
#endif
|
||||
|
||||
emit updateFilter(filter_str);
|
||||
}
|
||||
|
||||
void VoipCallsDialog::showSequence()
|
||||
{
|
||||
if (!cap_file_) return;
|
||||
|
||||
QSet<guint16> selected_calls;
|
||||
foreach (QTreeWidgetItem *ti, ui->callTreeWidget->selectedItems()) {
|
||||
voip_calls_info_t *call_info = ti->data(0, Qt::UserRole).value<voip_calls_info_t*>();
|
||||
selected_calls << call_info->call_num;
|
||||
}
|
||||
|
||||
sequence_analysis_list_sort(tapinfo_.graph_analysis);
|
||||
GList *cur_ga_item = g_queue_peek_nth_link(tapinfo_.graph_analysis->items, 0);
|
||||
while (cur_ga_item && cur_ga_item->data) {
|
||||
seq_analysis_item_t *ga_item = (seq_analysis_item_t*) cur_ga_item->data;
|
||||
ga_item->display = selected_calls.contains(ga_item->conv_num);
|
||||
cur_ga_item = g_list_next(cur_ga_item);
|
||||
}
|
||||
|
||||
SequenceDialog *sequence_dialog = new SequenceDialog(this, cap_file_, tapinfo_.graph_analysis);
|
||||
// XXX This goes away when we close the VoIP Calls dialog.
|
||||
connect(sequence_dialog, SIGNAL(goToPacket(int)),
|
||||
this, SIGNAL(goToPacket(int)));
|
||||
connect(this, SIGNAL(captureFileChanged(capture_file*)),
|
||||
sequence_dialog, SLOT(setCaptureFile(capture_file*)));
|
||||
sequence_dialog->show();
|
||||
}
|
||||
|
||||
void VoipCallsDialog::on_callTreeWidget_itemActivated(QTreeWidgetItem *item, int)
|
||||
{
|
||||
voip_calls_info_t *call_info = item->data(0, Qt::UserRole).value<voip_calls_info_t*>();
|
||||
if (!call_info) {
|
||||
return;
|
||||
}
|
||||
emit goToPacket(call_info->start_fd->num);
|
||||
}
|
||||
|
||||
void VoipCallsDialog::on_callTreeWidget_itemSelectionChanged()
|
||||
{
|
||||
updateWidgets();
|
||||
}
|
||||
|
||||
void VoipCallsDialog::on_actionSelect_All_triggered()
|
||||
{
|
||||
ui->callTreeWidget->selectAll();
|
||||
}
|
||||
|
||||
void VoipCallsDialog::on_buttonBox_clicked(QAbstractButton *button)
|
||||
{
|
||||
if (button == prepare_button_) {
|
||||
prepareFilter();
|
||||
} else if (button == sequence_button_) {
|
||||
showSequence();
|
||||
}
|
||||
}
|
||||
|
||||
void VoipCallsDialog::on_buttonBox_helpRequested()
|
||||
{
|
||||
wsApp->helpTopicAction(HELP_TELEPHONY_VOIP_CALLS_DIALOG);
|
||||
}
|
||||
|
||||
/*
|
||||
* Editor modelines
|
||||
*
|
||||
* Local Variables:
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 8
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* ex: set shiftwidth=4 tabstop=8 expandtab:
|
||||
* :indentSize=4:tabSize=8:noTabs=true:
|
||||
*/
|
|
@ -0,0 +1,107 @@
|
|||
/* voip_calls_dialog.h
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef VOIP_CALLS_DIALOG_H
|
||||
#define VOIP_CALLS_DIALOG_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "cfile.h"
|
||||
|
||||
#include "ui/voip_calls.h"
|
||||
|
||||
#include <QDialog>
|
||||
#include <QMenu>
|
||||
|
||||
class QAbstractButton;
|
||||
class QTreeWidgetItem;
|
||||
|
||||
namespace Ui {
|
||||
class VoipCallsDialog;
|
||||
}
|
||||
|
||||
class QTreeWidgetItem;
|
||||
class VoipCallsDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit VoipCallsDialog(QWidget *parent = 0, capture_file *cf = NULL, bool all_flows = false);
|
||||
~VoipCallsDialog();
|
||||
|
||||
public slots:
|
||||
void setCaptureFile(capture_file *cf);
|
||||
|
||||
signals:
|
||||
void updateFilter(QString &filter, bool force = false);
|
||||
void captureFileChanged(capture_file *cf);
|
||||
void goToPacket(int packet_num);
|
||||
|
||||
protected:
|
||||
void contextMenuEvent(QContextMenuEvent *event);
|
||||
|
||||
protected slots:
|
||||
void changeEvent(QEvent* event);
|
||||
|
||||
private:
|
||||
Ui::VoipCallsDialog *ui;
|
||||
|
||||
capture_file *cap_file_;
|
||||
voip_calls_tapinfo_t tapinfo_;
|
||||
QPushButton *prepare_button_;
|
||||
QPushButton *sequence_button_;
|
||||
QPushButton *player_button_;
|
||||
QMenu ctx_menu_;
|
||||
|
||||
// Tap callbacks
|
||||
// static void tapReset(void *tapinfo_ptr);
|
||||
static gboolean tapPacket(void *tapinfo_ptr, packet_info *pinfo, epan_dissect_t *, const void *data);
|
||||
static void tapDraw(void *tapinfo_ptr);
|
||||
|
||||
void updateCalls();
|
||||
void updateWidgets();
|
||||
void prepareFilter();
|
||||
void showSequence();
|
||||
|
||||
private slots:
|
||||
void on_callTreeWidget_itemActivated(QTreeWidgetItem *item, int);
|
||||
void on_callTreeWidget_itemSelectionChanged();
|
||||
void on_actionSelect_All_triggered();
|
||||
void on_buttonBox_clicked(QAbstractButton *button);
|
||||
void on_buttonBox_helpRequested();
|
||||
};
|
||||
|
||||
#endif // VOIP_CALLS_DIALOG_H
|
||||
|
||||
/*
|
||||
* Editor modelines
|
||||
*
|
||||
* Local Variables:
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 8
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*
|
||||
* ex: set shiftwidth=4 tabstop=8 expandtab:
|
||||
* :indentSize=4:tabSize=8:noTabs=true:
|
||||
*/
|
|
@ -0,0 +1,143 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>VoipCallsDialog</class>
|
||||
<widget class="QDialog" name="VoipCallsDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>750</width>
|
||||
<height>430</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="callTreeWidget">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="textElideMode">
|
||||
<enum>Qt::ElideMiddle</enum>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="itemsExpandable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Start Time</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Stop Time</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Initial Speaker</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>From</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>To</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Protocol</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Packets</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>State</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Comments</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="hintLabel">
|
||||
<property name="text">
|
||||
<string><small></small></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<action name="actionSelect_All">
|
||||
<property name="text">
|
||||
<string>Select &All</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Select all calls</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+A</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>VoipCallsDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>VoipCallsDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
|
@ -256,8 +256,6 @@ sequence_analysis_list_get(capture_file *cf, seq_analysis_info_t *sainfo)
|
|||
case SEQ_ANALYSIS_VOIP:
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
cf_retap_packets(cf);
|
||||
|
@ -278,6 +276,31 @@ static void sequence_analysis_item_free(gpointer data)
|
|||
g_free(data);
|
||||
}
|
||||
|
||||
|
||||
/* compare two list entries by packet no */
|
||||
static gint
|
||||
sequence_analysis_sort_compare(gconstpointer a, gconstpointer b, gpointer user_data _U_)
|
||||
{
|
||||
const seq_analysis_item_t *entry_a = (const seq_analysis_item_t *)a;
|
||||
const seq_analysis_item_t *entry_b = (const seq_analysis_item_t *)b;
|
||||
|
||||
if(entry_a->fd->num < entry_b->fd->num)
|
||||
return -1;
|
||||
|
||||
if(entry_a->fd->num > entry_b->fd->num)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sequence_analysis_list_sort(seq_analysis_info_t *sainfo)
|
||||
{
|
||||
if (!sainfo) return;
|
||||
g_queue_sort(sainfo->items, sequence_analysis_sort_compare, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
sequence_analysis_list_free(seq_analysis_info_t *sainfo)
|
||||
{
|
||||
|
@ -380,7 +403,7 @@ static void overwrite (GString *gstr, char *text_to_insert, guint32 p1, guint32
|
|||
* and Return -2 if the array is full
|
||||
*/
|
||||
/****************************************************************************/
|
||||
static gint add_or_get_node(seq_analysis_info_t *sainfo, address *node) {
|
||||
static guint add_or_get_node(seq_analysis_info_t *sainfo, address *node) {
|
||||
guint i;
|
||||
|
||||
if (node->type == AT_NONE) return NODE_OVERFLOW;
|
||||
|
@ -409,8 +432,8 @@ static void sequence_analysis_get_nodes_item_proc(gpointer data, gpointer user_d
|
|||
struct sainfo_counter *sc = (struct sainfo_counter *)user_data;
|
||||
if (gai->display) {
|
||||
(sc->num_items)++;
|
||||
gai->src_node = (guint16)add_or_get_node(sc->sainfo, &(gai->src_addr));
|
||||
gai->dst_node = (guint16)add_or_get_node(sc->sainfo, &(gai->dst_addr));
|
||||
gai->src_node = add_or_get_node(sc->sainfo, &(gai->src_addr));
|
||||
gai->dst_node = add_or_get_node(sc->sainfo, &(gai->dst_addr));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -60,8 +60,8 @@ typedef struct _seq_analysis_item {
|
|||
gchar *comment; /**< a comment that appears at the right of the graph */
|
||||
guint16 conv_num; /**< the conversation number, each conversation will be colored */
|
||||
gboolean display; /**< indicate if the packet is displayed or not in the graph */
|
||||
guint16 src_node; /**< this is used by graph_analysis.c to identify the node */
|
||||
guint16 dst_node; /**< a node is an IP address that will be displayed in columns */
|
||||
guint src_node; /**< this is used by graph_analysis.c to identify the node */
|
||||
guint dst_node; /**< a node is an IP address that will be displayed in columns */
|
||||
guint16 line_style; /**< the arrow line width in pixels*/
|
||||
} seq_analysis_item_t;
|
||||
|
||||
|
@ -94,6 +94,8 @@ void sequence_analysis_info_free(seq_analysis_info_t * sainfo);
|
|||
*/
|
||||
void sequence_analysis_list_get(capture_file *cf, seq_analysis_info_t *sainfo);
|
||||
|
||||
void sequence_analysis_list_sort(seq_analysis_info_t *sainfo);
|
||||
|
||||
/** Free the segment list
|
||||
*
|
||||
* @param sainfo Sequence analysis information.
|
||||
|
|
|
@ -34,11 +34,22 @@
|
|||
#ifndef __VOIP_CALLS_H__
|
||||
#define __VOIP_CALLS_H__
|
||||
|
||||
/** @file
|
||||
* "VoIP Calls" dialog box common routines.
|
||||
* @ingroup main_ui_group
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#include <glib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "epan/address.h"
|
||||
#include "epan/packet.h"
|
||||
#include "epan/guid-utils.h"
|
||||
#include "epan/tap.h"
|
||||
#include "epan/tap-voip.h"
|
||||
|
||||
#include "ui/tap-sequence-analysis.h"
|
||||
|
@ -160,7 +171,7 @@ typedef struct _voip_calls_info {
|
|||
nstime_t start_rel_ts;
|
||||
frame_data *stop_fd;
|
||||
nstime_t stop_rel_ts;
|
||||
gboolean selected;
|
||||
gboolean selected; /* GTK+ only */
|
||||
|
||||
} voip_calls_info_t;
|
||||
|
||||
|
@ -176,6 +187,7 @@ typedef struct _voip_calls_tapinfo {
|
|||
tap_reset_cb tap_reset; /**< tap reset callback */
|
||||
tap_packet_cb tap_packet; /**< tap per-packet callback */
|
||||
tap_draw_cb tap_draw; /**< tap draw callback */
|
||||
void *tap_data; /**< data for tap callbacks */
|
||||
int ncalls; /**< number of call */
|
||||
GQueue* callsinfos; /**< queue with all calls */
|
||||
GHashTable* callsinfo_hashtable[1]; /**< array of hashes per voip protocol; currently only the one for SIP is used */
|
||||
|
@ -237,6 +249,10 @@ void voip_calls_remove_all_tap_listeners(voip_calls_tapinfo_t *tap_id_base);
|
|||
*/
|
||||
void voip_calls_reset_all_taps(voip_calls_tapinfo_t *tapinfo);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __VOIP_CALLS_H__ */
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue