And finally (I hope) the last part from the patch
[obnox/wireshark/wip.git] / gtk / voip_calls_dlg.c
1 /* voip_calls_dlg.c
2  * VoIP calls summary addition for ethereal
3  *
4  * $Id$
5  *
6  * Copyright 2004, Ericsson , Spain
7  * By Francisco Alcoba <francisco.alcoba@ericsson.com>
8  *
9  * based on h323_calls_dlg.c
10  * Copyright 2004, Iskratel, Ltd, Kranj
11  * By Miha Jemec <m.jemec@iskratel.si>
12  *
13  * H323, RTP and Graph Support
14  * By Alejandro Vaquero, alejandro.vaquero@verso.com
15  * Copyright 2005, Verso Technologies Inc.
16  *
17  * Ethereal - Network traffic analyzer
18  * By Gerald Combs <gerald@ethereal.com>
19  * Copyright 1998 Gerald Combs
20  *
21  * This program is free software; you can redistribute it and/or
22  * modify it under the terms of the GNU General Public License
23  * as published by the Free Software Foundation; either version 2
24  * of the License, or (at your option) any later version.
25  *
26  * This program is distributed in the hope that it will be useful,
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
29  * GNU General Public License for more details.
30  *
31  * You should have received a copy of the GNU General Public License
32  * along with this program; if not, write to the Free Software
33  * Foundation,  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
34  */
35
36 #ifdef HAVE_CONFIG_H
37 #  include <config.h>
38 #endif
39
40 #include "register.h"
41
42 #include "graph_analysis.h"
43 #include "voip_calls_dlg.h"
44 #include "voip_calls.h"
45
46 #include "globals.h"
47 #include "epan/filesystem.h"
48
49 #include "tap_menu.h"
50 #include "dlg_utils.h"
51 #include "ui_util.h"
52 #include "compat_macros.h"
53 #include "gtkglobals.h"
54
55 #include "image/clist_ascend.xpm"
56 #include "image/clist_descend.xpm"
57 #include "simple_dialog.h"
58
59 #include <epan/to_str.h>
60
61 #include <string.h>
62 #include <ctype.h>
63
64 static const gchar FWD_LABEL_TEXT[] = "Select one call.";
65
66 /****************************************************************************/
67 /* pointer to the one and only dialog window */
68 static GtkWidget *voip_calls_dlg = NULL;
69
70 static GtkWidget *clist = NULL;
71 static GtkWidget *top_label = NULL;
72 static GtkWidget *status_label = NULL;
73 static GtkWidget *label_fwd = NULL;
74
75 /*static GtkWidet *bt_unselect = NULL;*/
76 static GtkWidget *bt_filter = NULL;
77 static GtkWidget *bt_graph = NULL;
78
79
80 static voip_calls_info_t* selected_call_fwd = NULL;  /* current selection */
81 static GList *last_list = NULL;
82
83 static guint32 calls_nb = 0;     /* number of displayed calls */
84 static guint32 calls_ns = 0;     /* number of selected calls */
85
86 static graph_analysis_data_t *graph_analysis_data;
87
88 #define NUM_COLS 9
89
90 /****************************************************************************/
91 /* append a line to clist */
92 static void add_to_clist(voip_calls_info_t* strinfo)
93 {
94         gchar label_text[256];
95         gint added_row;
96         gchar *data[NUM_COLS];
97         gchar field[NUM_COLS][50];
98         gint c;
99         isup_calls_info_t *tmp_isupinfo;
100         h323_calls_info_t *tmp_h323info;
101         gboolean tmp_bool = FALSE;
102         for (c=0;c<NUM_COLS;c++){
103                 data[c]=&field[c][0];
104         }
105
106
107         g_snprintf(field[0], 15, "%i.%2i", strinfo->start_sec, strinfo->start_usec/10000);
108         g_snprintf(field[1], 15, "%i.%2i", strinfo->stop_sec, strinfo->stop_usec/10000);
109 /*      xxx display_signed_time(data[0], sizeof(field[0]), strinfo->start_sec, strinfo->start_usec, USECS); */
110 /*      display_signed_time(data[1], sizeof(field[0]), strinfo->stop_sec, strinfo->stop_usec, USECS); */
111         g_snprintf(field[2], 30, "%s", ip_to_str((const guint8*)&(strinfo->initial_speaker)));
112         g_snprintf(field[3], 50, "%s", strinfo->from_identity);
113         g_snprintf(field[4], 50, "%s", strinfo->to_identity);
114         g_snprintf(field[5], 15, "%s", voip_protocol_name[strinfo->protocol]);
115         g_snprintf(field[6], 15, "%u", strinfo->npackets);
116         g_snprintf(field[7], 15, "%s", voip_call_state_name[strinfo->call_state]);
117
118         /* Add comments based on the protocol */
119         switch(strinfo->protocol){
120                 case VOIP_ISUP:
121                         tmp_isupinfo = strinfo->prot_info;
122                         g_snprintf(field[8],30, "%i-%i -> %i-%i", tmp_isupinfo->ni, tmp_isupinfo->opc,
123                                 tmp_isupinfo->ni, tmp_isupinfo->dpc);
124                         break;
125                 case VOIP_H323:
126                         tmp_h323info = strinfo->prot_info;
127                         if (strinfo->call_state == VOIP_CALL_SETUP) 
128                                 tmp_bool = tmp_h323info->is_faststart_Setup;
129                         else
130                                 if ((tmp_h323info->is_faststart_Setup == TRUE) && (tmp_h323info->is_faststart_Proc == TRUE)) tmp_bool = TRUE; 
131                         g_snprintf(field[8],35, "Tunneling: %s  Fast Start: %s", (tmp_h323info->is_h245Tunneling==TRUE?"ON":"OFF"), 
132                                 (tmp_bool==TRUE?"ON":"OFF"));
133                         break;
134                 default:
135                         field[8][0]='\0';
136         }
137
138         
139         added_row = gtk_clist_append(GTK_CLIST(clist), data);
140
141         /* set data pointer of last row to point to user data for that row */
142         gtk_clist_set_row_data(GTK_CLIST(clist), added_row, strinfo);
143
144         /* Update the top label with the number of detected calls */
145         calls_nb++;
146         g_snprintf(label_text, 256,
147                 "Detected %d VoIP %s. Selected %d %s.",
148                 calls_nb, 
149                 plurality(calls_nb, "Call", "Calls"),
150                 calls_ns,
151                 plurality(calls_ns, "Call", "Calls"));
152         gtk_label_set(GTK_LABEL(top_label), label_text);
153
154         /* Update the status label with the number of total messages */
155         g_snprintf(label_text, 256,
156                 "Total: Calls: %d   Start packets: %d   Completed calls: %d   Rejected calls: %d",
157                         g_list_length(voip_calls_get_info()->strinfo_list),
158                         voip_calls_get_info()->start_packets, 
159                         voip_calls_get_info()->completed_calls,
160                         voip_calls_get_info()->rejected_calls);
161         gtk_label_set(GTK_LABEL(status_label), label_text);
162 }
163
164
165 void voip_calls_remove_tap_listener()
166 {
167         /* Remove the calls tap listener */
168         remove_tap_listener_sip_calls();
169         remove_tap_listener_isup_calls();
170         remove_tap_listener_mtp3_calls();
171         remove_tap_listener_h225_calls();
172         remove_tap_listener_h245dg_calls();
173         remove_tap_listener_q931_calls();
174         remove_tap_listener_sdp_calls();
175         remove_tap_listener_rtp();
176 }
177
178 /****************************************************************************/
179 /* CALLBACKS                                                                */
180 /****************************************************************************/
181 static void
182 voip_calls_on_destroy                      (GtkObject       *object _U_,
183                                         gpointer         user_data _U_)
184 {
185         /* remove_tap_listeners */
186         voip_calls_remove_tap_listener();
187
188         /* Clean up memory used by calls tap */
189         voip_calls_reset((voip_calls_tapinfo_t*) voip_calls_get_info());
190
191         /* Note that we no longer have a "VoIP Calls" dialog box. */
192         voip_calls_dlg = NULL;
193 }
194
195
196 /****************************************************************************/
197 static void
198 voip_calls_on_unselect                  (GtkButton       *button _U_,
199                                         gpointer         user_data _U_)
200 {
201         selected_call_fwd = NULL;
202         gtk_clist_unselect_all(GTK_CLIST(clist));
203         gtk_label_set_text(GTK_LABEL(label_fwd), FWD_LABEL_TEXT);
204
205         /*gtk_widget_set_sensitive(bt_unselect, FALSE);*/
206         gtk_widget_set_sensitive(bt_filter, FALSE);
207 }
208
209
210 /****************************************************************************/
211 static void
212 voip_calls_on_filter                    (GtkButton       *button _U_,
213                                         gpointer         user_data _U_)
214 {
215         const gchar *filter_string;
216         gchar c;
217         GString *filter_string_fwd;
218         gchar *filter_prepend;
219         sip_calls_info_t *tmp_sipinfo;
220         isup_calls_info_t *tmp_isupinfo;
221         h323_calls_info_t *tmp_h323info;
222         h245_address_t *h245_add = NULL;
223         GList* list;
224
225         if (selected_call_fwd==NULL)
226                 return;
227
228         filter_string=gtk_entry_get_text(GTK_ENTRY(main_display_filter_widget));
229         filter_prepend = "";
230         while ((c = *filter_string++) != '\0') {
231                 if (!isspace((guchar)c)) {
232                         /* The filter string isn't blank, so there's already
233                            an expression; we OR in the new expression */
234                         filter_prepend = " or ";
235                         break;
236                 }
237         }
238                 
239         filter_string_fwd = g_string_new(filter_prepend);
240         switch(selected_call_fwd->protocol){
241                 case VOIP_SIP:
242                         tmp_sipinfo = selected_call_fwd->prot_info;
243                         g_string_sprintfa(filter_string_fwd,
244                            "(sip.Call-ID == \"%s\") ",
245                            tmp_sipinfo->call_identifier 
246                            );
247                         gtk_entry_append_text(GTK_ENTRY(main_display_filter_widget), filter_string_fwd->str);
248                         break;
249                 case VOIP_ISUP:
250                         tmp_isupinfo = selected_call_fwd->prot_info;
251                         g_string_sprintfa(filter_string_fwd,
252                            "(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))) ",
253                            tmp_isupinfo->cic,selected_call_fwd->first_frame_num,
254                            selected_call_fwd->last_frame_num, 
255                            tmp_isupinfo->ni, tmp_isupinfo->dpc, tmp_isupinfo->opc, 
256                            tmp_isupinfo->opc, tmp_isupinfo->dpc
257                            );
258                         gtk_entry_append_text(GTK_ENTRY(main_display_filter_widget), filter_string_fwd->str);
259                         break;
260                 case VOIP_H323:
261                         tmp_h323info = selected_call_fwd->prot_info;
262                         g_string_sprintfa(filter_string_fwd,
263                            "((h225.guid == %x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x || q931.call_ref == %x:%x || q931.call_ref == %x:%x) ",
264                            (guint8)tmp_h323info->guid[0], (guint8)tmp_h323info->guid[1], (guint8)tmp_h323info->guid[2],
265                            (guint8)tmp_h323info->guid[3], (guint8)tmp_h323info->guid[4], (guint8)tmp_h323info->guid[5], (guint8)tmp_h323info->guid[6],
266                            (guint8)tmp_h323info->guid[7], (guint8)tmp_h323info->guid[8], (guint8)tmp_h323info->guid[9], (guint8)tmp_h323info->guid[10],
267                            (guint8)tmp_h323info->guid[11], (guint8)tmp_h323info->guid[12], (guint8)tmp_h323info->guid[13], (guint8)tmp_h323info->guid[14],
268                            (guint8)tmp_h323info->guid[15], (guint8)(tmp_h323info->q931_crv & 0xff), (guint8)((tmp_h323info->q931_crv & 0xff00)>>8)
269                            , (guint8)(tmp_h323info->q931_crv2 & 0xff), (guint8)((tmp_h323info->q931_crv2 & 0xff00)>>8));
270
271                         list = g_list_first(tmp_h323info->h245_list);
272                         while (list)
273                         {
274                                 h245_add=list->data;
275                                 g_string_sprintfa(filter_string_fwd,
276                                         " || (ip.addr == %s && tcp.port == %d && h245) ", 
277                                         ip_to_str((guint8 *)&(h245_add->h245_address)), h245_add->h245_port);
278                                 list = g_list_next(list);
279                         }
280                         g_string_sprintfa(filter_string_fwd, ") ");
281                         gtk_entry_append_text(GTK_ENTRY(main_display_filter_widget), filter_string_fwd->str);
282                         break;
283
284         }
285         g_string_free(filter_string_fwd, TRUE);
286 }
287
288
289
290
291 /****************************************************************************/
292 static void
293 on_graph_bt_clicked                    (GtkButton       *button _U_,
294                                         gpointer         user_data _U_)
295 {
296         graph_analysis_item_t *gai;
297         GList* list;
298         GList* list2;
299         voip_calls_info_t *tmp_listinfo;
300
301         /* reset the "display" parameter in graph analysis */
302         list2 = g_list_first(voip_calls_get_info()->graph_analysis->list);
303         while (list2){
304                 gai = list2->data;
305                 gai->display = FALSE;
306                 list2 = g_list_next(list2);
307         }
308
309
310         /* set the display for selected calls */
311         list = g_list_first(voip_calls_get_info()->strinfo_list);
312         while (list){
313                 tmp_listinfo=list->data;
314                 if (tmp_listinfo->selected){
315                         list2 = g_list_first(voip_calls_get_info()->graph_analysis->list);
316                         while (list2){
317                                 gai = list2->data;
318                                 if (gai->conv_num == tmp_listinfo->call_num){
319                                         gai->display = TRUE;
320                                 }
321                                 list2 = g_list_next(list2);
322                         }
323                 }
324                 list = g_list_next(list);
325         }
326
327         /* create or refresh the graph windows */
328         if (graph_analysis_data->dlg.window == NULL)    /* create the window */
329                 graph_analysis_create(graph_analysis_data);
330         else
331                 graph_analysis_update(graph_analysis_data);             /* refresh it */
332 }
333
334 static const GdkColor COLOR_SELECT = {0, 0x00ff, 0x80ff, 0x80ff};
335 static const GdkColor COLOR_DEFAULT = {0, 0xffff, 0xffff, 0xffff};
336
337 /****************************************************************************/
338 /* when the user selects a row in the calls list */
339 static void
340 voip_calls_on_select_row(GtkCList *clist,
341                                             gint row _U_,
342                                             gint column _U_,
343                                             GdkEventButton *event _U_,
344                                             gpointer user_data _U_)
345 {
346         GdkColor color = COLOR_DEFAULT;
347         gchar label_text[80];
348         
349         selected_call_fwd = gtk_clist_get_row_data(GTK_CLIST(clist), row);
350
351         if (!selected_call_fwd->selected)
352                 calls_ns++;
353         else
354                 calls_ns--;
355
356         g_snprintf(label_text, 256,
357                 "Detected %d VoIP %s. Selected %d %s.",
358                 calls_nb, 
359             plurality(calls_nb, "Call", "Calls"),
360                         calls_ns,
361                         plurality(calls_ns, "Call", "Calls"));
362         gtk_label_set(GTK_LABEL(top_label), label_text);
363
364         g_snprintf(label_text, 80, "Selected Call: From  %s  To %s, starting time %i.%i",
365                 selected_call_fwd->from_identity,
366                 selected_call_fwd->to_identity,
367                 selected_call_fwd->start_sec, 
368                 selected_call_fwd->start_usec
369         );
370         gtk_label_set_text(GTK_LABEL(label_fwd), label_text);
371
372         selected_call_fwd->selected=!selected_call_fwd->selected;
373         if (selected_call_fwd->selected)
374                 color = COLOR_SELECT;
375         else
376                 color = COLOR_DEFAULT;
377
378         gtk_clist_set_background(GTK_CLIST(clist), row, &color);
379         
380         /*gtk_widget_set_sensitive(bt_unselect, TRUE);*/
381         gtk_widget_set_sensitive(bt_filter, TRUE);
382
383         /* TODO: activate other buttons when implemented */
384 }
385
386
387 /****************************************************************************/
388
389 typedef struct column_arrows {
390         GtkWidget *table;
391         GtkWidget *ascend_pm;
392         GtkWidget *descend_pm;
393 } column_arrows;
394
395
396 /****************************************************************************/
397 static void
398 voip_calls_click_column_cb(GtkCList *clist, gint column, gpointer data)
399 {
400         column_arrows *col_arrows = (column_arrows *) data;
401         int i;
402
403         gtk_clist_freeze(clist);
404
405         for (i=0; i<NUM_COLS; i++) {
406                 gtk_widget_hide(col_arrows[i].ascend_pm);
407                 gtk_widget_hide(col_arrows[i].descend_pm);
408         }
409
410         if (column == clist->sort_column) {
411                 if (clist->sort_type == GTK_SORT_ASCENDING) {
412                         clist->sort_type = GTK_SORT_DESCENDING;
413                         gtk_widget_show(col_arrows[column].descend_pm);
414                 } else {
415                         clist->sort_type = GTK_SORT_ASCENDING;
416                         gtk_widget_show(col_arrows[column].ascend_pm);
417                 }
418         } else {
419                 clist->sort_type = GTK_SORT_ASCENDING;
420                 gtk_widget_show(col_arrows[column].ascend_pm);
421                 gtk_clist_set_sort_column(clist, column);
422         }
423         gtk_clist_thaw(clist);
424
425         gtk_clist_sort(clist);
426 }
427
428
429 /****************************************************************************/
430 static gint
431 voip_calls_sort_column(GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2)
432 {
433         char *text1 = NULL;
434         char *text2 = NULL;
435         int i1, i2;
436
437         const GtkCListRow *row1 = (const GtkCListRow *) ptr1;
438         const GtkCListRow *row2 = (const GtkCListRow *) ptr2;
439
440         text1 = GTK_CELL_TEXT (row1->cell[clist->sort_column])->text;
441         text2 = GTK_CELL_TEXT (row2->cell[clist->sort_column])->text;
442
443         switch(clist->sort_column){
444         case 0:
445         case 1:
446         case 2:
447         case 3:
448         case 4:
449         case 5:
450                 return strcmp (text1, text2);
451         case 6:
452                 i1=atoi(text1);
453                 i2=atoi(text2);
454                 return i1-i2;
455         }
456         g_assert_not_reached();
457         return 0;
458 }
459
460
461 /****************************************************************************/
462 /* INTERFACE                                                                */
463 /****************************************************************************/
464
465 static void voip_calls_dlg_create (void)
466 {
467         GtkWidget *voip_calls_dlg_w;
468         GtkWidget *main_vb;
469         GtkWidget *scrolledwindow;
470         GtkWidget *hbuttonbox;
471         GtkWidget *bt_close;
472         GtkTooltips *tooltips = gtk_tooltips_new();
473
474         gchar *titles[NUM_COLS] =  {"Start Time", "Stop Time", "Initial Speaker", "From",  "To", "Protocol", "Packets", "State", "Comments"};
475         column_arrows *col_arrows;
476         GtkWidget *column_lb;
477         int i;
478
479         voip_calls_dlg_w=window_new(GTK_WINDOW_TOPLEVEL, "Ethereal: VoIP Calls");
480
481         gtk_window_set_default_size(GTK_WINDOW(voip_calls_dlg_w), 840, 350);
482
483         main_vb = gtk_vbox_new (FALSE, 0);
484         gtk_container_add(GTK_CONTAINER(voip_calls_dlg_w), main_vb);
485         gtk_container_set_border_width (GTK_CONTAINER (main_vb), 12);
486
487         top_label = gtk_label_new ("Detected 0 VoIP Calls. Selected 0 Calls.");
488         gtk_box_pack_start (GTK_BOX (main_vb), top_label, FALSE, FALSE, 8);
489
490         scrolledwindow = scrolled_window_new (NULL, NULL);
491         gtk_box_pack_start (GTK_BOX (main_vb), scrolledwindow, TRUE, TRUE, 0);
492
493         clist = gtk_clist_new (NUM_COLS);
494         gtk_container_add (GTK_CONTAINER (scrolledwindow), clist);
495
496         gtk_clist_set_column_width (GTK_CLIST (clist), 0, 60);
497         gtk_clist_set_column_width (GTK_CLIST (clist), 1, 60);
498         gtk_clist_set_column_width (GTK_CLIST (clist), 2, 80);
499         gtk_clist_set_column_width (GTK_CLIST (clist), 3, 130);
500         gtk_clist_set_column_width (GTK_CLIST (clist), 4, 130);
501         gtk_clist_set_column_width (GTK_CLIST (clist), 5, 50);
502         gtk_clist_set_column_width (GTK_CLIST (clist), 6, 45);
503         gtk_clist_set_column_width (GTK_CLIST (clist), 7, 60);
504         gtk_clist_set_column_width (GTK_CLIST (clist), 8, 100);
505
506         gtk_clist_set_column_justification(GTK_CLIST(clist), 0, GTK_JUSTIFY_LEFT);
507         gtk_clist_set_column_justification(GTK_CLIST(clist), 1, GTK_JUSTIFY_LEFT);
508         gtk_clist_set_column_justification(GTK_CLIST(clist), 2, GTK_JUSTIFY_LEFT);
509         gtk_clist_set_column_justification(GTK_CLIST(clist), 3, GTK_JUSTIFY_LEFT);
510         gtk_clist_set_column_justification(GTK_CLIST(clist), 4, GTK_JUSTIFY_LEFT);
511         gtk_clist_set_column_justification(GTK_CLIST(clist), 5, GTK_JUSTIFY_CENTER);
512         gtk_clist_set_column_justification(GTK_CLIST(clist), 6, GTK_JUSTIFY_CENTER);
513         gtk_clist_set_column_justification(GTK_CLIST(clist), 7, GTK_JUSTIFY_LEFT);
514         gtk_clist_set_column_justification(GTK_CLIST(clist), 8, GTK_JUSTIFY_LEFT);
515
516         gtk_clist_column_titles_show (GTK_CLIST (clist));
517
518         gtk_clist_set_compare_func(GTK_CLIST(clist), voip_calls_sort_column);
519         gtk_clist_set_sort_column(GTK_CLIST(clist), 0);
520         gtk_clist_set_sort_type(GTK_CLIST(clist), GTK_SORT_ASCENDING);
521
522         gtk_widget_show(voip_calls_dlg_w);
523
524         /* sort by column feature */
525         col_arrows = (column_arrows *) g_malloc(sizeof(column_arrows) * NUM_COLS);
526
527         for (i=0; i<NUM_COLS; i++) {
528                 col_arrows[i].table = gtk_table_new(2, 2, FALSE);
529                 gtk_table_set_col_spacings(GTK_TABLE(col_arrows[i].table), 5);
530                 column_lb = gtk_label_new(titles[i]);
531                 gtk_table_attach(GTK_TABLE(col_arrows[i].table), column_lb, 0, 1, 0, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
532                 gtk_widget_show(column_lb);
533
534                 col_arrows[i].ascend_pm = xpm_to_widget(clist_ascend_xpm);
535                 gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].ascend_pm, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
536                 col_arrows[i].descend_pm = xpm_to_widget(clist_descend_xpm);
537                 gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].descend_pm, 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
538                 /* make start time be the default sort order */
539                 if (i == 0) {
540                         gtk_widget_show(col_arrows[i].ascend_pm);
541                 }
542                 gtk_clist_set_column_widget(GTK_CLIST(clist), i, col_arrows[i].table);
543                 gtk_widget_show(col_arrows[i].table);
544         }
545
546         SIGNAL_CONNECT(clist, "click-column", voip_calls_click_column_cb, col_arrows);
547
548         label_fwd = gtk_label_new (FWD_LABEL_TEXT);
549         gtk_box_pack_start (GTK_BOX (main_vb), label_fwd, FALSE, FALSE, 0);
550
551         status_label = gtk_label_new ("Total: Calls: 0   Start packets: 0   Completed calls: 0   Rejected calls: 0");
552         gtk_box_pack_start (GTK_BOX (main_vb), status_label, FALSE, FALSE, 8);
553
554         /* button row */
555         hbuttonbox = gtk_hbutton_box_new ();
556         gtk_box_pack_start (GTK_BOX (main_vb), hbuttonbox, FALSE, FALSE, 0);
557         gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox), GTK_BUTTONBOX_SPREAD);
558         gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbuttonbox), 30);
559
560         /*bt_unselect = gtk_button_new_with_label ("Unselect");
561         gtk_container_add (GTK_CONTAINER (hbuttonbox), bt_unselect);
562         gtk_tooltips_set_tip (tooltips, bt_unselect, "Unselect this conversation", NULL);*/
563
564         bt_filter = gtk_button_new_with_label ("Prepare filter");
565         gtk_container_add (GTK_CONTAINER (hbuttonbox), bt_filter);
566         gtk_tooltips_set_tip (tooltips, bt_filter, "Prepare a display filter of the selected conversation", NULL);
567
568         bt_graph = gtk_button_new_with_label("Graph");
569         gtk_container_add(GTK_CONTAINER(hbuttonbox), bt_graph);
570         gtk_widget_show(bt_graph);
571         SIGNAL_CONNECT(bt_graph, "clicked", on_graph_bt_clicked, NULL);
572
573         bt_close = BUTTON_NEW_FROM_STOCK(GTK_STOCK_CLOSE);
574         gtk_container_add (GTK_CONTAINER (hbuttonbox), bt_close);
575         GTK_WIDGET_SET_FLAGS(bt_close, GTK_CAN_DEFAULT);
576         gtk_tooltips_set_tip (tooltips, bt_close, "Close this dialog", NULL);
577
578         SIGNAL_CONNECT(clist, "select_row", voip_calls_on_select_row, NULL);
579         /*SIGNAL_CONNECT(bt_unselect, "clicked", voip_calls_on_unselect, NULL);*/
580         SIGNAL_CONNECT(bt_filter, "clicked", voip_calls_on_filter, NULL);
581
582         window_set_cancel_button(voip_calls_dlg_w, bt_close, window_cancel_button_cb);
583
584         SIGNAL_CONNECT(voip_calls_dlg_w, "delete_event", window_delete_event_cb, NULL);
585         SIGNAL_CONNECT(voip_calls_dlg_w, "destroy", voip_calls_on_destroy, NULL);
586
587         gtk_widget_show_all(voip_calls_dlg_w);
588         window_present(voip_calls_dlg_w);
589
590         voip_calls_on_unselect(NULL, NULL);
591
592         voip_calls_dlg = voip_calls_dlg_w;
593 }
594
595
596 /****************************************************************************/
597 /* PUBLIC                                                                   */
598 /****************************************************************************/
599
600 /****************************************************************************/
601 /* update the contents of the dialog box clist */
602 /* list: pointer to list of voip_calls_info_t* */
603
604 void voip_calls_dlg_update(GList *list)
605 {
606         gchar label_text[256];
607 guint foo;
608         if (voip_calls_dlg != NULL) {
609                 gtk_clist_clear(GTK_CLIST(clist));
610                 calls_nb = 0;
611                 calls_ns = 0;
612                 g_snprintf(label_text, 256,
613                         "Total: Calls: %d   Start packets: %d   Completed calls: %d   Rejected calls: %d",
614                         g_list_length(voip_calls_get_info()->strinfo_list),
615                         voip_calls_get_info()->start_packets, 
616                         voip_calls_get_info()->completed_calls,
617                         voip_calls_get_info()->rejected_calls);
618                 gtk_label_set(GTK_LABEL(status_label), label_text);
619
620                 foo=    g_list_length(list);
621                 list = g_list_first(list);
622                 while (list)
623                 {
624                         add_to_clist((voip_calls_info_t*)(list->data));
625                         list = g_list_next(list);
626                 }
627
628                 g_snprintf(label_text, 256,
629                         "Detected %d VoIP %s. Selected %d %s.",
630                         calls_nb, 
631                         plurality(calls_nb, "Call", "Calls"),
632                         calls_ns,
633                         plurality(calls_ns, "Call", "Calls"));
634                 gtk_label_set(GTK_LABEL(top_label), label_text);
635
636                 voip_calls_on_unselect(NULL, NULL);
637         }
638
639         last_list = list;
640 }
641
642
643 /****************************************************************************/
644 /* draw function for tap listeners to keep the window up to date */
645 void voip_calls_dlg_draw(void *ptr _U_)
646 {
647         voip_calls_dlg_update(voip_calls_get_info()->strinfo_list);
648 }
649
650 /* reset function for tap listeners to clear window, if necessary */
651 void voip_calls_dlg_reset(void *ptr _U_)
652 {
653         /* Clean up memory used by calls tap */
654         voip_calls_reset((voip_calls_tapinfo_t*) voip_calls_get_info());
655 }
656
657 /* init function for tap */
658 static void
659 voip_calls_init_tap(char *dummy _U_)
660 {
661         graph_analysis_data_init();
662
663         /* Clean up memory used by calls tap */
664         voip_calls_reset((voip_calls_tapinfo_t*) voip_calls_get_info());
665
666         /* Register the tap listener */
667         sip_calls_init_tap();
668         mtp3_calls_init_tap();
669         isup_calls_init_tap();
670         h225_calls_init_tap();
671         h245dg_calls_init_tap();
672         q931_calls_init_tap();
673         sdp_calls_init_tap();
674         rtp_init_tap();
675         
676         /* init the Graph Analysys */
677         graph_analysis_data = graph_analysis_init();
678         graph_analysis_data->graph_info = voip_calls_get_info()->graph_analysis;
679
680         /* create dialog box if necessary */
681         if (voip_calls_dlg == NULL) {
682                 voip_calls_dlg_create();
683         } else {
684                 /* There's already a dialog box; reactivate it. */
685                 reactivate_window(voip_calls_dlg);
686         }
687         
688         /* Scan for VoIP calls calls (redissect all packets) */
689         cf_retap_packets(&cfile);
690         
691         /* Tap listener will be removed and cleaned up in voip_calls_on_destroy */
692 }
693
694
695 /****************************************************************************/
696 /* entry point when called via the GTK menu */
697 void voip_calls_launch(GtkWidget *w _U_, gpointer data _U_)
698 {
699         voip_calls_init_tap("");
700 }
701
702 /****************************************************************************/
703 void
704 register_tap_listener_voip_calls_dlg(void)
705 {
706         register_ethereal_tap("voip,calls",voip_calls_init_tap);
707         register_tap_menu_item("VoIP Calls...", REGISTER_TAP_GROUP_NONE,
708             voip_calls_launch, NULL, NULL, NULL);
709             
710 }