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
*
* 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"
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"
2015-10-04 17:10:29 +00:00
# include <wsutil/utf8_entities.h>
2014-11-19 00:21:42 +00:00
2015-01-29 21:55:18 +00:00
# include "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"
# include "stock_icon.h"
# include "wireshark_application.h"
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
// 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 * )
2014-12-13 00:51:40 +00:00
enum { voip_calls_type_ = 1000 } ;
2014-11-19 00:21:42 +00:00
class VoipCallsTreeWidgetItem : public QTreeWidgetItem
{
public :
2014-12-13 00:51:40 +00:00
VoipCallsTreeWidgetItem ( QTreeWidget * tree , voip_calls_info_t * call_info ) :
QTreeWidgetItem ( tree , voip_calls_type_ ) ,
call_info_ ( call_info )
{
2014-11-19 00:21:42 +00:00
drawData ( ) ;
}
2014-12-13 00:51:40 +00:00
voip_calls_info_t * callInfo ( ) {
// XXX Not needed? We explicitly pass selected conversations to RtpPlayerDialog.
// call_info_->selected = isSelected() ? TRUE : FALSE;
return call_info_ ;
}
2014-11-19 00:21:42 +00:00
void drawData ( ) {
2014-12-13 00:51:40 +00:00
if ( ! call_info_ ) {
setText ( start_time_col_ , QObject : : tr ( " Error " ) ) ;
2014-11-19 00:21:42 +00:00
return ;
}
// XXX Pull digit count from capture file precision
2014-12-13 00:51:40 +00:00
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_ , address_to_display_qstring ( & ( 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 ] ) ;
2014-11-19 00:21:42 +00:00
/* Add comments based on the protocol */
QString call_comments ;
2014-12-13 00:51:40 +00:00
switch ( call_info_ - > protocol ) {
2014-11-19 00:21:42 +00:00
case VOIP_ISUP :
{
2014-12-13 00:51:40 +00:00
isup_calls_info_t * isup_info = ( isup_calls_info_t * ) call_info_ - > prot_info ;
2014-11-19 00:21:42 +00:00
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 :
{
2014-12-13 00:51:40 +00:00
h323_calls_info_t * h323_info = ( h323_calls_info_t * ) call_info_ - > prot_info ;
2014-11-19 00:21:42 +00:00
gboolean flag = FALSE ;
static const QString on_str = QObject : : tr ( " On " ) ;
static const QString off_str = QObject : : tr ( " Off " ) ;
2014-12-13 00:51:40 +00:00
if ( call_info_ - > call_state = = VOIP_CALL_SETUP ) {
2014-11-19 00:21:42 +00:00
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 :
2014-12-13 00:51:40 +00:00
call_comments = call_info_ - > call_comment ;
2014-11-19 00:21:42 +00:00
break ;
}
setText ( comments_col_ , call_comments ) ;
}
2016-06-16 21:09:28 +00:00
// Return a QString, int, double, or invalid QVariant representing the raw column data.
QVariant colData ( int col ) const {
if ( ! call_info_ ) {
return QVariant ( ) ;
}
switch ( col ) {
case start_time_col_ :
return nstime_to_sec ( & call_info_ - > start_rel_ts ) ;
break ;
case stop_time_col_ :
return nstime_to_sec ( & call_info_ - > stop_rel_ts ) ;
break ;
case initial_speaker_col_ :
case from_col_ :
case to_col_ :
case protocol_col_ :
case state_col_ :
case comments_col_ :
return text ( col ) ;
break ;
case packets_col_ :
return call_info_ - > npackets ;
break ;
default :
break ;
}
return QVariant ( ) ;
}
2014-11-19 00:21:42 +00:00
bool operator < ( const QTreeWidgetItem & other ) const
{
2014-12-13 00:51:40 +00:00
if ( other . type ( ) ! = voip_calls_type_ ) return QTreeWidgetItem : : operator < ( other ) ;
const VoipCallsTreeWidgetItem * other_row = static_cast < const VoipCallsTreeWidgetItem * > ( & other ) ;
if ( ! call_info_ | | ! other_row - > call_info_ ) {
return QTreeWidgetItem : : operator < ( other ) ;
2014-11-19 00:21:42 +00:00
}
switch ( treeWidget ( ) - > sortColumn ( ) ) {
case start_time_col_ :
2014-12-13 00:51:40 +00:00
return nstime_cmp ( & ( call_info_ - > start_rel_ts ) , & ( other_row - > call_info_ - > start_rel_ts ) ) < 0 ;
2014-11-19 00:21:42 +00:00
break ;
case stop_time_col_ :
2014-12-13 00:51:40 +00:00
return nstime_cmp ( & ( call_info_ - > stop_rel_ts ) , & ( other_row - > call_info_ - > stop_rel_ts ) ) < 0 ;
2014-11-19 00:21:42 +00:00
break ;
case initial_speaker_col_ :
2014-12-13 00:51:40 +00:00
return cmp_address ( & ( call_info_ - > initial_speaker ) , & ( other_row - > call_info_ - > initial_speaker ) ) < 0 ;
2014-11-19 00:21:42 +00:00
break ;
case packets_col_ :
2014-12-13 00:51:40 +00:00
return call_info_ - > npackets < other_row - > call_info_ - > npackets ;
2014-11-19 00:21:42 +00:00
break ;
default :
break ;
}
// Fall back to string comparison
return QTreeWidgetItem : : operator < ( other ) ;
}
2014-12-13 00:51:40 +00:00
private :
voip_calls_info_t * call_info_ ;
2014-11-19 00:21:42 +00:00
} ;
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 ) ,
parent_ ( parent )
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 ) ;
2014-11-19 00:21:42 +00:00
ui - > callTreeWidget - > sortByColumn ( start_time_col_ , 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
2016-06-16 21:09:28 +00:00
ctx_menu_ . addAction ( ui - > actionSelect_All ) ;
ctx_menu_ . addSeparator ( ) ;
ctx_menu_ . addAction ( ui - > actionCopyAsCsv ) ;
ctx_menu_ . addAction ( ui - > actionCopyAsYaml ) ;
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
2016-06-16 21:09:28 +00:00
copy_button_ = ui - > buttonBox - > addButton ( tr ( " Copy " ) , QDialogButtonBox : : ApplyRole ) ;
QMenu * copy_menu = new QMenu ( ) ;
QAction * ca ;
ca = copy_menu - > addAction ( tr ( " as CSV " ) ) ;
ca - > setToolTip ( ui - > actionCopyAsCsv - > toolTip ( ) ) ;
connect ( ca , SIGNAL ( triggered ( ) ) , this , SLOT ( on_actionCopyAsCsv_triggered ( ) ) ) ;
ca = copy_menu - > addAction ( tr ( " as YAML " ) ) ;
ca - > setToolTip ( ui - > actionCopyAsYaml - > toolTip ( ) ) ;
connect ( ca , SIGNAL ( triggered ( ) ) , this , SLOT ( on_actionCopyAsYaml_triggered ( ) ) ) ;
copy_button_ - > setMenu ( copy_menu ) ;
2014-11-19 00:21:42 +00:00
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 ;
2015-11-15 21:57:43 +00:00
sequence_info_ = new SequenceInfo ( tapinfo_ . graph_analysis ) ;
2014-11-19 00:21:42 +00:00
voip_calls_init_all_taps ( & tapinfo_ ) ;
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_ ) ;
2014-11-19 00:21:42 +00:00
voip_calls_remove_all_tap_listeners ( & tapinfo_ ) ;
2015-11-15 21:57:43 +00:00
sequence_info_ - > unref ( ) ;
2015-10-25 18:24:06 +00:00
g_queue_free ( tapinfo_ . callsinfos ) ;
2014-11-19 00:21:42 +00:00
}
2015-12-06 21:29:53 +00:00
void VoipCallsDialog : : endRetapPackets ( )
{
voip_calls_remove_all_tap_listeners ( & tapinfo_ ) ;
WiresharkDialog : : endRetapPackets ( ) ;
}
2014-12-29 19:42:01 +00:00
void VoipCallsDialog : : captureFileClosing ( )
2014-11-19 00:21:42 +00:00
{
2014-12-29 19:42:01 +00:00
voip_calls_remove_all_tap_listeners ( & tapinfo_ ) ;
tapinfo_ . session = NULL ;
WiresharkDialog : : captureFileClosing ( ) ;
2014-11-19 00:21:42 +00:00
}
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 ) ;
}
2015-07-07 06:24:50 +00:00
//void VoipCallsDialog::tapReset(void *)
2014-11-19 00:21:42 +00:00
//{
// voip_calls_tapinfo_t *tapinfo = (voip_calls_tapinfo_t *) tapinfo_ptr;
//}
2015-07-07 06:24:50 +00:00
gboolean 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.
// 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 ;
}
2014-12-13 00:51:40 +00:00
GList * graph_item = g_queue_peek_nth_link ( tapinfo - > graph_analysis - > items , 0 ) ;
for ( ; graph_item ; graph_item = g_list_next ( graph_item ) ) {
for ( GList * rsi_entry = g_list_first ( tapinfo - > rtp_stream_list ) ; rsi_entry ; rsi_entry = g_list_next ( rsi_entry ) ) {
seq_analysis_item_t * sai = ( seq_analysis_item_t * ) graph_item - > data ;
rtp_stream_info_t * rsi = ( rtp_stream_info_t * ) rsi_entry - > data ;
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 ( ) ;
}
}
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 ) ;
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 ( )
{
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 ( ) ) {
2015-10-16 13:00:24 +00:00
VoipCallsTreeWidgetItem * vc_ti = static_cast < VoipCallsTreeWidgetItem * > ( ti ) ;
voip_calls_info_t * call_info = vc_ti - > callInfo ( ) ;
if ( ! call_info ) {
return ;
}
2014-11-19 00:21:42 +00:00
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 ) ) {
2015-10-25 21:52:30 +00:00
filter_str + = QString ( " %1frame.number == %2 " ) . arg ( or_prepend ) . arg ( ga_item - > frame_number ) ;
2014-11-19 00:21:42 +00:00
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 ;
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 ) {
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 :
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 ) {
h245_add = ( h245_address_t * ) listb - > data ;
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 ) ;
2014-11-19 00:21:42 +00:00
listb = g_list_next ( listb ) ;
}
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 ;
}
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 ( )
{
2014-12-29 19:42:01 +00:00
if ( file_closed_ ) return ;
2014-11-19 00:21:42 +00:00
QSet < guint16 > selected_calls ;
foreach ( QTreeWidgetItem * ti , ui - > callTreeWidget - > selectedItems ( ) ) {
2015-10-16 13:00:24 +00:00
VoipCallsTreeWidgetItem * vc_ti = static_cast < VoipCallsTreeWidgetItem * > ( ti ) ;
voip_calls_info_t * call_info = vc_ti - > callInfo ( ) ;
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 ) {
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 ) ;
}
2015-11-15 21:57:43 +00:00
SequenceDialog * sequence_dialog = new SequenceDialog ( parent_ , cap_file_ , sequence_info_ ) ;
2014-11-19 00:21:42 +00:00
// XXX This goes away when we close the VoIP Calls dialog.
connect ( sequence_dialog , SIGNAL ( goToPacket ( int ) ) ,
this , SIGNAL ( goToPacket ( int ) ) ) ;
sequence_dialog - > show ( ) ;
}
2014-12-13 00:51:40 +00:00
void VoipCallsDialog : : showPlayer ( )
{
# ifdef QT_MULTIMEDIA_LIB
RtpPlayerDialog rtp_player_dialog ( * this , cap_file_ ) ;
foreach ( QTreeWidgetItem * ti , ui - > callTreeWidget - > selectedItems ( ) ) {
VoipCallsTreeWidgetItem * vc_ti = static_cast < VoipCallsTreeWidgetItem * > ( ti ) ;
for ( GList * rsi_entry = g_list_first ( tapinfo_ . rtp_stream_list ) ; rsi_entry ; rsi_entry = g_list_next ( rsi_entry ) ) {
rtp_stream_info_t * rsi = ( rtp_stream_info_t * ) rsi_entry - > data ;
if ( ! rsi ) continue ;
//VOIP_CALLS_DEBUG("checking call %u, start frame %u == stream call %u, start frame %u, setup frame %u",
// vc_ti->callInfo()->call_num, vc_ti->callInfo()->start_fd->num,
// rsi->call_num, rsi->start_fd->num, rsi->setup_frame_number);
if ( vc_ti - > callInfo ( ) - > call_num = = rsi - > call_num ) {
//VOIP_CALLS_DEBUG("adding call number %u", vc_ti->callInfo()->call_num);
rtp_player_dialog . addRtpStream ( rsi ) ;
}
}
}
connect ( & rtp_player_dialog , SIGNAL ( goToPacket ( int ) ) , this , SIGNAL ( goToPacket ( int ) ) ) ;
rtp_player_dialog . exec ( ) ;
# endif // QT_MULTIMEDIA_LIB
}
2016-06-16 21:09:28 +00:00
QList < QVariant > VoipCallsDialog : : streamRowData ( int row ) const
{
QList < QVariant > row_data ;
if ( row > = ui - > callTreeWidget - > topLevelItemCount ( ) ) {
return row_data ;
}
for ( int col = 0 ; col < ui - > callTreeWidget - > columnCount ( ) ; col + + ) {
if ( row < 0 ) {
row_data < < ui - > callTreeWidget - > headerItem ( ) - > text ( col ) ;
} else {
VoipCallsTreeWidgetItem * vcti = static_cast < VoipCallsTreeWidgetItem * > ( ui - > callTreeWidget - > topLevelItem ( row ) ) ;
if ( vcti ) {
row_data < < vcti - > colData ( col ) ;
}
}
}
return row_data ;
}
2014-11-19 00:21:42 +00:00
void VoipCallsDialog : : on_callTreeWidget_itemActivated ( QTreeWidgetItem * item , int )
{
2015-10-16 13:00:24 +00:00
VoipCallsTreeWidgetItem * vc_ti = static_cast < VoipCallsTreeWidgetItem * > ( item ) ;
voip_calls_info_t * call_info = vc_ti - > callInfo ( ) ;
2014-11-19 00:21:42 +00:00
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 ( ) ;
}
2016-06-16 21:09:28 +00:00
void VoipCallsDialog : : on_actionCopyAsCsv_triggered ( )
{
QString csv ;
QTextStream stream ( & csv , QIODevice : : Text ) ;
for ( int row = - 1 ; row < ui - > callTreeWidget - > topLevelItemCount ( ) ; row + + ) {
QStringList rdsl ;
foreach ( QVariant v , streamRowData ( row ) ) {
if ( ! v . isValid ( ) ) {
rdsl < < " \" \" " ;
} else if ( ( int ) v . type ( ) = = ( int ) QMetaType : : QString ) {
rdsl < < QString ( " \" %1 \" " ) . arg ( v . toString ( ) ) ;
} else {
rdsl < < v . toString ( ) ;
}
}
stream < < rdsl . join ( " , " ) < < endl ;
}
wsApp - > clipboard ( ) - > setText ( stream . readAll ( ) ) ;
}
void VoipCallsDialog : : on_actionCopyAsYaml_triggered ( )
{
QString yaml ;
QTextStream stream ( & yaml , QIODevice : : Text ) ;
stream < < " --- " < < endl ;
for ( int row = - 1 ; row < ui - > callTreeWidget - > topLevelItemCount ( ) ; row + + ) {
stream < < " - " < < endl ;
foreach ( QVariant v , streamRowData ( row ) ) {
stream < < " - " < < v . toString ( ) < < endl ;
}
}
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
}
}
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 :
*/