2014-11-19 00:21:42 +00:00
/* voip_calls_dialog.cpp
*
* Wireshark - Network traffic analyzer
* By Gerald Combs < gerald @ wireshark . org >
* Copyright 1998 Gerald Combs
*
2018-04-30 07:47:58 +00:00
* SPDX - License - Identifier : GPL - 2.0 - or - later
*/
2014-11-19 00:21:42 +00:00
# include "voip_calls_dialog.h"
2015-06-25 16:17:03 +00:00
# include <ui_voip_calls_dialog.h>
2014-11-19 00:21:42 +00:00
# include "file.h"
# include "epan/addr_resolv.h"
# include "epan/dissectors/packet-h225.h"
2014-12-13 00:51:40 +00:00
# include "ui/rtp_stream.h"
2020-12-30 08:51:00 +00:00
# include "ui/rtp_stream_id.h"
2014-11-19 00:21:42 +00:00
2017-07-25 14:15:18 +00:00
# include <ui/qt/utils/qt_ui_utils.h>
2014-12-13 00:51:40 +00:00
# include "rtp_player_dialog.h"
2014-11-19 00:21:42 +00:00
# include "sequence_dialog.h"
2017-07-25 14:15:18 +00:00
# include <ui/qt/utils/stock_icon.h>
2014-11-19 00:21:42 +00:00
# include "wireshark_application.h"
2017-07-25 14:47:16 +00:00
# include <ui/qt/models/voip_calls_info_model.h>
2014-11-19 00:21:42 +00:00
2016-06-17 10:39:09 +00:00
# include <QClipboard>
2014-11-19 00:21:42 +00:00
# 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
2017-02-13 00:36:58 +00:00
// - Add filter for quickly searching through list?
2014-11-19 00:21:42 +00:00
// Bugs:
// - Preparing a filter overwrites the existing filter. The GTK+ UI appends.
// We'll probably have to add an "append" parameter to MainWindow::filterPackets.
2014-12-13 00:51:40 +00:00
enum { voip_calls_type_ = 1000 } ;
2014-12-29 19:42:01 +00:00
VoipCallsDialog : : VoipCallsDialog ( QWidget & parent , CaptureFile & cf , bool all_flows ) :
WiresharkDialog ( parent , cf ) ,
2015-02-14 00:18:57 +00:00
ui ( new Ui : : VoipCallsDialog ) ,
2020-01-05 22:33:04 +00:00
parent_ ( parent ) ,
voip_calls_tap_listeners_removed_ ( false )
2014-11-19 00:21:42 +00:00
{
ui - > setupUi ( this ) ;
2016-02-28 18:23:20 +00:00
loadGeometry ( parent . width ( ) * 4 / 5 , parent . height ( ) * 2 / 3 ) ;
2017-02-13 00:36:58 +00:00
// Create the model that stores the actual data and the proxy model that is
// responsible for sorting and filtering data in the display.
call_infos_model_ = new VoipCallsInfoModel ( this ) ;
2017-03-16 23:51:08 +00:00
cache_model_ = new CacheProxyModel ( this ) ;
cache_model_ - > setSourceModel ( call_infos_model_ ) ;
2017-02-13 00:36:58 +00:00
sorted_model_ = new VoipCallsInfoSortedModel ( this ) ;
2017-03-16 23:51:08 +00:00
sorted_model_ - > setSourceModel ( cache_model_ ) ;
2017-02-13 00:36:58 +00:00
ui - > callTreeView - > setModel ( sorted_model_ ) ;
connect ( ui - > callTreeView - > selectionModel ( ) , SIGNAL ( selectionChanged ( QItemSelection , QItemSelection ) ) ,
this , SLOT ( updateWidgets ( ) ) ) ;
ui - > callTreeView - > sortByColumn ( VoipCallsInfoModel : : StartTime , Qt : : AscendingOrder ) ;
2014-12-29 19:42:01 +00:00
setWindowSubtitle ( all_flows ? tr ( " SIP Flows " ) : tr ( " VoIP Calls " ) ) ;
2014-11-19 00:21:42 +00:00
prepare_button_ = ui - > buttonBox - > addButton ( tr ( " Prepare Filter " ) , QDialogButtonBox : : ApplyRole ) ;
sequence_button_ = ui - > buttonBox - > addButton ( tr ( " Flow Sequence " ) , QDialogButtonBox : : ApplyRole ) ;
2015-10-08 18:31:42 +00:00
player_button_ = RtpPlayerDialog : : addPlayerButton ( ui - > buttonBox ) ;
2014-11-19 00:21:42 +00:00
2019-11-17 19:02:20 +00:00
connect ( ui - > todCheckBox , & QAbstractButton : : toggled , this , & VoipCallsDialog : : switchTimeOfDay ) ;
2019-08-02 18:39:13 +00:00
2016-06-16 21:09:28 +00:00
copy_button_ = ui - > buttonBox - > addButton ( tr ( " Copy " ) , QDialogButtonBox : : ApplyRole ) ;
2017-09-17 21:48:12 +00:00
QMenu * copy_menu = new QMenu ( copy_button_ ) ;
2016-06-16 21:09:28 +00:00
QAction * ca ;
ca = copy_menu - > addAction ( tr ( " as CSV " ) ) ;
2019-08-02 18:39:13 +00:00
connect ( ca , SIGNAL ( triggered ( ) ) , this , SLOT ( copyAsCSV ( ) ) ) ;
2016-06-16 21:09:28 +00:00
ca = copy_menu - > addAction ( tr ( " as YAML " ) ) ;
2019-08-02 18:39:13 +00:00
connect ( ca , SIGNAL ( triggered ( ) ) , this , SLOT ( copyAsYAML ( ) ) ) ;
2016-06-16 21:09:28 +00:00
copy_button_ - > setMenu ( copy_menu ) ;
2021-01-01 15:51:47 +00:00
connect ( & cap_file_ , SIGNAL ( captureEvent ( CaptureEvent ) ) ,
this , SLOT ( captureEvent ( CaptureEvent ) ) ) ;
2016-06-16 21:09:28 +00:00
2014-11-19 00:21:42 +00:00
memset ( & tapinfo_ , 0 , sizeof ( tapinfo_ ) ) ;
tapinfo_ . tap_packet = tapPacket ;
2020-12-13 13:04:11 +00:00
tapinfo_ . tap_reset = tapReset ;
2014-11-19 00:21:42 +00:00
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 ( ) ;
2017-09-16 14:52:23 +00:00
tapinfo_ . graph_analysis - > name = " voip " ;
2015-11-15 21:57:43 +00:00
sequence_info_ = new SequenceInfo ( tapinfo_ . graph_analysis ) ;
2020-12-31 00:00:57 +00:00
shown_callsinfos_ = g_queue_new ( ) ;
2014-11-19 00:21:42 +00:00
voip_calls_init_all_taps ( & tapinfo_ ) ;
2021-01-01 15:51:47 +00:00
if ( cap_file_ . capFile ( ) - > dfilter ) {
// Activate display filter checking
tapinfo_ . apply_display_filter = true ;
ui - > displayFilterCheckBox - > setChecked ( true ) ;
}
2014-11-19 00:21:42 +00:00
updateWidgets ( ) ;
2015-09-04 16:23:51 +00:00
if ( cap_file_ . isValid ( ) ) {
tapinfo_ . session = cap_file_ . capFile ( ) - > epan ;
cap_file_ . delayedRetapPackets ( ) ;
}
2014-11-19 00:21:42 +00:00
}
VoipCallsDialog : : ~ VoipCallsDialog ( )
{
delete ui ;
2015-10-25 18:24:06 +00:00
voip_calls_reset_all_taps ( & tapinfo_ ) ;
2020-01-05 22:33:04 +00:00
if ( ! voip_calls_tap_listeners_removed_ ) {
voip_calls_remove_all_tap_listeners ( & tapinfo_ ) ;
voip_calls_tap_listeners_removed_ = true ;
}
2015-11-15 21:57:43 +00:00
sequence_info_ - > unref ( ) ;
2015-10-25 18:24:06 +00:00
g_queue_free ( tapinfo_ . callsinfos ) ;
2020-12-31 00:00:57 +00:00
// We don't need to clear shown_callsinfos_ data, it was shared
// with tapinfo_.callsinfos and was cleared
// during voip_calls_reset_all_taps
g_queue_free ( shown_callsinfos_ ) ;
2014-11-19 00:21:42 +00:00
}
2018-01-14 20:37:16 +00:00
void VoipCallsDialog : : removeTapListeners ( )
2015-12-06 21:29:53 +00:00
{
2020-01-05 22:33:04 +00:00
if ( ! voip_calls_tap_listeners_removed_ ) {
voip_calls_remove_all_tap_listeners ( & tapinfo_ ) ;
voip_calls_tap_listeners_removed_ = true ;
}
2018-01-14 20:37:16 +00:00
WiresharkDialog : : removeTapListeners ( ) ;
2015-12-06 21:29:53 +00:00
}
2014-12-29 19:42:01 +00:00
void VoipCallsDialog : : captureFileClosing ( )
2014-11-19 00:21:42 +00:00
{
2017-03-16 23:51:08 +00:00
// The time formatting is currently provided by VoipCallsInfoModel, but when
// the cache is active, the ToD cannot be modified.
ui - > todCheckBox - > setEnabled ( false ) ;
cache_model_ - > setSourceModel ( NULL ) ;
2020-01-05 22:33:04 +00:00
if ( ! voip_calls_tap_listeners_removed_ ) {
voip_calls_remove_all_tap_listeners ( & tapinfo_ ) ;
voip_calls_tap_listeners_removed_ = true ;
}
2014-12-29 19:42:01 +00:00
tapinfo_ . session = NULL ;
WiresharkDialog : : captureFileClosing ( ) ;
2014-11-19 00:21:42 +00:00
}
void VoipCallsDialog : : contextMenuEvent ( QContextMenuEvent * event )
{
2019-08-02 18:39:13 +00:00
bool selected = ui - > callTreeView - > selectionModel ( ) - > hasSelection ( ) ;
2019-11-17 19:02:20 +00:00
if ( ! selected )
2019-08-02 18:39:13 +00:00
return ;
QMenu popupMenu ;
QAction * action = popupMenu . addAction ( tr ( " Select &All " ) , this , SLOT ( selectAll ( ) ) ) ;
action - > setToolTip ( tr ( " Select all calls " ) ) ;
popupMenu . addSeparator ( ) ;
action = popupMenu . addAction ( tr ( " Display time as time of day " ) , this , SLOT ( switchTimeOfDay ( ) ) ) ;
action - > setCheckable ( true ) ;
action - > setChecked ( call_infos_model_ - > timeOfDay ( ) ) ;
popupMenu . addSeparator ( ) ;
action = popupMenu . addAction ( tr ( " Copy as CSV " ) , this , SLOT ( copyAsCSV ( ) ) ) ;
action - > setToolTip ( tr ( " Copy stream list as CSV. " ) ) ;
action = popupMenu . addAction ( tr ( " Copy as YAML " ) , this , SLOT ( copyAsYAML ( ) ) ) ;
action - > setToolTip ( tr ( " Copy stream list as YAML. " ) ) ;
popupMenu . exec ( event - > globalPos ( ) ) ;
2014-11-19 00:21:42 +00:00
}
void VoipCallsDialog : : changeEvent ( QEvent * event )
{
if ( 0 ! = event )
{
switch ( event - > type ( ) )
{
case QEvent : : LanguageChange :
ui - > retranslateUi ( this ) ;
break ;
default :
break ;
}
}
QDialog : : changeEvent ( event ) ;
}
2021-01-01 15:51:47 +00:00
void VoipCallsDialog : : captureEvent ( CaptureEvent e )
{
if ( e . captureContext ( ) = = CaptureEvent : : Retap )
{
switch ( e . eventType ( ) )
{
case CaptureEvent : : Started :
ui - > displayFilterCheckBox - > setEnabled ( false ) ;
break ;
case CaptureEvent : : Finished :
ui - > displayFilterCheckBox - > setEnabled ( true ) ;
break ;
default :
break ;
}
}
}
2020-12-13 13:04:11 +00:00
void VoipCallsDialog : : tapReset ( void * tapinfo_ptr )
{
voip_calls_tapinfo_t * tapinfo = static_cast < voip_calls_tapinfo_t * > ( tapinfo_ptr ) ;
VoipCallsDialog * voip_calls_dialog = static_cast < VoipCallsDialog * > ( tapinfo - > tap_data ) ;
2020-12-31 00:00:57 +00:00
// Create new callsinfos queue in tapinfo. Current callsinfos are
// in shown_callsinfos_.
voip_calls_dialog - > tapinfo_ . callsinfos = g_queue_new ( ) ;
2020-12-13 13:04:11 +00:00
voip_calls_reset_all_taps ( tapinfo ) ;
2020-12-29 15:52:33 +00:00
// Leave old graph_analysis as is and allocate new one
voip_calls_dialog - > sequence_info_ - > unref ( ) ;
voip_calls_dialog - > tapinfo_ . graph_analysis = sequence_analysis_info_new ( ) ;
voip_calls_dialog - > tapinfo_ . graph_analysis - > name = " voip " ;
voip_calls_dialog - > sequence_info_ = new SequenceInfo ( voip_calls_dialog - > tapinfo_ . graph_analysis ) ;
2020-12-13 13:04:11 +00:00
}
2014-11-19 00:21:42 +00:00
2019-01-01 03:36:12 +00:00
tap_packet_status VoipCallsDialog : : tapPacket ( void * , packet_info * , epan_dissect_t * , const void * )
2014-11-19 00:21:42 +00:00
{
2014-12-13 00:51:40 +00:00
# ifdef QT_MULTIMEDIA_LIB
2014-11-19 00:21:42 +00:00
// voip_calls_tapinfo_t *tapinfo = (voip_calls_tapinfo_t *) tapinfo_ptr;
// add_rtp_packet for voip player.
2019-01-01 03:36:12 +00:00
// return TAP_PACKET_REDRAW;
2014-11-19 00:21:42 +00:00
# endif
2019-01-01 03:36:12 +00:00
return TAP_PACKET_DONT_REDRAW ;
2014-11-19 00:21:42 +00:00
}
void VoipCallsDialog : : tapDraw ( void * tapinfo_ptr )
{
2019-08-14 08:18:51 +00:00
voip_calls_tapinfo_t * tapinfo = static_cast < voip_calls_tapinfo_t * > ( tapinfo_ptr ) ;
2014-11-19 00:21:42 +00:00
if ( ! tapinfo | | ! tapinfo - > redraw ) {
return ;
}
2014-12-13 00:51:40 +00:00
GList * graph_item = g_queue_peek_nth_link ( tapinfo - > graph_analysis - > items , 0 ) ;
2019-08-14 08:18:51 +00:00
for ( ; graph_item ; graph_item = gxx_list_next ( graph_item ) ) {
for ( GList * rsi_entry = g_list_first ( tapinfo - > rtpstream_list ) ; rsi_entry ; rsi_entry = gxx_list_next ( rsi_entry ) ) {
seq_analysis_item_t * sai = gxx_list_data ( seq_analysis_item_t * , graph_item ) ;
rtpstream_info_t * rsi = gxx_list_data ( rtpstream_info_t * , rsi_entry ) ;
2014-12-13 00:51:40 +00:00
2015-10-25 21:52:30 +00:00
if ( rsi - > start_fd - > num = = sai - > frame_number ) {
2014-12-13 00:51:40 +00:00
rsi - > call_num = sai - > conv_num ;
2015-12-06 21:29:53 +00:00
// VOIP_CALLS_DEBUG("setting conv num %u for frame %u", sai->conv_num, sai->frame_number);
2014-12-13 00:51:40 +00:00
}
}
}
2014-11-19 00:21:42 +00:00
VoipCallsDialog * voip_calls_dialog = static_cast < VoipCallsDialog * > ( tapinfo - > tap_data ) ;
if ( voip_calls_dialog ) {
voip_calls_dialog - > updateCalls ( ) ;
}
}
2020-12-31 13:14:14 +00:00
gint VoipCallsDialog : : compareCallNums ( gconstpointer a , gconstpointer b )
2020-12-31 00:00:57 +00:00
{
voip_calls_info_t * call_a = ( voip_calls_info_t * ) a ;
voip_calls_info_t * call_b = ( voip_calls_info_t * ) b ;
2020-12-31 13:14:14 +00:00
return ( call_a - > call_num ! = call_b - > call_num ) ;
2020-12-31 00:00:57 +00:00
}
2014-11-19 00:21:42 +00:00
void VoipCallsDialog : : updateCalls ( )
{
2020-12-31 00:00:57 +00:00
voip_calls_info_t * new_callsinfo ;
voip_calls_info_t * old_callsinfo ;
GList * found ;
2017-02-13 00:36:58 +00:00
ui - > callTreeView - > setSortingEnabled ( false ) ;
2014-11-19 00:21:42 +00:00
2020-12-31 00:00:57 +00:00
// Merge new callsinfos with old ones
// It keeps list of calls visible including selected items
GList * list = g_queue_peek_nth_link ( tapinfo_ . callsinfos , 0 ) ;
while ( list ) {
// Find new callsinfo
new_callsinfo = gxx_list_data ( voip_calls_info_t * , list ) ;
2020-12-31 13:14:14 +00:00
found = g_queue_find_custom ( shown_callsinfos_ , new_callsinfo , VoipCallsDialog : : compareCallNums ) ;
2020-12-31 00:00:57 +00:00
if ( ! found ) {
// New call, add it to list for show
g_queue_push_tail ( shown_callsinfos_ , new_callsinfo ) ;
} else {
// Existing call
old_callsinfo = ( voip_calls_info_t * ) found - > data ;
if ( new_callsinfo ! = old_callsinfo ) {
// Replace it
voip_calls_free_callsinfo ( old_callsinfo ) ;
found - > data = new_callsinfo ;
}
}
list = gxx_list_next ( list ) ;
}
// Update model
call_infos_model_ - > updateCalls ( shown_callsinfos_ ) ;
2014-11-19 00:21:42 +00:00
// Resize columns
2017-02-13 00:36:58 +00:00
for ( int i = 0 ; i < call_infos_model_ - > columnCount ( ) ; i + + ) {
ui - > callTreeView - > resizeColumnToContents ( i ) ;
2014-11-19 00:21:42 +00:00
}
2017-02-13 00:36:58 +00:00
ui - > callTreeView - > setSortingEnabled ( true ) ;
2014-11-19 00:21:42 +00:00
updateWidgets ( ) ;
}
void VoipCallsDialog : : updateWidgets ( )
{
2017-02-13 00:36:58 +00:00
bool selected = ui - > callTreeView - > selectionModel ( ) - > hasSelection ( ) ;
2014-11-19 00:21:42 +00:00
bool have_ga_items = false ;
if ( tapinfo_ . graph_analysis & & tapinfo_ . graph_analysis - > items ) {
have_ga_items = true ;
}
prepare_button_ - > setEnabled ( selected & & have_ga_items ) ;
sequence_button_ - > setEnabled ( selected & & have_ga_items ) ;
2014-12-13 00:51:40 +00:00
# if defined(QT_MULTIMEDIA_LIB)
2014-11-19 00:21:42 +00:00
player_button_ - > setEnabled ( selected & & have_ga_items ) ;
# else
player_button_ - > setEnabled ( false ) ;
player_button_ - > setText ( tr ( " No Audio " ) ) ;
# endif
}
void VoipCallsDialog : : prepareFilter ( )
{
2017-02-13 00:36:58 +00:00
if ( ! ui - > callTreeView - > selectionModel ( ) - > hasSelection ( ) | | ! tapinfo_ . graph_analysis ) {
2014-11-19 00:21:42 +00:00
return ;
}
QString filter_str ;
QSet < guint16 > selected_calls ;
2018-06-02 12:43:40 +00:00
QString frame_numbers ;
2019-10-28 16:07:14 +00:00
QList < int > rows ;
2014-11-19 00:21:42 +00:00
/* Build a new filter based on frame numbers */
2017-02-13 00:36:58 +00:00
foreach ( QModelIndex index , ui - > callTreeView - > selectionModel ( ) - > selectedIndexes ( ) ) {
2019-11-17 19:02:20 +00:00
if ( index . isValid ( ) & & ! rows . contains ( index . row ( ) ) )
2019-10-28 16:07:14 +00:00
{
voip_calls_info_t * call_info = VoipCallsInfoModel : : indexToCallInfo ( index ) ;
if ( ! call_info ) {
return ;
}
selected_calls < < call_info - > call_num ;
rows < < index . row ( ) ;
2015-10-16 13:00:24 +00:00
}
2014-11-19 00:21:42 +00:00
}
GList * cur_ga_item = g_queue_peek_nth_link ( tapinfo_ . graph_analysis - > items , 0 ) ;
while ( cur_ga_item & & cur_ga_item - > data ) {
2019-08-14 08:18:51 +00:00
seq_analysis_item_t * ga_item = gxx_list_data ( seq_analysis_item_t * , cur_ga_item ) ;
2014-11-19 00:21:42 +00:00
if ( selected_calls . contains ( ga_item - > conv_num ) ) {
2018-06-02 12:43:40 +00:00
frame_numbers + = QString ( " %1 " ) . arg ( ga_item - > frame_number ) ;
2014-11-19 00:21:42 +00:00
}
2019-08-14 08:18:51 +00:00
cur_ga_item = gxx_list_next ( cur_ga_item ) ;
2014-11-19 00:21:42 +00:00
}
2018-06-02 12:43:40 +00:00
if ( ! frame_numbers . isEmpty ( ) ) {
frame_numbers . chop ( 1 ) ;
filter_str = QString ( " frame.number in {%1} or rtp.setup-frame in {%1} " ) . arg ( frame_numbers ) ;
}
2014-11-19 00:21:42 +00:00
#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 ;
2015-01-29 21:55:18 +00:00
char * guid_str ;
2014-11-19 00:21:42 +00:00
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 ) {
2019-08-14 08:18:51 +00:00
listinfo = gxx_list_data ( voip_calls_info_t * , lista ) ;
2014-11-19 00:21:42 +00:00
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 :
2015-01-29 21:55:18 +00:00
{
2014-11-19 00:21:42 +00:00
h323info = ( h323_calls_info_t * ) listinfo - > prot_info ;
2015-01-08 00:24:52 +00:00
guid_str = guid_to_str ( NULL , & h323info - > guid [ 0 ] ) ;
2014-11-19 00:21:42 +00:00
g_string_append_printf ( filter_string_fwd ,
" ((h225.guid == %s || q931.call_ref == %x:%x || q931.call_ref == %x:%x) " ,
2015-01-08 00:24:52 +00:00
guid_str ,
2014-11-19 00:21:42 +00:00
( 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 ) ;
2015-01-08 00:24:52 +00:00
wmem_free ( NULL , guid_str ) ;
2014-11-19 00:21:42 +00:00
while ( listb ) {
2019-08-14 08:18:51 +00:00
h245_add = gxx_list_data ( h245_address_t * , listb ) ;
2014-11-19 00:21:42 +00:00
g_string_append_printf ( filter_string_fwd ,
" || (ip.addr == %s && tcp.port == %d && h245) " ,
2015-01-29 21:55:18 +00:00
address_to_qstring ( & h245_add - > h245_address ) , h245_add - > h245_port ) ;
2019-08-14 08:18:51 +00:00
listb = gxx_list_next ( listb ) ;
2014-11-19 00:21:42 +00:00
}
g_string_append_printf ( filter_string_fwd , " ) " ) ;
2015-01-29 21:55:18 +00:00
}
2014-11-19 00:21:42 +00:00
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 ;
}
2019-08-14 08:18:51 +00:00
lista = gxx_list_next ( lista ) ;
2014-11-19 00:21:42 +00:00
}
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 ( )
{
2014-12-29 19:42:01 +00:00
if ( file_closed_ ) return ;
2014-11-19 00:21:42 +00:00
QSet < guint16 > selected_calls ;
2017-02-13 00:36:58 +00:00
foreach ( QModelIndex index , ui - > callTreeView - > selectionModel ( ) - > selectedIndexes ( ) ) {
voip_calls_info_t * call_info = VoipCallsInfoModel : : indexToCallInfo ( index ) ;
2015-10-16 13:00:24 +00:00
if ( ! call_info ) {
return ;
}
2014-11-19 00:21:42 +00:00
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 ) {
2019-08-14 08:18:51 +00:00
seq_analysis_item_t * ga_item = gxx_list_data ( seq_analysis_item_t * , cur_ga_item ) ;
2014-11-19 00:21:42 +00:00
ga_item - > display = selected_calls . contains ( ga_item - > conv_num ) ;
2019-08-14 08:18:51 +00:00
cur_ga_item = gxx_list_next ( cur_ga_item ) ;
2014-11-19 00:21:42 +00:00
}
2015-11-15 21:57:43 +00:00
SequenceDialog * sequence_dialog = new SequenceDialog ( parent_ , cap_file_ , sequence_info_ ) ;
2020-12-30 08:51:00 +00:00
connect ( sequence_dialog , SIGNAL ( selectRtpStream ( rtpstream_id_t * ) ) , this , SLOT ( selectRtpStreamPassIn ( rtpstream_id_t * ) ) ) ;
connect ( sequence_dialog , SIGNAL ( deselectRtpStream ( rtpstream_id_t * ) ) , this , SLOT ( deselectRtpStreamPassIn ( rtpstream_id_t * ) ) ) ;
connect ( sequence_dialog , SIGNAL ( openRtpStreamDialog ( ) ) , this , SLOT ( openRtpStreamDialogPassIn ( ) ) ) ;
2019-10-02 14:29:35 +00:00
sequence_dialog - > setAttribute ( Qt : : WA_DeleteOnClose ) ;
2014-11-19 00:21:42 +00:00
sequence_dialog - > show ( ) ;
}
2014-12-13 00:51:40 +00:00
void VoipCallsDialog : : showPlayer ( )
{
# ifdef QT_MULTIMEDIA_LIB
2019-10-02 14:29:35 +00:00
RtpPlayerDialog * rtp_player_dialog = new RtpPlayerDialog ( * this , cap_file_ ) ;
2014-12-13 00:51:40 +00:00
2017-02-13 00:36:58 +00:00
foreach ( QModelIndex index , ui - > callTreeView - > selectionModel ( ) - > selectedIndexes ( ) ) {
voip_calls_info_t * vci = VoipCallsInfoModel : : indexToCallInfo ( index ) ;
if ( ! vci ) continue ;
2019-08-14 08:18:51 +00:00
for ( GList * rsi_entry = g_list_first ( tapinfo_ . rtpstream_list ) ; rsi_entry ; rsi_entry = gxx_list_next ( rsi_entry ) ) {
rtpstream_info_t * rsi = gxx_list_data ( rtpstream_info_t * , rsi_entry ) ;
2014-12-13 00:51:40 +00:00
if ( ! rsi ) continue ;
//VOIP_CALLS_DEBUG("checking call %u, start frame %u == stream call %u, start frame %u, setup frame %u",
2017-02-13 00:36:58 +00:00
// vci->call_num, vci->start_fd->num,
2014-12-13 00:51:40 +00:00
// rsi->call_num, rsi->start_fd->num, rsi->setup_frame_number);
2019-08-14 08:18:51 +00:00
if ( vci - > call_num = = static_cast < guint > ( rsi - > call_num ) ) {
2017-02-13 00:36:58 +00:00
//VOIP_CALLS_DEBUG("adding call number %u", vci->call_num);
2019-10-02 14:29:35 +00:00
rtp_player_dialog - > addRtpStream ( rsi ) ;
2014-12-13 00:51:40 +00:00
}
}
}
2019-10-02 14:29:35 +00:00
connect ( rtp_player_dialog , SIGNAL ( goToPacket ( int ) ) , this , SIGNAL ( goToPacket ( int ) ) ) ;
2014-12-13 00:51:40 +00:00
2019-10-02 14:29:35 +00:00
rtp_player_dialog - > setWindowModality ( Qt : : ApplicationModal ) ;
rtp_player_dialog - > setAttribute ( Qt : : WA_DeleteOnClose ) ;
2020-01-01 23:38:35 +00:00
rtp_player_dialog - > setMarkers ( ) ;
2019-10-02 14:29:35 +00:00
rtp_player_dialog - > show ( ) ;
2014-12-13 00:51:40 +00:00
# endif // QT_MULTIMEDIA_LIB
}
2016-06-16 21:09:28 +00:00
QList < QVariant > VoipCallsDialog : : streamRowData ( int row ) const
{
QList < QVariant > row_data ;
2017-02-13 00:36:58 +00:00
if ( row > = sorted_model_ - > rowCount ( ) ) {
2016-06-16 21:09:28 +00:00
return row_data ;
}
2017-02-13 00:36:58 +00:00
for ( int col = 0 ; col < sorted_model_ - > columnCount ( ) ; col + + ) {
2016-06-16 21:09:28 +00:00
if ( row < 0 ) {
2017-02-13 00:36:58 +00:00
row_data < < sorted_model_ - > headerData ( col , Qt : : Horizontal ) ;
2016-06-16 21:09:28 +00:00
} else {
2017-02-13 00:36:58 +00:00
row_data < < sorted_model_ - > index ( row , col ) . data ( ) ;
2016-06-16 21:09:28 +00:00
}
}
return row_data ;
}
2017-02-13 00:36:58 +00:00
void VoipCallsDialog : : on_callTreeView_activated ( const QModelIndex & index )
2014-11-19 00:21:42 +00:00
{
2017-02-13 00:36:58 +00:00
voip_calls_info_t * call_info = VoipCallsInfoModel : : indexToCallInfo ( index ) ;
2014-11-19 00:21:42 +00:00
if ( ! call_info ) {
return ;
}
emit goToPacket ( call_info - > start_fd - > num ) ;
}
2019-08-02 18:39:13 +00:00
void VoipCallsDialog : : selectAll ( )
2014-11-19 00:21:42 +00:00
{
2017-02-13 00:36:58 +00:00
ui - > callTreeView - > selectAll ( ) ;
2014-11-19 00:21:42 +00:00
}
2019-08-02 18:39:13 +00:00
void VoipCallsDialog : : copyAsCSV ( )
2016-06-16 21:09:28 +00:00
{
QString csv ;
QTextStream stream ( & csv , QIODevice : : Text ) ;
2017-02-13 00:36:58 +00:00
for ( int row = - 1 ; row < sorted_model_ - > rowCount ( ) ; row + + ) {
2016-06-16 21:09:28 +00:00
QStringList rdsl ;
foreach ( QVariant v , streamRowData ( row ) ) {
2017-02-13 00:36:58 +00:00
QString strval = v . toString ( ) ;
// XXX should quotes (") in strval be stripped/sanitized?
rdsl < < QString ( " \" %1 \" " ) . arg ( strval ) ;
2016-06-16 21:09:28 +00:00
}
2020-05-28 18:40:08 +00:00
stream < < rdsl . join ( " , " ) < < ' \n ' ;
2016-06-16 21:09:28 +00:00
}
wsApp - > clipboard ( ) - > setText ( stream . readAll ( ) ) ;
}
2019-08-02 18:39:13 +00:00
void VoipCallsDialog : : copyAsYAML ( )
2016-06-16 21:09:28 +00:00
{
QString yaml ;
QTextStream stream ( & yaml , QIODevice : : Text ) ;
2020-05-28 18:40:08 +00:00
stream < < " --- " < < ' \n ' ;
2017-02-13 00:36:58 +00:00
for ( int row = - 1 ; row < sorted_model_ - > rowCount ( ) ; row + + ) {
2020-05-28 18:40:08 +00:00
stream < < " - " < < ' \n ' ;
2016-06-16 21:09:28 +00:00
foreach ( QVariant v , streamRowData ( row ) ) {
2020-05-28 18:40:08 +00:00
stream < < " - " < < v . toString ( ) < < ' \n ' ;
2016-06-16 21:09:28 +00:00
}
}
wsApp - > clipboard ( ) - > setText ( stream . readAll ( ) ) ;
}
2014-11-19 00:21:42 +00:00
void VoipCallsDialog : : on_buttonBox_clicked ( QAbstractButton * button )
{
if ( button = = prepare_button_ ) {
prepareFilter ( ) ;
} else if ( button = = sequence_button_ ) {
showSequence ( ) ;
2014-12-13 00:51:40 +00:00
} else if ( button = = player_button_ ) {
showPlayer ( ) ;
2014-11-19 00:21:42 +00:00
}
}
2021-01-01 15:51:47 +00:00
void VoipCallsDialog : : removeAllCalls ( )
{
voip_calls_info_t * callsinfo ;
GList * list = NULL ;
call_infos_model_ - > removeAllCalls ( ) ;
/* Free shown callsinfos */
list = g_queue_peek_nth_link ( shown_callsinfos_ , 0 ) ;
while ( list )
{
callsinfo = ( voip_calls_info_t * ) list - > data ;
voip_calls_free_callsinfo ( callsinfo ) ;
list = g_list_next ( list ) ;
}
g_queue_clear ( shown_callsinfos_ ) ;
}
void VoipCallsDialog : : on_displayFilterCheckBox_toggled ( bool checked )
{
if ( ! cap_file_ . isValid ( ) ) {
return ;
}
tapinfo_ . apply_display_filter = checked ;
removeAllCalls ( ) ;
cap_file_ . retapPackets ( ) ;
}
2014-11-19 00:21:42 +00:00
void VoipCallsDialog : : on_buttonBox_helpRequested ( )
{
wsApp - > helpTopicAction ( HELP_TELEPHONY_VOIP_CALLS_DIALOG ) ;
}
2019-08-02 18:39:13 +00:00
void VoipCallsDialog : : switchTimeOfDay ( )
2016-10-22 09:32:51 +00:00
{
2019-08-02 18:39:13 +00:00
bool checked = ! call_infos_model_ - > timeOfDay ( ) ;
ui - > todCheckBox - > setChecked ( checked ) ;
call_infos_model_ - > setTimeOfDay ( checked ) ;
2017-02-13 00:36:58 +00:00
ui - > callTreeView - > resizeColumnToContents ( VoipCallsInfoModel : : StartTime ) ;
ui - > callTreeView - > resizeColumnToContents ( VoipCallsInfoModel : : StopTime ) ;
2016-10-22 09:32:51 +00:00
}
2020-12-30 08:51:00 +00:00
void VoipCallsDialog : : selectRtpStreamPassIn ( rtpstream_id_t * id )
{
emit selectRtpStreamPassOut ( id ) ;
}
void VoipCallsDialog : : deselectRtpStreamPassIn ( rtpstream_id_t * id )
{
emit deselectRtpStreamPassOut ( id ) ;
}
void VoipCallsDialog : : openRtpStreamDialogPassIn ( )
{
emit openRtpStreamDialogPassOut ( ) ;
}
2021-01-01 15:51:47 +00:00
void VoipCallsDialog : : displayFilterSuccess ( bool success )
{
if ( success & & ui - > displayFilterCheckBox - > isChecked ( ) ) {
removeAllCalls ( ) ;
cap_file_ . retapPackets ( ) ;
}
}
2020-12-30 08:51:00 +00:00
2014-11-19 00:21:42 +00:00
/*
* 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 :
*/