Make "register_tap_listener()" return NULL on success and a "GString *"
[metze/wireshark/wip.git] / gtk / tap_rtp.c
1 /*
2  * tap_rtp.c
3  *
4  * $Id: tap_rtp.c,v 1.10 2003/04/23 08:20:06 guy Exp $
5  *
6  * RTP analysing addition for ethereal
7  *
8  * Copyright 2003, Iskratel, Ltd, Kranj
9  * By Miha Jemec <m.jemec@iskratel.si>
10  *
11  * Ethereal - Network traffic analyzer
12  * By Gerald Combs <gerald@ethereal.com>
13  * Copyright 1998 Gerald Combs
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation,  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
28  *
29  * This tap works as follows:
30  * When the user clicks on the RTP analisys button, we first check if it is a RTP packet.
31  * If yes we store the SSRC, ip, and port values. Then the tap is registered and the 
32  * redissect_packets() routine is called. So we go through all the RTP packets and search 
33  * for SSRC of reversed connection (it has inversed socket parameters). If more than one 
34  * is found a window is displayed where the user can select the appropriate from the list.
35  * Rigth now we have the information about the converstion we are looking for (both SSRC). 
36  * The redissect_packets() routine is called again. This time whenever a RTP packet with
37  * matching SSRC values arrives, we store all the information we need (number, sequence
38  * number, arrival time, ...) and compute the delay, jitter and wrong sequence number.
39  * We add this values to CList. If the RTP packet carries voice in g711 alaw or ulaw, we
40  * also store this voice information in a temp file. Window is displayed.
41  * Then three buttons are available: Close, Refresh and Save voice.
42  * The Refresh button calls the redissect_packets() routine again. It goes through the packets
43  * again and does all the calculation again (if capturing in real time this means that some
44  * more packets could come and can be computed in statistic). It also writes the sound
45  * data again.
46  * The Save voice button opens the dialog where we can choose the file name, format (not yet)
47  * and direction we want to save. Currently it works only with g711 alaw and ulaw, and if the
48  * length of captured packets is equal the length of packets on wire and if there are no padding
49  * bits.    
50  *
51  * To do:
52  * - Support for saving voice in more different formats and with more different codecs:
53  *   Since this should be portable to all OS, there is only possibility to save the 
54  *   voice in a file and not play it directly through the sound card. There are enough 
55  *   players on all platforms, that are doing right this. What about the format? 
56  *   Currently there is only support for saving as an .au file (ulaw, 8000 Hz, 8bit)
57  *   There are many players for this format on all platforms (for example Windows Media Player
58  *   under Windows, command play under Linux). Support will be added for wav format and 
59  *   possibility to save with two channels (separate channel for each direction)
60  *
61  * - Support for more codecs. Now you can save voice only if the codec is g.711 alaw or ulaw.
62  *
63  * - right now, the reversed connection must have the same (only inversed) ip and port numbers.
64  *   I think that there is no reason that in special cases the reversed connection would not use 
65  *   some different port or even the IP combination (please correct me if I am wrong). 
66  *   So this will be added soon.
67  *
68  * - some more statistics (delay and jitter distribution)
69  *
70  * - GTK2 implementation
71  *
72  * - grammar correction
73  * 
74  * - some more testing (other OS)
75  *
76  * XXX Problems: 
77  *
78  * - instead of tmpnam() use of mkstemp(). 
79  *   I tried to do it with mkstemp() but didn't now how to solve following  problem: 
80  *   I call mkstemp() and then write in this temp file and it works fine . But if the user 
81  *   then hits the refresh button, this temp file should be deleted and opened again. I tried
82  *   to call close() and unlink(), but when I call mkstemp() for the second time I always get
83  *   an error ( -1) as return value. What is the correct order? Is it possible to call 
84  *   mkstemp() twice with the same template?    
85  *
86  * - problem with statistics for lost (late, duplicated) packets. How to make the statistic 
87  *   more resistant to special (bizarre) arrival of sequence numbers
88  */
89
90 #ifdef HAVE_CONFIG_H
91 # include "config.h"
92 #endif
93
94 #include <stdio.h>
95
96 #ifdef HAVE_SYS_TYPES_H
97 # include <sys/types.h>
98 #endif
99
100 #include <gtk/gtk.h>
101 #include "globals.h"
102 #include <string.h>
103 #include "epan/packet_info.h"
104 #include <epan/epan_dissect.h>
105 #include <epan/filesystem.h>
106 #include "../tap.h"
107 #include "../register.h"
108 #include "../packet-rtp.h"
109 #include "file_dlg.h"
110 #include "dlg_utils.h"
111 #include "ui_util.h"
112 #include "simple_dialog.h"
113 #include "menu.h"
114 #include "main.h"
115 #include <math.h>
116 #include "progress_dlg.h"
117 #include "compat_macros.h"
118 #include "../g711.h"
119 #ifdef HAVE_UNISTD_H
120 #include <unistd.h>
121 #endif
122 #include <fcntl.h>
123
124 #ifdef HAVE_IO_H
125 #include <io.h> /* open/close on win32 */
126 #endif
127
128 #ifndef O_BINARY
129 #define O_BINARY 0
130 #endif
131
132 static GtkWidget *rtp_w = NULL;
133 static GtkWidget *save_voice_as_w = NULL;
134 static GtkWidget *main_vb;
135 static GtkWidget *clist;
136 static GtkWidget *clist_r;
137 static GtkWidget *max;
138 static GtkWidget *max_r;
139
140 static gboolean copy_file(gchar *, /*gint,*/ gint, void *);
141
142 static char f_tempname[100], r_tempname[100];
143
144 /* type of error when saving voice in a file didn't succeed */
145 typedef enum {
146         TAP_RTP_WRONG_CODEC,
147         TAP_RTP_WRONG_LENGTH,
148         TAP_RTP_PADDING_SET,
149         TAP_RTP_FILE_OPEN_ERROR,
150         TAP_RTP_NO_DATA
151 } error_type_t; 
152
153 /* structure that holds the information about the forwarding and reversed connection */
154 /* f_* always aplies to the forward direction and r_* to the reversed */
155 typedef struct _info_stat {
156         gchar source[16];
157         gchar destination[16];
158         guint16 srcport;
159         guint16 dstport;
160         guint32 ssrc_forward;
161         guint32 ssrc_reversed;
162         guint32 *ssrc_tmp;
163         gboolean search_ssrc;
164         guint reversed_ip;
165         guint reversed_ip_and_port;
166         gboolean f_first_packet;
167         gboolean r_first_packet;
168         guint16 f_seq_num;
169         guint16 r_seq_num;
170         guint32 f_timestamp;
171         guint32 r_timestamp;
172         guint32 f_delta_timestamp;
173         guint32 r_delta_timestamp;
174         double f_delay;
175         double r_delay;
176         double f_jitter;
177         double r_jitter;
178         double f_time;
179         double r_time;
180         double f_start_time;
181         double r_start_time;
182         double f_max_delay;
183         double r_max_delay;
184         guint32 f_max_nr;
185         guint32 r_max_nr;
186         guint16 f_start_seq_nr;
187         guint16 r_start_seq_nr;
188         guint16 f_stop_seq_nr;
189         guint16 r_stop_seq_nr;
190         guint32 f_total_nr;
191         guint32 r_total_nr;
192         guint32 f_sequence;
193         guint32 r_sequence;
194         gint f_cycles;
195         gint r_cycles;
196         gboolean f_under;
197         gboolean r_under;
198         FILE *f_fp;
199         FILE *r_fp;
200         gboolean f_saved;
201         gboolean r_saved;
202         error_type_t f_error_type;
203         error_type_t r_error_type;
204         guint32 f_count;
205         guint32 r_count;
206 } info_stat;
207
208
209 /* when there is a [re]reading of packet's */
210 static void
211 rtp_reset(void *prs)
212 {
213   info_stat *rs=prs;
214
215   rs->f_first_packet = TRUE;
216   rs->r_first_packet = TRUE;
217   rs->f_max_delay = 0;
218   rs->r_max_delay = 0;
219   rs->f_max_nr = 0;
220   rs->r_max_nr = 0;
221   rs->f_total_nr = 0;
222   rs->r_total_nr = 0;
223   rs->f_sequence = 0;
224   rs->r_sequence = 0;
225   rs->f_start_seq_nr = 0;
226   rs->r_start_seq_nr = 1; /* 1 is ok (for statistics in reversed direction) */
227   rs->f_stop_seq_nr = 0;
228   rs->r_stop_seq_nr = 0;
229   rs->f_cycles = 0;
230   rs->r_cycles = 0;
231   rs->f_under = FALSE;
232   rs->r_under = FALSE;
233   rs->f_saved = FALSE;
234   rs->r_saved = FALSE;
235   rs->f_start_time = 0;
236   rs->r_start_time = 0;
237   rs->f_count = 0;
238   rs->r_count = 0;
239   /* XXX check for error at fclose? */
240   if (rs->f_fp != NULL)
241         fclose(rs->f_fp); 
242   if (rs->r_fp != NULL)
243         fclose(rs->r_fp); 
244   rs->f_fp = fopen(f_tempname, "wb"); 
245   if (rs->f_fp == NULL)
246         rs->f_error_type = TAP_RTP_FILE_OPEN_ERROR;
247   rs->r_fp = fopen(r_tempname, "wb");
248   if (rs->r_fp == NULL)
249         rs->r_error_type = TAP_RTP_FILE_OPEN_ERROR;
250   return;
251 }
252
253 /* here we can redraw the output */
254 /* not used yet */
255 static void rtp_draw(void *prs _U_)
256 {
257         return;
258 }
259
260 /* when we are finished with redisection, we add the label for the statistic */
261 static void draw_stat(void *prs)
262 {
263         info_stat *rs=prs;
264         gchar label_max[200];
265         guint32 f_expected = (rs->f_stop_seq_nr + rs->f_cycles*65536) - rs->f_start_seq_nr + 1;
266         guint32 r_expected = (rs->r_stop_seq_nr + rs->r_cycles*65536) - rs->r_start_seq_nr + 1;
267         gint32 f_lost = f_expected - rs->f_total_nr;
268         gint32 r_lost = r_expected - rs->r_total_nr;
269
270         g_snprintf(label_max, 199, "Max delay = %f sec at packet nr. %u \n\n"
271                 "Total RTP packets = %u   (expected %u)   Lost RTP packets = %d"  
272                 "   Sequence error = %u",
273                         rs->f_max_delay, rs->f_max_nr, rs->f_total_nr, f_expected, 
274                                                         f_lost, rs->f_sequence);
275
276         gtk_label_set_text(GTK_LABEL(max), label_max);
277
278         g_snprintf(label_max, 199, "Max delay = %f sec at packet nr. %u \n\n"
279                 "Total RTP packets = %u   (expected %u)   Lost RTP packets = %d"
280                 "   Sequence error = %u",
281                          rs->r_max_delay, rs->r_max_nr, rs->r_total_nr, r_expected,
282                                                         r_lost, rs->r_sequence);
283
284         gtk_label_set_text(GTK_LABEL(max_r), label_max);
285
286         /* could be done somewhere else, but can be here as well */
287         /* if this is true, then we don't have any reversed connection, so the error type
288          * will be no data. This applies only the reversed connection */
289         if (rs->reversed_ip_and_port == 0)
290                 rs->r_error_type = TAP_RTP_NO_DATA;
291
292         return ;
293 }
294
295 /* append a line to clist */
296 /* XXX is there a nicer way to make these assignements? */
297 static void add_to_clist(gboolean forward, guint32 number, guint16 seq_num, 
298                                 double delay, double jitter, gboolean status, gboolean marker)
299 {
300         gchar *data[6];
301         gchar field[6][30];
302
303         data[0]=&field[0][0];
304         data[1]=&field[1][0];
305         data[2]=&field[2][0];
306         data[3]=&field[3][0];
307         data[4]=&field[4][0];
308         data[5]=&field[5][0];
309
310         g_snprintf(field[0], 20, "%u", number);
311         g_snprintf(field[1], 20, "%u", seq_num);
312         g_snprintf(field[2], 20, "%f", delay);
313         g_snprintf(field[3], 20, "%f", jitter);
314         g_snprintf(field[4], 20, "%s", marker? "SET" : "");
315         g_snprintf(field[5], 29, "%s", status? "OK" : "NOK - Wrong sequence nr.");
316
317         gtk_clist_append(GTK_CLIST(forward? clist : clist_r), data);
318
319 }
320
321 /* whenever a RTP packet is seen by the tap listener */
322 /* this function works as follows:
323  * 1) packets that are not displayed are ignored
324  *      return
325  * 2) are we searching what could be the reversed connection (looking for reversed SSRC)
326  *      if yes, do the parameters match (inversed IP and port combination from the forward one)?
327  *              if yes, do we already have this SSRC stored
328  *                      if not store it
329  * 3) if not, is current packet matching the forward direction
330  *      is it the first time we see a packet in this direction
331  *              if yes, store some values, add a line to list and save the voice info
332  *              in a temporary file if the codec is supported and the RTP data is ok
333  *      if not, is it a packet with mark bit set (there was silence surpression)
334  *              same as above, only we have to add some silence in front of the voice data
335  *      if not, then this must be a normal packet
336  *              store the values and voice data
337  * 4) if not, is current packet matching the reversed connection
338  *      (same as for number 3)
339  */
340 static int rtp_packet(void *prs, packet_info *pinfo, epan_dissect_t *edt _U_, void *vpri)
341 {
342         info_stat *rs=prs;
343         struct _rtp_info *pri=vpri;
344         guint i;
345         double n_time;
346         double n_jitter;
347         guint8 *data;
348         gint16 tmp;
349
350         /* we ignore packets that are not displayed */
351         if (pinfo->fd->flags.passed_dfilter == 0)
352                 return 0;
353
354         /* are we looking for the SSRC of the reversed connection? */
355         if (rs->search_ssrc != FALSE) {
356                 /* XXX what should be the rules for reversed connection? 
357                  * 1. It should should have same inversed IP and port numbers
358                  * 2. If none are found, only inversed IP's - is this possible?
359                  * 3. If none are found, there isn't any reversed connection 
360                  * XXX is it possible that the conversation is not P2P? 
361                  * Curretly it works only if it matches the number 1. */
362
363                 /* have we found inverse parameters? */
364                 if ( strcmp(ip_to_str(pinfo->src.data), rs->destination) == 0  && 
365                                 strcmp( ip_to_str(pinfo->dst.data), rs->source) == 0 ) {
366
367                         /* do the ports also match? */
368                         if ((rs->srcport == pinfo->destport) && (rs->dstport == pinfo->srcport)) {
369                                 /* ok, the ip and port combination does match 
370                                  * do we already have this ssrc stored */
371                                 for(i=0; i< rs->reversed_ip_and_port; i++) {
372                                         if (pri->info_sync_src == *(rs->ssrc_tmp+i) ) 
373                                                 return 0;
374                                 }
375                                 
376                                 /* no, we found new ssrc, let's store it */
377                                 rs->ssrc_tmp = (guint32*)g_realloc(rs->ssrc_tmp, 
378                                                                 (i+1)*sizeof(guint32));
379                                 *(rs->ssrc_tmp+i) = pri->info_sync_src;
380                                 rs->reversed_ip_and_port++;
381                                 return 0;
382                         }
383                         /* no, only ip addresses match */
384                         /* XXX not implemented yet */
385                         else {
386                                 rs->reversed_ip++;
387                                 return 0;
388                         }
389
390                 }
391         }
392         
393         /* ok, we are not looking for SSRC of the reversed connection */
394         /* is it the forward direction? 
395          * if yes, there 3 possibilities:
396          * a) is this the first packet we got in this direction?
397          * b) or is it a packet with the mark bit set?
398          * c) if neither then it is a "normal" packet */
399         else if (rs->ssrc_forward == pri->info_sync_src) {
400                 /* first packet? */
401                 if (rs->f_first_packet != FALSE) {
402                         /* we store all the values */
403                         rs->f_seq_num = pri->info_seq_num;
404                         rs->f_delay = 0;
405                         rs->f_jitter = 0;
406                         rs->f_first_packet = FALSE;
407                         rs->f_timestamp = pri->info_timestamp;
408                         rs->f_start_seq_nr = pri->info_seq_num;
409                         rs->f_stop_seq_nr = pri->info_seq_num;
410                         rs->f_total_nr++;
411                         rs->f_time = (double)pinfo->fd->rel_secs + 
412                                                 (double) pinfo->fd->rel_usecs/1000000;
413                         rs->f_start_time = rs->f_time;
414                         /* and add a row to clist; delay and jitter are 0 for the first packet */
415                         add_to_clist(TRUE, pinfo->fd->num, pri->info_seq_num, 0, 0, TRUE, FALSE);
416
417                         /* and now save the voice info */
418
419                         /* if we couldn't open the tmp file for writing, then we set the flag */
420                         if (rs->f_fp == NULL) {
421                                 rs->f_saved = FALSE;
422                                 rs->f_error_type = TAP_RTP_FILE_OPEN_ERROR;
423                                 return 0;
424                         }
425                         /* if the captured length and packet length aren't equal, we quit 
426                          * because there is some information missing */
427                         if (pinfo->fd->pkt_len != pinfo->fd->cap_len) {
428                                 rs->f_saved = FALSE;
429                                 rs->f_error_type = TAP_RTP_WRONG_LENGTH;
430                                 return 0;
431                         }
432                         /* if padding bit is set, we don't do it yet */
433                         if (pri->info_padding_set != FALSE) {
434                                 rs->f_saved = FALSE;
435                                 rs->f_error_type = TAP_RTP_PADDING_SET;
436                                 return 0;
437                         }
438                         /* is it the ulaw? */
439                         if (pri->info_payload_type == 0) {
440                                 /* we put the pointer at the beggining of the RTP data, that is
441                                  * at the end of the current frame minus the length of the 
442                                  * RTP field plus 12 for the RTP header */
443                                 data = cfile.pd + (pinfo->fd->pkt_len - pri->info_data_len + 12);
444                                 for(i=0; i < (pri->info_data_len-12 ); i++, data++) {
445                                         tmp = (gint16 )ulaw2linear((unsigned char)*data);
446                                         fwrite(&tmp, 2, 1, rs->f_fp);
447                                         rs->f_count++;
448                                 }
449                                 rs->f_saved = TRUE;
450                                 return 0;
451                         }
452                         /* alaw? */
453                         else if (pri->info_payload_type == 8) {
454                                 data = cfile.pd + (pinfo->fd->pkt_len - pri->info_data_len + 12);
455                                 for(i=0; i < (pri->info_data_len -12 ); i++, data++) {
456                                         tmp = (gint16 )alaw2linear((unsigned char)*data);
457                                         fwrite(&tmp, 2, 1, rs->f_fp);
458                                         rs->f_count++;
459                                 }
460                                 rs->f_saved = TRUE;
461                                 return 0;
462                         }
463                         /* unsupported codec or other error */
464                         else {
465                                 rs->f_saved = FALSE;
466                                 rs->f_error_type = TAP_RTP_WRONG_CODEC;
467                                 return 0;
468                         }
469                 }
470                 
471                 /* packet with mark bit set? */
472                 if (pri->info_marker_set != FALSE) {
473                         n_time = (double)pinfo->fd->rel_secs +
474                                         (double) pinfo->fd->rel_usecs/1000000;
475                         /* jitter is calculated as for RCTP - RFC 1889 
476                          * J = J + ( | D(i-1, i) | - J) / 16
477                          * XXX the output there should be in timestamp (probably miliseconds)
478                          * units expressed as an unsigned integer, so should we do it the same? 
479                          * (currently we use seconds) 
480                          *
481                          * XXX Packet loss in RTCP is calculated as the difference between the
482                          * number of packets expected and actually received, where for actually 
483                          * received the number is simply the count of packets as they arrive, 
484                          * including any late or duplicate packets (this means that the number
485                          * can be negative). For example, if the seq numbers of the arrived
486                          * packets are: 1,2,3,4,5,5,7,7,9,10 the expected number is 10 and the
487                          * the number of actually captured frames is also 10. So in upper 
488                          * calculation there would be no losses. But there are 2 losses and 
489                          * 2 duplicate packets. Because this kind of statistic is rather 
490                          * useless (or confusing) we add the information, that there was 
491                          * an error with sequence number each time the sequence number was 
492                          * not one bigger than the previous one
493                         */
494                        
495                         /* jitter calculation */
496                         n_jitter = rs->f_jitter + ( fabs(n_time-(rs->f_time) - 
497                                         ((double)(pri->info_timestamp)-
498                                         (double)(rs->f_timestamp))/8000) - rs->f_jitter)/16;
499
500                         /* we add the information into the clist */
501                         add_to_clist(TRUE, pinfo->fd->num, pri->info_seq_num, n_time-(rs->f_time),
502                                  n_jitter, rs->f_seq_num+1 == pri->info_seq_num?TRUE:FALSE, TRUE);
503
504                         /* when calculating expected rtp packets the seq number can wrap around
505                          * so we have to count the number of cycles 
506                          * f_cycles counts the wraps around in forwarding connection and
507                          * f_under is flag that indicates where we are 
508                          *
509                          * XXX how to determine number of cycles with all possible lost, late
510                          * and duplicated packets without any doubt? It seems to me, that 
511                          * because of all possible combination of late, duplicated or lost
512                          * packets, this can only be more or less good approximation
513                          *
514                          * There are some combinations (rare but theoretically possible), 
515                          * where below code won't work correctly - statistic may be wrong then.
516                          */
517
518                         /* so if the current sequence number is less than the start one
519                          * we assume, that there is another cycle running */
520                         if ((pri->info_seq_num < rs->f_start_seq_nr) && (rs->f_under == FALSE)){
521                                 rs->f_cycles++;
522                                 rs->f_under = TRUE;
523                         }
524                         /* what if the start seq nr was 0. Then the above condition will never 
525                          * be true, so we add another condition. XXX The problem would arise if
526                          * if one of the packets with seq nr 0 or 65535 would be lost or late */
527                         else if ((pri->info_seq_num == 0) && (rs->f_stop_seq_nr == 65535) && 
528                                                                         (rs->f_under == FALSE)){
529                                 rs->f_cycles++;
530                                 rs->f_under = TRUE;
531                         }
532                         /* the whole round is over, so reset the flag */
533                         else if ((pri->info_seq_num>rs->f_start_seq_nr)&&(rs->f_under!=FALSE)){
534                                 rs->f_under = FALSE;
535                         }
536
537                         /* number of times where sequence number was not ok */
538                         if ( rs->f_seq_num+1 == pri->info_seq_num)
539                                 rs->f_seq_num = pri->info_seq_num;
540                         /* XXX same problem as above */
541                         else if ( (rs->f_seq_num == 65535) && (pri->info_seq_num == 0) )
542                                 rs->f_seq_num = pri->info_seq_num;
543                         /* lost packets */
544                         else if (rs->f_seq_num+1 < pri->info_seq_num) {
545                                 rs->f_seq_num = pri->info_seq_num;
546                                 rs->f_sequence++;
547                         }
548                         /* late or duplicated */
549                         else if (rs->f_seq_num+1 > pri->info_seq_num)
550                                 rs->f_sequence++;
551
552                         rs->f_stop_seq_nr = pri->info_seq_num;
553                         rs->f_time = n_time;
554                         rs->f_jitter = n_jitter;
555                         rs->f_delta_timestamp = pri->info_timestamp - rs->f_timestamp;
556                         rs->f_timestamp = pri->info_timestamp;
557                         rs->f_total_nr++;
558
559                         /* save the voice information */
560                         /* if there was already an error, we quit */
561                         if (rs->f_saved == FALSE)
562                                 return 0;
563                         /* if the captured length and packet length aren't equal, we quit */
564                         if (pinfo->fd->pkt_len != pinfo->fd->cap_len) {
565                                 rs->f_saved = FALSE;
566                                 rs->f_error_type = TAP_RTP_WRONG_LENGTH;
567                                 return 0;
568                         }
569                         /* if padding bit is set, we don't do it yet */
570                         if (pri->info_padding_set != FALSE) {
571                                 rs->f_saved = FALSE;
572                                 rs->f_error_type = TAP_RTP_PADDING_SET;
573                                 return 0;
574                         }
575                         /* because the mark bit is set, we have to add some silence in front */
576                         /* is it the ulaw? */
577                         if (pri->info_payload_type == 0) {
578                                 /* we insert some silence */
579                                 /* XXX the amount of silence should be the difference between
580                                  * the last timestamp and the current one minus x in the
581                                  * I am not sure if x is equal the amount of information 
582                                  * current packet? */
583                                 for(i=0; i<(rs->f_delta_timestamp-pri->info_data_len+12); i++) {
584                                         tmp = (gint16 )ulaw2linear((unsigned char)(0x55));
585                                         fwrite(&tmp, 2, 1, rs->f_fp);
586                                         rs->f_count++;
587                                 }
588                                 data = cfile.pd + (pinfo->fd->pkt_len - pri->info_data_len + 12);
589                                 for(i=0; i < (pri->info_data_len-12 ); i++, data++) {
590                                         tmp = (gint16 )ulaw2linear((unsigned char)*data);
591                                         fwrite(&tmp, 2, 1, rs->f_fp);
592                                         rs->f_count++;
593                                 }
594                                 return 0;
595                         }
596                         /* alaw? */
597                         else if (pri->info_payload_type == 8) {
598                                 for(i=0; i < (rs->f_delta_timestamp-pri->info_data_len+12); i++) {
599                                         tmp = (gint16 )ulaw2linear((unsigned char)(0x55));
600                                         fwrite(&tmp, 2, 1, rs->f_fp);
601                                         rs->f_count++;
602                                 }
603                                 data = cfile.pd + (pinfo->fd->pkt_len - pri->info_data_len + 12);
604                                 for(i=0; i < (pri->info_data_len -12 ); i++, data++) {
605                                         tmp = (gint16 )alaw2linear((unsigned char)*data);
606                                         fwrite(&tmp, 2, 1, rs->f_fp);
607                                         rs->f_count++;
608                                 }
609                                 return 0;
610                         }
611                         /* unsupported codec or other error */
612                         else {
613                                 rs->f_saved = FALSE;
614                                 rs->f_error_type = TAP_RTP_WRONG_CODEC;
615                                 return 0;
616                         }
617                         return 0;
618                 }
619                 
620                 /* normal packet in forward connection */
621                 n_time = (double)pinfo->fd->rel_secs +
622                                         (double) pinfo->fd->rel_usecs/1000000;
623                 n_jitter = rs->f_jitter + ( fabs (n_time-(rs->f_time) - 
624                                 ((double)(pri->info_timestamp)-
625                                 (double)(rs->f_timestamp))/8000) - rs->f_jitter)/16;
626                 rs->f_delay =  n_time-(rs->f_time);
627                 /* the delay is bigger than previous max delay, so store the delay and nr */
628                 if (rs->f_delay > rs->f_max_delay) {
629                         rs->f_max_delay = rs->f_delay;
630                         rs->f_max_nr = pinfo->fd->num;
631                 }
632                 add_to_clist(TRUE, pinfo->fd->num, pri->info_seq_num, n_time-(rs->f_time),
633                                  n_jitter, rs->f_seq_num+1 == pri->info_seq_num?TRUE:FALSE, FALSE);
634
635                 /* count the cycles */
636                 if ((pri->info_seq_num < rs->f_start_seq_nr) && (rs->f_under == FALSE)){
637                         rs->f_cycles++;
638                         rs->f_under = TRUE;
639                 }
640                 else if ((pri->info_seq_num == 0) && (rs->f_stop_seq_nr == 65535) && 
641                                                                 (rs->f_under == FALSE)){
642                         rs->f_cycles++;
643                         rs->f_under = TRUE;
644                 }
645                 /* the whole round is over, so reset the flag */
646                 else if ((pri->info_seq_num>rs->f_start_seq_nr+1)&&(rs->f_under!=FALSE)){
647                         rs->f_under = FALSE;
648                 }
649
650                 /* number of times where sequence number was not ok */
651                 if ( rs->f_seq_num+1 == pri->info_seq_num)
652                         rs->f_seq_num = pri->info_seq_num;
653                 else if ( (rs->f_seq_num == 65535) && (pri->info_seq_num == 0) )
654                         rs->f_seq_num = pri->info_seq_num;
655                 /* lost packets */
656                 else if (rs->f_seq_num+1 < pri->info_seq_num) {
657                         rs->f_seq_num = pri->info_seq_num;
658                         rs->f_sequence++;
659                 }
660                 /* late or duplicated */
661                 else if (rs->f_seq_num+1 > pri->info_seq_num)
662                         rs->f_sequence++;
663
664                 rs->f_stop_seq_nr = pri->info_seq_num;
665                 rs->f_time = n_time;
666                 rs->f_jitter = n_jitter;
667                 rs->f_timestamp = pri->info_timestamp;
668                 rs->f_total_nr++;
669
670                 /* save the voice information */
671                 /* we do it only in following cases:
672                  * - the codecs we support are g.711 alaw in ulaw
673                  * - the captured length must equal the packet length
674                  * - XXX we don't support it if there are padding bits 
675                  */
676                 /* if there was already an error, we quit */
677                 if (rs->f_saved == FALSE)
678                         return 0;
679                 /* if the captured length and packet length aren't equal, we quit */
680                 if (pinfo->fd->pkt_len != pinfo->fd->cap_len) {
681                         rs->f_saved = FALSE;
682                         rs->f_error_type = TAP_RTP_WRONG_LENGTH;
683                         return 0;
684                 }
685                 /* if padding bit is set, we don't do it yet */
686                 if (pri->info_padding_set != FALSE) {
687                         rs->f_saved = FALSE;
688                         rs->f_error_type = TAP_RTP_PADDING_SET;
689                         return 0;
690                 }
691                 /* is it the ulaw? */
692                 if (pri->info_payload_type == 0) {
693                         /* cfile.pd points at the beggining of the actual packet. We have
694                          * to move this pointer at the RTP data. This is the packet length,
695                          * minus whole RTP data length (including the RTP header, that is
696                          * why we add 12) */
697                         data = cfile.pd + (pinfo->fd->pkt_len - pri->info_data_len + 12);
698                         for(i=0; i < (pri->info_data_len - 12); i++, data++) {
699                                 tmp = (gint16 )ulaw2linear((unsigned char)*data);
700                                 fwrite(&tmp, 2, 1, rs->f_fp);
701                                 rs->f_count++;
702                         }
703                         return 0;                               
704                 }
705                 /* alaw? */
706                 else if (pri->info_payload_type == 8) {
707                         data = cfile.pd + (pinfo->fd->pkt_len - pri->info_data_len + 12);
708                         for(i=0; i < (pri->info_data_len-12 ); i++, data++) {
709                                 tmp = (gint16 )alaw2linear((unsigned char)*data);
710                                 fwrite(&tmp, 2, 1, rs->f_fp);
711                                 rs->f_count++;
712                         }
713                         return 0;
714                 }
715                 /* unsupported codec or other error */
716                 else {
717                         rs->f_saved = FALSE;
718                         rs->f_error_type = TAP_RTP_WRONG_CODEC;
719                         return 0;
720                 }
721         }                               
722
723         /* is it the reversed direction? */
724         else if (rs->ssrc_reversed == pri->info_sync_src) {
725                 /* first packet? */
726                 if (rs->r_first_packet !=FALSE) {
727                         rs->r_seq_num = pri->info_seq_num;
728                         rs->r_delay = 0;
729                         rs->r_jitter = 0;
730                         rs->r_first_packet = FALSE;
731                         rs->r_timestamp = pri->info_timestamp;
732                         rs->r_start_seq_nr = pri->info_seq_num;
733                         rs->r_stop_seq_nr = pri->info_seq_num;
734                         rs->r_total_nr++;
735                         rs->r_time = (double)pinfo->fd->rel_secs + 
736                                                 (double) pinfo->fd->rel_usecs/1000000;
737                         rs->r_start_time = rs->r_time;
738                         add_to_clist(FALSE, pinfo->fd->num, pri->info_seq_num, 0, 0, TRUE, FALSE);
739
740                         /* save it */
741                         /* if we couldn't open the tmp file for writing, then we set the flag */
742                         if (rs->r_fp == NULL) {
743                                 rs->r_saved = FALSE;
744                                 return 0;
745                         }
746                         /* if the captured length and packet length aren't equal, we quit */
747                         if (pinfo->fd->pkt_len != pinfo->fd->cap_len) {
748                                 rs->r_saved = FALSE;
749                                 rs->r_error_type = TAP_RTP_WRONG_LENGTH;
750                                 return 0;
751                         }
752                         /* if padding bit is set, we don't do it yet */
753                         if (pri->info_padding_set != FALSE) {
754                                 rs->r_saved = FALSE;
755                                 rs->r_error_type = TAP_RTP_PADDING_SET;
756                                 return 0;
757                         }
758                         /* is it the ulaw? */
759                         if (pri->info_payload_type == 0) {
760                                 data = cfile.pd + (pinfo->fd->pkt_len - pri->info_data_len + 12);
761                                 for(i=0; i < (pri->info_data_len-12 ); i++, data++) {
762                                         tmp = (gint16 )ulaw2linear((unsigned char)*data);
763                                         fwrite(&tmp, 2, 1, rs->r_fp);
764                                         rs->r_count++;
765                                 }
766                                 rs->r_saved = TRUE;
767                                 return 0;
768                         }
769                         /* alaw? */
770                         else if (pri->info_payload_type == 8) {
771                                 data = cfile.pd + (pinfo->fd->pkt_len - pri->info_data_len + 12);
772                                 for(i=0; i < (pri->info_data_len -12 ); i++, data++) {
773                                         tmp = (gint16 )alaw2linear((unsigned char)*data);
774                                         fwrite(&tmp, 2, 1, rs->r_fp);
775                                         rs->r_count++;
776                                 }
777                                 rs->r_saved = TRUE;
778                                 return 0;
779                         }
780                         /* unsupported codec or other error */
781                         else {
782                                 rs->r_saved = FALSE;
783                                 rs->r_error_type = TAP_RTP_WRONG_CODEC;
784                                 return 0;
785                         }
786                 }
787                 
788                 /* packet with mark bit set? */
789                 if (pri->info_marker_set != FALSE) {
790                         n_time = (double)pinfo->fd->rel_secs +
791                                         (double) pinfo->fd->rel_usecs/1000000;
792                         n_jitter = rs->r_jitter + ( fabs (n_time-(rs->r_time) - 
793                                         ((double)(pri->info_timestamp)-
794                                         (double)(rs->r_timestamp))/8000) - rs->r_jitter)/16;
795                         add_to_clist(FALSE, pinfo->fd->num, pri->info_seq_num, n_time-(rs->r_time),
796                                  n_jitter, rs->r_seq_num+1 == pri->info_seq_num?TRUE:FALSE, TRUE);
797
798                         /* count the cycles */
799                         if ((pri->info_seq_num < rs->r_start_seq_nr) && (rs->r_under == FALSE)){
800                                 rs->r_cycles++;
801                                 rs->r_under = TRUE;
802                         }
803                         else if ((pri->info_seq_num == 0) && (rs->r_stop_seq_nr == 65535) && 
804                                                                         (rs->r_under == FALSE)){
805                                 rs->r_cycles++;
806                                 rs->r_under = TRUE;
807                         }
808                         /* the whole round is over, so reset the flag */
809                         else if ((pri->info_seq_num>rs->r_start_seq_nr+1)&&(rs->r_under!=FALSE)){
810                                 rs->r_under = FALSE;
811                         }
812
813                         /* number of times where sequence number was not ok */
814                         if ( rs->r_seq_num+1 == pri->info_seq_num)
815                                 rs->r_seq_num = pri->info_seq_num;
816                         else if ( (rs->r_seq_num == 65535) && (pri->info_seq_num == 0) )
817                                 rs->r_seq_num = pri->info_seq_num;
818                         /* lost packets */
819                         else if (rs->r_seq_num+1 < pri->info_seq_num) {
820                                 rs->r_seq_num = pri->info_seq_num;
821                                 rs->r_sequence++;
822                         }
823                         /* late or duplicated */
824                         else if (rs->r_seq_num+1 > pri->info_seq_num)
825                                 rs->r_sequence++;
826
827                         rs->r_stop_seq_nr = pri->info_seq_num;
828                         rs->r_time = n_time;
829                         rs->r_jitter = n_jitter;
830                         rs->r_delta_timestamp = pri->info_timestamp - rs->r_timestamp;
831                         rs->r_timestamp = pri->info_timestamp;
832                         rs->r_total_nr++;
833
834                         /* save the voice information */
835                         /* if there was already an error, we quit */
836                         if (rs->r_saved == FALSE)
837                                 return 0;
838                         /* if the captured length and packet length aren't equal, we quit */
839                         if (pinfo->fd->pkt_len != pinfo->fd->cap_len) {
840                                 rs->r_saved = FALSE;
841                                 rs->r_error_type = TAP_RTP_WRONG_LENGTH;
842                                 return 0;
843                         }
844                         /* if padding bit is set, we don't do it yet */
845                         if (pri->info_padding_set != FALSE) {
846                                 rs->r_saved = FALSE;
847                                 rs->r_error_type = TAP_RTP_PADDING_SET;
848                                 return 0;
849                         }
850                         /* because the mark bit is set, we have to add some silence in front */
851                         /* is it the ulaw? */
852                         if (pri->info_payload_type == 0) {
853                                 /* we insert some silence */
854                                 for(i=0; i<(rs->r_delta_timestamp-pri->info_data_len+12); i++) {
855                                         tmp = (gint16 )ulaw2linear((unsigned char)(0x55));
856                                         fwrite(&tmp, 2, 1, rs->r_fp);
857                                         rs->r_count++;
858                                 }
859                                 data = cfile.pd + (pinfo->fd->pkt_len - pri->info_data_len + 12);
860                                 for(i=0; i < (pri->info_data_len-12 ); i++, data++) {
861                                         tmp = (gint16 )ulaw2linear((unsigned char)*data);
862                                         fwrite(&tmp, 2, 1, rs->r_fp);
863                                         rs->r_count++;
864                                 }
865                                 return 0;
866                         }
867                         /* alaw? */
868                         else if (pri->info_payload_type == 8) {
869                                 for(i=0; i < (rs->r_delta_timestamp-pri->info_data_len+12); i++) {
870                                         tmp = (gint16 )ulaw2linear((unsigned char)(0x55));
871                                         fwrite(&tmp, 2, 1, rs->r_fp);
872                                         rs->r_count++;
873                                 }
874                                 data = cfile.pd + (pinfo->fd->pkt_len - pri->info_data_len + 12);
875                                 for(i=0; i < (pri->info_data_len -12 ); i++, data++) {
876                                         tmp = (gint16 )alaw2linear((unsigned char)*data);
877                                         fwrite(&tmp, 2, 1, rs->r_fp);
878                                         rs->r_count++;
879                                 }
880                                 return 0;
881                         }
882                         /* unsupported codec or other error */
883                         else {
884                                 rs->r_saved = FALSE;
885                                 rs->r_error_type = TAP_RTP_WRONG_CODEC;
886                                 return 0;
887                         }
888                         return 0;
889                 }
890                 
891                 /* normal packet in reversed connection */
892                 n_time = (double)pinfo->fd->rel_secs +
893                                 (double) pinfo->fd->rel_usecs/1000000;
894                 n_jitter = rs->r_jitter + ( fabs (n_time-(rs->r_time) - 
895                                 ((double)(pri->info_timestamp)-
896                                 (double)(rs->r_timestamp))/8000) - rs->r_jitter)/16;
897                 rs->r_delay =  n_time-(rs->r_time);
898                 if (rs->r_delay > rs->r_max_delay) {
899                         rs->r_max_delay = rs->r_delay;
900                         rs->r_max_nr = pinfo->fd->num;
901                 }
902                 add_to_clist(FALSE, pinfo->fd->num, pri->info_seq_num, n_time-(rs->r_time),
903                                  n_jitter, rs->r_seq_num+1 == pri->info_seq_num?TRUE:FALSE, FALSE);
904                 /* count the cycles */
905                 if ((pri->info_seq_num < rs->r_start_seq_nr) && (rs->r_under == FALSE)){
906                         rs->r_cycles++;
907                         rs->r_under = TRUE;
908                 }
909                 else if ((pri->info_seq_num == 0) && (rs->r_stop_seq_nr == 65535) && 
910                                                                 (rs->r_under == FALSE)){
911                         rs->r_cycles++;
912                         rs->r_under = TRUE;
913                 }
914                 /* the whole round is over, so reset the flag */
915                 else if ((pri->info_seq_num>rs->r_start_seq_nr+1)&&(rs->r_under!=FALSE)){
916                         rs->r_under = FALSE;
917                 }
918
919                 /* number of times where sequence number was not ok */
920                 if ( rs->r_seq_num+1 == pri->info_seq_num)
921                         rs->r_seq_num = pri->info_seq_num;
922                 else if ( (rs->r_seq_num == 65535) && (pri->info_seq_num == 0) )
923                         rs->r_seq_num = pri->info_seq_num;
924                 /* lost packets */
925                 else if (rs->r_seq_num+1 < pri->info_seq_num) {
926                         rs->r_seq_num = pri->info_seq_num;
927                         rs->r_sequence++;
928                 }
929                 /* late or duplicated */
930                 else if (rs->r_seq_num+1 > pri->info_seq_num)
931                         rs->r_sequence++;
932
933                 rs->r_stop_seq_nr = pri->info_seq_num;
934                 rs->r_time = n_time;
935                 rs->r_jitter = n_jitter;
936                 rs->r_timestamp = pri->info_timestamp;
937                 rs->r_total_nr++;
938
939                 /* save the voice information */
940                 /* if there was already an error, we quit */
941                 if (rs->r_saved == FALSE)
942                         return 0;
943                 /* if the captured length and packet length aren't equal, we quit */
944                 if (pinfo->fd->pkt_len != pinfo->fd->cap_len) {
945                         rs->r_saved = FALSE;
946                         rs->r_error_type = TAP_RTP_WRONG_LENGTH;
947                         return 0;
948                 }
949                 /* if padding bit is set, we don't do it yet */
950                 if (pri->info_padding_set != FALSE) {
951                         rs->r_saved = FALSE;
952                         rs->r_error_type = TAP_RTP_PADDING_SET;
953                         return 0;
954                 }
955                 /* is it the ulaw? */
956                 if (pri->info_payload_type == 0) {
957                         data = cfile.pd + (pinfo->fd->pkt_len - pri->info_data_len + 12);
958                         for(i=0; i < (pri->info_data_len-12 ); i++, data++) {
959                                 tmp = (gint16 )ulaw2linear((unsigned char)*data);
960                                 fwrite(&tmp, 2, 1, rs->r_fp);
961                                 rs->r_count++;
962                         }
963                         return 0;
964                 }
965                 /* alaw? */
966                 else if (pri->info_payload_type == 8) {
967                         data = cfile.pd + (pinfo->fd->pkt_len - pri->info_data_len + 12);
968                         for(i=0; i < (pri->info_data_len -12 ); i++, data++) {
969                                 tmp = (gint16 )alaw2linear((unsigned char)*data);
970                                 fwrite(&tmp, 2, 1, rs->r_fp);
971                                 rs->r_count++;
972                         }
973                         return 0;
974                 }
975                 /* unsupported codec or other error */
976                 else {
977                         rs->r_saved = FALSE;
978                         rs->r_error_type = TAP_RTP_WRONG_CODEC;
979                         return 0;
980                 }
981         }                               
982
983         return 0;
984 }
985
986 /* XXX just copied from gtk/rpc_stat.c */
987 void protect_thread_critical_region(void);
988 void unprotect_thread_critical_region(void);
989
990
991 /* here we close the rtp analysis dialog window and remove the tap listener */
992 static void rtp_destroy_cb(GtkWidget *win _U_, gpointer data _U_)
993 {
994   info_stat *rs=(info_stat *)data;
995
996   protect_thread_critical_region();
997   remove_tap_listener(rs);
998   unprotect_thread_critical_region();
999
1000   /* xxx is this enough? */
1001   g_free(rs->ssrc_tmp);
1002   g_free(rs);
1003  
1004   if (rs->f_fp != NULL)
1005         fclose(rs->f_fp);
1006   if (rs->r_fp != NULL)
1007         fclose(rs->r_fp);
1008   remove(f_tempname);
1009   remove(r_tempname);
1010
1011   /* Is there a save voice window open? */
1012   if (save_voice_as_w != NULL)
1013         gtk_widget_destroy(save_voice_as_w);
1014
1015   /* Note that we no longer have a "RTP Analyse" dialog box. */
1016   rtp_w = NULL;
1017 }
1018
1019 /* when the close button in rtp window was clicked */
1020 /* it seems to me that rtp_destroy_cb is automatically called, so we don't
1021  * need to do the g_free... and rtp_w = NULL ... */
1022 static void rtp_destroy (GtkWidget *close_bt _U_, gpointer parent_w)
1023 {
1024     gtk_grab_remove(GTK_WIDGET(parent_w));
1025     gtk_widget_destroy(GTK_WIDGET(parent_w));
1026 }
1027
1028 /* we search the rtp.ssrc node here (thanks to Guy Harris - code here is magic for me */
1029 static guint32 process_node(proto_item *ptree_node, header_field_info *hfinformation) 
1030 {
1031   field_info            *finfo;
1032   proto_item            *proto_sibling_node;
1033   header_field_info     *hfssrc;
1034   guint32 ssrc;
1035
1036   finfo = PITEM_FINFO(ptree_node);
1037
1038   if (hfinformation==(finfo->hfinfo)) {
1039         hfssrc = proto_registrar_get_byname("rtp.ssrc");
1040         if (hfssrc == NULL)
1041                 return 0;
1042         for(ptree_node=g_node_first_child(ptree_node); ptree_node!=NULL; 
1043                                 ptree_node=g_node_next_sibling(ptree_node)) {
1044                 finfo=PITEM_FINFO(ptree_node);
1045                 if (hfssrc==finfo->hfinfo) {
1046                         ssrc = fvalue_get_integer(finfo->value);
1047                         return ssrc;
1048                 }
1049                 }
1050   }
1051
1052   proto_sibling_node = g_node_next_sibling(ptree_node);
1053
1054   if (proto_sibling_node) {
1055         ssrc = process_node(proto_sibling_node, hfinformation);
1056         return ssrc;
1057   }
1058   else
1059         return 0;
1060 }
1061
1062 /* here we search the rtp protocol */
1063 static guint32 process_tree(proto_tree *protocol_tree)
1064 {
1065   proto_item      *ptree_node;
1066   header_field_info     *hfinformation;
1067
1068   hfinformation = proto_registrar_get_byname("rtp");
1069   if (hfinformation == NULL)
1070         return 0;
1071
1072   ptree_node = g_node_first_child(protocol_tree);
1073   if (!ptree_node)
1074         return 0;
1075
1076   return process_node(ptree_node, hfinformation);
1077 }
1078
1079 /* when we want to update the information */
1080 static void refresh_cb(GtkWidget *w _U_, void *pri)
1081 {
1082   info_stat *rs=pri;
1083
1084   gtk_clist_clear(GTK_CLIST(clist));
1085   gtk_clist_clear(GTK_CLIST(clist_r));
1086   redissect_packets(&cfile);
1087   draw_stat(rs);
1088 }
1089
1090 static void save_voice_as_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1091 {
1092   /* Note that we no longer have a Save voice info dialog box. */
1093   save_voice_as_w = NULL;
1094 }
1095
1096 /* the user wants to save in a file */
1097 /* XXX support for different formats is currently commented out */
1098 static void save_voice_as_ok_cb(GtkWidget *ok_bt, gpointer fs)
1099 {
1100   gchar *g_dest;
1101   /*GtkWidget *wav, *au, *sw;*/
1102   GtkWidget *rev, *forw, *both;
1103   info_stat *rs;
1104   gint channels /*, format*/;
1105
1106   g_dest = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION (fs)));
1107
1108   /* Perhaps the user specified a directory instead of a file.
1109      Check whether they did. */
1110   if (test_for_directory(g_dest) == EISDIR) {
1111         /* It's a directory - set the file selection box to display it. */
1112         set_last_open_dir(g_dest);
1113         g_free(g_dest);
1114         gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
1115         return;
1116   }
1117
1118   /*wav = (GtkWidget *)OBJECT_GET_DATA(ok_bt, "wav_rb");
1119   au = (GtkWidget *)OBJECT_GET_DATA(ok_bt, "au_rb");
1120   sw = (GtkWidget *)OBJECT_GET_DATA(ok_bt, "sw_rb");*/
1121   rev = (GtkWidget *)OBJECT_GET_DATA(ok_bt, "reversed_rb");
1122   forw = (GtkWidget *)OBJECT_GET_DATA(ok_bt, "forward_rb");
1123   both = (GtkWidget *)OBJECT_GET_DATA(ok_bt, "both_rb");
1124   rs = (info_stat *)OBJECT_GET_DATA(ok_bt, "info_stat");
1125
1126   /* XXX user clicks the ok button, but we know we can't save the voice info because f.e.
1127    * we don't support that codec. So we pop up a warning. Maybe it would be better to
1128    * disable the ok button or disable the buttons for direction if only one is not ok. The
1129    * problem is if we open the save voice dialog and then click the refresh button and maybe 
1130    * the state changes, so we can't save anymore. In this case we should be able to update
1131    * the buttons. For now it is easier if we put the warning when the ok button is pressed.
1132    */
1133
1134   /* we can not save in both dirctions */
1135   if ((rs->f_saved == FALSE) && (rs->r_saved == FALSE) && (GTK_TOGGLE_BUTTON (both)->active)) {
1136         /* there are many combinations here, we just exit when first matches */
1137         if ((rs->f_error_type == TAP_RTP_WRONG_CODEC) || (rs->r_error_type == TAP_RTP_WRONG_CODEC))
1138                 simple_dialog(ESD_TYPE_CRIT, NULL, 
1139                 "Can't save in a file: Unsupported codec!");
1140         else if ((rs->f_error_type == TAP_RTP_WRONG_LENGTH) || (rs->r_error_type == TAP_RTP_WRONG_LENGTH))
1141                 simple_dialog(ESD_TYPE_CRIT, NULL, 
1142                 "Can't save in a file: Wrong length of captured packets!");
1143         else if ((rs->f_error_type == TAP_RTP_PADDING_SET) || (rs->r_error_type == TAP_RTP_PADDING_SET))
1144                 simple_dialog(ESD_TYPE_CRIT, NULL, 
1145                 "Can't save in a file: RTP data with padding!");
1146         else  
1147                 simple_dialog(ESD_TYPE_CRIT, NULL, 
1148                 "Can't save in a file: File I/O problem!");
1149         return;
1150   }
1151   /* we can not save forward direction */
1152   else if ((rs->f_saved == FALSE) && ((GTK_TOGGLE_BUTTON (forw)->active) ||
1153                                                 (GTK_TOGGLE_BUTTON (both)->active))) {  
1154         if (rs->f_error_type == TAP_RTP_WRONG_CODEC)
1155                 simple_dialog(ESD_TYPE_CRIT, NULL, 
1156                 "Can't save forward direction in a file: Unsupported codec!");
1157         else if (rs->f_error_type == TAP_RTP_WRONG_LENGTH)
1158                 simple_dialog(ESD_TYPE_CRIT, NULL,
1159                 "Can't save forward direction in a file: Wrong length of captured packets!");
1160         else if (rs->f_error_type == TAP_RTP_PADDING_SET)
1161                 simple_dialog(ESD_TYPE_CRIT, NULL, 
1162                 "Can't save forward direction in a file: RTP data with padding!");
1163         else
1164                 simple_dialog(ESD_TYPE_CRIT, NULL, 
1165                 "Can't save forward direction in a file: File I/O problem!");
1166         return;
1167   }
1168   /* we can not save reversed direction */
1169   else if ((rs->r_saved == FALSE) && ((GTK_TOGGLE_BUTTON (rev)->active) ||
1170                                                 (GTK_TOGGLE_BUTTON (both)->active))) {  
1171         if (rs->r_error_type == TAP_RTP_WRONG_CODEC)
1172                 simple_dialog(ESD_TYPE_CRIT, NULL,
1173                 "Can't save reversed direction in a file: Unsupported codec!");
1174         else if (rs->r_error_type == TAP_RTP_WRONG_LENGTH)
1175                 simple_dialog(ESD_TYPE_CRIT, NULL,
1176                 "Can't save reversed direction in a file: Wrong length of captured packets!");
1177         else if (rs->r_error_type == TAP_RTP_PADDING_SET)
1178                 simple_dialog(ESD_TYPE_CRIT, NULL,
1179                 "Can't save reversed direction in a file: RTP data with padding!");
1180         else if (rs->r_error_type == TAP_RTP_NO_DATA)
1181                 simple_dialog(ESD_TYPE_CRIT, NULL,
1182                 "Can't save reversed direction in a file: No RTP data!");
1183         else
1184                 simple_dialog(ESD_TYPE_CRIT, NULL,
1185                 "Can't save reversed direction in a file: File I/O problem!");
1186         return;
1187   }
1188
1189   /*if (GTK_TOGGLE_BUTTON (wav)->active)
1190         format = 1;
1191   else if (GTK_TOGGLE_BUTTON (au)->active)
1192         format = 2;
1193   else if (GTK_TOGGLE_BUTTON (sw)->active)
1194         format = 3;*/
1195
1196   if (GTK_TOGGLE_BUTTON (rev)->active)
1197         channels = 2;
1198   else if (GTK_TOGGLE_BUTTON (both)->active)
1199         channels = 3;
1200   else 
1201         channels = 1;
1202
1203   if(!copy_file(g_dest, channels/*, format*/, rs)) {
1204         simple_dialog(ESD_TYPE_CRIT, NULL, "An error occured while saving voice in a file!");
1205         return;
1206   }
1207
1208   /* XXX I get GTK warning (sometimes?)!!! */
1209   gtk_widget_destroy(GTK_WIDGET(save_voice_as_w));
1210 }
1211
1212 /* when the user wants to save the voice information in a file */
1213 /* XXX support for different formats is currently commented out */
1214 static void save_voice_as_cb(GtkWidget *w _U_, gpointer data)
1215 {
1216   info_stat *rs=(info_stat *)data;
1217
1218   GtkWidget *vertb;
1219   GtkWidget *table1;
1220   GtkWidget *label_format;
1221   GtkWidget *channels_label;
1222   /*GSList *format_group = NULL;*/
1223   GSList *channels_group = NULL;
1224   GtkWidget *forward_rb;
1225   GtkWidget *reversed_rb;
1226   GtkWidget *both_rb;
1227   /*GtkWidget *wav_rb; GtkWidget *au_rb; GtkWidget *sw_rb;*/
1228   GtkWidget *ok_bt;
1229
1230   /* if we can't save in a file: wrong codec, cut packets or other errors */
1231   /* shold the error arise here or later when you click ok button ? 
1232    * if we do it here, then we must disable the refresh button, so we don't do it here */
1233
1234   if (save_voice_as_w != NULL) {
1235         /* There's already a Save voice info dialog box; reactivate it. */
1236         reactivate_window(save_voice_as_w);
1237         return;
1238   }
1239   
1240   save_voice_as_w = gtk_file_selection_new("Ethereal: Save Voice Data As");
1241   gtk_signal_connect(GTK_OBJECT(save_voice_as_w), "destroy",
1242        GTK_SIGNAL_FUNC(save_voice_as_destroy_cb), NULL);
1243
1244   /* Container for each row of widgets */
1245   vertb = gtk_vbox_new(FALSE, 0);
1246   gtk_container_border_width(GTK_CONTAINER(vertb), 5);
1247   gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(save_voice_as_w)->action_area),
1248     vertb, FALSE, FALSE, 0);
1249   gtk_widget_show (vertb);
1250
1251   table1 = gtk_table_new (2, 4, FALSE);
1252   gtk_widget_show (table1);
1253   gtk_box_pack_start (GTK_BOX (vertb), table1, FALSE, FALSE, 0);
1254   gtk_container_set_border_width (GTK_CONTAINER (table1), 10);
1255   gtk_table_set_row_spacings (GTK_TABLE (table1), 20);
1256
1257   label_format = gtk_label_new ("Format: .au (ulaw, 8 bit, 8000 Hz, mono) ");
1258   gtk_widget_show (label_format);
1259   gtk_table_attach (GTK_TABLE (table1), label_format, 0, 3, 0, 1,
1260                     (GtkAttachOptions) (GTK_FILL),
1261                     (GtkAttachOptions) (0), 0, 0);
1262
1263   /* we support .au - ulaw*/ 
1264 /*  wav_rb = gtk_radio_button_new_with_label (format_group, ".wav");
1265   format_group = gtk_radio_button_group (GTK_RADIO_BUTTON (wav_rb));
1266   gtk_widget_show (wav_rb);
1267   gtk_table_attach (GTK_TABLE (table1), wav_rb, 1, 2, 0, 1,
1268                     (GtkAttachOptions) (GTK_FILL),
1269                     (GtkAttachOptions) (0), 0, 0);
1270
1271   sw_rb = gtk_radio_button_new_with_label (format_group, "8 kHz, 16 bit  ");
1272   format_group = gtk_radio_button_group (GTK_RADIO_BUTTON (sw_rb));
1273   gtk_widget_show (sw_rb);
1274   gtk_table_attach (GTK_TABLE (table1), sw_rb, 2, 3, 0, 1,
1275                     (GtkAttachOptions) (GTK_FILL),
1276                     (GtkAttachOptions) (0), 0, 0);
1277   au_rb = gtk_radio_button_new_with_label (format_group, ".au");
1278   format_group = gtk_radio_button_group (GTK_RADIO_BUTTON (au_rb));
1279   gtk_widget_show (au_rb);
1280   gtk_table_attach (GTK_TABLE (table1), au_rb, 3, 4, 0, 1,
1281                     (GtkAttachOptions) (GTK_FILL),
1282                     (GtkAttachOptions) (0), 0, 0);
1283  */ 
1284
1285   channels_label = gtk_label_new ("Channels:");
1286   gtk_widget_show (channels_label);
1287   gtk_table_attach (GTK_TABLE (table1), channels_label, 0, 1, 1, 2,
1288                                 (GtkAttachOptions) (GTK_FILL),
1289                                 (GtkAttachOptions) (0), 0, 0);
1290   gtk_misc_set_alignment (GTK_MISC (channels_label), 0, 0.5);
1291
1292   forward_rb = gtk_radio_button_new_with_label (channels_group, "forward  ");
1293   channels_group = gtk_radio_button_group (GTK_RADIO_BUTTON (forward_rb));
1294   gtk_widget_show (forward_rb);
1295   gtk_table_attach (GTK_TABLE (table1), forward_rb, 1, 2, 1, 2,
1296                         (GtkAttachOptions) (GTK_FILL),
1297                         (GtkAttachOptions) (0), 0, 0);
1298
1299   reversed_rb = gtk_radio_button_new_with_label (channels_group, "reversed");
1300   channels_group = gtk_radio_button_group (GTK_RADIO_BUTTON (reversed_rb));
1301   gtk_widget_show (reversed_rb);
1302   gtk_table_attach (GTK_TABLE (table1), reversed_rb, 2, 3, 1, 2,
1303                         (GtkAttachOptions) (GTK_FILL),
1304                         (GtkAttachOptions) (0), 0, 0);
1305
1306   both_rb = gtk_radio_button_new_with_label (channels_group, "both");
1307   channels_group = gtk_radio_button_group (GTK_RADIO_BUTTON (both_rb));
1308   gtk_widget_show (both_rb);
1309   gtk_table_attach (GTK_TABLE (table1), both_rb, 3, 4, 1, 2,
1310                         (GtkAttachOptions) (GTK_FILL),
1311                         (GtkAttachOptions) (0), 0, 0);
1312
1313   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(both_rb), TRUE);
1314
1315   /* if one direction is nok we don't allow saving 
1316   XXX this is not ok since the user can click the refresh button and cause changes
1317   but we can not update this window. So we move all the decision on the time the ok
1318   button is clicked
1319   if (rs->f_saved == FALSE) {
1320         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(reversed_rb), TRUE);
1321         gtk_widget_set_sensitive(forward_rb, FALSE);
1322         gtk_widget_set_sensitive(both_rb, FALSE);
1323   }
1324   else if (rs->r_saved == FALSE) {
1325         gtk_widget_set_sensitive(reversed_rb, FALSE);
1326         gtk_widget_set_sensitive(both_rb, FALSE);
1327   }
1328   */
1329
1330   ok_bt = GTK_FILE_SELECTION(save_voice_as_w)->ok_button;
1331   /*OBJECT_SET_DATA(ok_bt, "wav_rb", wav_rb);
1332   OBJECT_SET_DATA(ok_bt, "au_rb", au_rb);
1333   OBJECT_SET_DATA(ok_bt, "sw_rb", sw_rb);*/
1334   OBJECT_SET_DATA(ok_bt, "forward_rb", forward_rb);
1335   OBJECT_SET_DATA(ok_bt, "reversed_rb", reversed_rb);
1336   OBJECT_SET_DATA(ok_bt, "both_rb", both_rb);
1337   OBJECT_SET_DATA(ok_bt, "info_stat", rs);
1338
1339   /* Connect the cancel_button to destroy the widget */
1340   SIGNAL_CONNECT_OBJECT(GTK_FILE_SELECTION(save_voice_as_w)->cancel_button,
1341                         "clicked", (GtkSignalFunc)gtk_widget_destroy,
1342                         save_voice_as_w);
1343
1344   /* Catch the "key_press_event" signal in the window, so that we can catch
1345      the ESC key being pressed and act as if the "Cancel" button had
1346      been selected. */
1347   dlg_set_cancel(save_voice_as_w, GTK_FILE_SELECTION(save_voice_as_w)->cancel_button);
1348   
1349   gtk_signal_connect(GTK_OBJECT(ok_bt), "clicked",
1350                 GTK_SIGNAL_FUNC(save_voice_as_ok_cb), save_voice_as_w);
1351   
1352   gtk_widget_show(save_voice_as_w);
1353 }
1354
1355 /* all the graphics on the window is done here */
1356 static void add_rtp_notebook(void *pri) 
1357 {
1358   info_stat *rs=pri;
1359
1360   GtkWidget *notebook, *page, *page_r, *label, *label1, *label2, *label3;
1361   GtkWidget *scrolled_window, *scrolled_window_r/*, *frame, *text, *label4, *page_help*/;
1362   GtkWidget *box4, *voice_bt, *refresh_bt, *close_bn;
1363   
1364   gchar *titles[6] =  {"Packet nr.", "Sequence",  "Delay (s)", "Jitter (s)", "Marker", "Status"};
1365   gchar label_forward[150];
1366   gchar label_reverse[150];
1367
1368   g_snprintf(label_forward, 149, 
1369                 "Analysing connection from  %s port %u  to  %s port %u   SSRC = %u\n", 
1370                 rs->source, rs->srcport, rs->destination, rs->dstport, rs->ssrc_forward);
1371   g_snprintf(label_reverse, 149,
1372                 "Analysing connection from  %s port %u  to  %s port %u   SSRC = %u\n", 
1373                 rs->destination, rs->dstport, rs->source, rs->srcport, rs->ssrc_reversed);
1374
1375   gtk_widget_destroy(main_vb);
1376   main_vb = gtk_vbox_new(FALSE, 3);
1377   gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
1378   gtk_container_add(GTK_CONTAINER(rtp_w), main_vb);
1379   gtk_widget_show(main_vb);
1380
1381   /* Start a nootbook for flipping between sets of changes */
1382   notebook = gtk_notebook_new();
1383   gtk_container_add(GTK_CONTAINER(main_vb), notebook);
1384   gtk_object_set_data(GTK_OBJECT(rtp_w), "notebook", notebook);
1385
1386   /* page for forward connection */
1387   page = gtk_vbox_new(FALSE, 5);
1388   gtk_container_set_border_width(GTK_CONTAINER(page), 20);
1389
1390   /* scrolled window */
1391   scrolled_window = gtk_scrolled_window_new(NULL, NULL);
1392   gtk_widget_set_usize(scrolled_window, 600, 200);
1393   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), 
1394                                         GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
1395
1396   /* direction label */
1397   label1 = gtk_label_new(label_forward);
1398   gtk_box_pack_start(GTK_BOX(page), label1, FALSE, FALSE, 0);
1399
1400   /* place for some statistics */
1401   max = gtk_label_new("\n\n");
1402   gtk_box_pack_end(GTK_BOX(page), max, FALSE, FALSE, 5);
1403
1404   /* clist for the information */
1405   clist = gtk_clist_new_with_titles(6, titles);
1406   gtk_widget_show(clist);
1407   gtk_container_add(GTK_CONTAINER(scrolled_window), clist);
1408   gtk_box_pack_start(GTK_BOX(page), scrolled_window, TRUE, TRUE, 0);
1409
1410   /* and the label */
1411   label = gtk_label_new("     Forward Direction     ");
1412   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
1413
1414   /* column width and justification */
1415   gtk_clist_set_column_width(GTK_CLIST(clist), 0, 80);
1416   gtk_clist_set_column_width(GTK_CLIST(clist), 1, 80);
1417   gtk_clist_set_column_width(GTK_CLIST(clist), 2, 80);
1418   gtk_clist_set_column_width(GTK_CLIST(clist), 3, 80);
1419   gtk_clist_set_column_width(GTK_CLIST(clist), 4, 40);
1420   gtk_clist_set_column_justification(GTK_CLIST(clist), 0, GTK_JUSTIFY_CENTER);
1421   gtk_clist_set_column_justification(GTK_CLIST(clist), 1, GTK_JUSTIFY_CENTER);
1422   gtk_clist_set_column_justification(GTK_CLIST(clist), 2, GTK_JUSTIFY_CENTER);
1423   gtk_clist_set_column_justification(GTK_CLIST(clist), 3, GTK_JUSTIFY_CENTER);
1424   gtk_clist_set_column_justification(GTK_CLIST(clist), 4, GTK_JUSTIFY_CENTER);
1425   gtk_clist_set_column_justification(GTK_CLIST(clist), 5, GTK_JUSTIFY_CENTER);
1426
1427   /* same page for reversed connection */
1428   page_r = gtk_vbox_new(FALSE, 5);
1429   gtk_container_set_border_width(GTK_CONTAINER(page_r), 20);
1430   scrolled_window_r = gtk_scrolled_window_new(NULL, NULL);
1431   gtk_widget_set_usize(scrolled_window_r, 600, 200);
1432   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window_r), 
1433                                 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
1434   label3 = gtk_label_new(label_reverse);
1435   gtk_box_pack_start(GTK_BOX(page_r), label3, FALSE, FALSE, 0);
1436   max_r = gtk_label_new("\n\n");
1437   gtk_box_pack_end(GTK_BOX(page_r), max_r, FALSE, FALSE, 5);
1438   clist_r = gtk_clist_new_with_titles(6, titles);
1439   gtk_widget_show(clist_r);
1440   gtk_container_add(GTK_CONTAINER(scrolled_window_r), clist_r);
1441   gtk_box_pack_start(GTK_BOX(page_r), scrolled_window_r, TRUE, TRUE, 0);
1442   label2 = gtk_label_new("     Reversed Direction     ");
1443   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page_r, label2);
1444
1445   gtk_clist_set_column_width(GTK_CLIST(clist_r), 0, 80);
1446   gtk_clist_set_column_width(GTK_CLIST(clist_r), 1, 80);
1447   gtk_clist_set_column_width(GTK_CLIST(clist_r), 2, 80);
1448   gtk_clist_set_column_width(GTK_CLIST(clist_r), 3, 80);
1449   gtk_clist_set_column_width(GTK_CLIST(clist_r), 4, 40);
1450   gtk_clist_set_column_justification(GTK_CLIST(clist_r), 0, GTK_JUSTIFY_CENTER);
1451   gtk_clist_set_column_justification(GTK_CLIST(clist_r), 1, GTK_JUSTIFY_CENTER);
1452   gtk_clist_set_column_justification(GTK_CLIST(clist_r), 2, GTK_JUSTIFY_CENTER);
1453   gtk_clist_set_column_justification(GTK_CLIST(clist_r), 3, GTK_JUSTIFY_CENTER);
1454   gtk_clist_set_column_justification(GTK_CLIST(clist_r), 4, GTK_JUSTIFY_CENTER);
1455   gtk_clist_set_column_justification(GTK_CLIST(clist_r), 5, GTK_JUSTIFY_CENTER);
1456
1457   /* page for help&about or future 
1458   page_help = gtk_hbox_new(FALSE, 5);
1459   label4 = gtk_label_new("     Future    ");
1460   gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page_help, label4);
1461   frame = gtk_frame_new("");
1462   text = gtk_label_new("\n\nMaybe some more statistics: delay and jitter distribution,...");
1463   gtk_label_set_justify(GTK_LABEL(text), GTK_JUSTIFY_LEFT);
1464   gtk_container_add(GTK_CONTAINER(frame), text);
1465   gtk_container_set_border_width(GTK_CONTAINER(frame), 20);
1466   gtk_box_pack_start(GTK_BOX(page_help), frame, TRUE, TRUE, 0);
1467 */
1468   /* show all notebooks */
1469   gtk_widget_show_all(notebook);
1470
1471   /* and the buttons */
1472   box4 = gtk_hbutton_box_new();
1473   gtk_box_pack_start(GTK_BOX(main_vb), box4, FALSE, TRUE, 0);
1474   gtk_container_set_border_width(GTK_CONTAINER(box4), 10);
1475   gtk_button_box_set_layout(GTK_BUTTON_BOX(box4), GTK_BUTTONBOX_SPREAD);
1476   gtk_widget_show(box4);
1477
1478   voice_bt = gtk_button_new_with_label("Save voice data as...");
1479   gtk_container_add(GTK_CONTAINER(box4), voice_bt);
1480   gtk_widget_show(voice_bt);
1481   gtk_signal_connect(GTK_OBJECT(voice_bt), "clicked",
1482                 GTK_SIGNAL_FUNC(save_voice_as_cb), rs);
1483
1484   refresh_bt = gtk_button_new_with_label("Refresh");
1485   gtk_container_add(GTK_CONTAINER(box4), refresh_bt);
1486   gtk_widget_show(refresh_bt);
1487   gtk_signal_connect(GTK_OBJECT(refresh_bt), "clicked",
1488                 GTK_SIGNAL_FUNC(refresh_cb), rs);
1489
1490   close_bn = gtk_button_new_with_label("Close");
1491   gtk_container_add(GTK_CONTAINER(box4), close_bn);
1492   gtk_widget_show(close_bn);
1493   gtk_signal_connect(GTK_OBJECT(close_bn), "clicked",
1494                 GTK_SIGNAL_FUNC(rtp_destroy), GTK_OBJECT(rtp_w));
1495
1496   redissect_packets(&cfile);
1497
1498   draw_stat(rs);
1499 }
1500
1501
1502 /* when we click on the selected row it copies that ssrc value into ssrc_reversed */
1503 static void get_selected_ssrc(GtkWidget *clist_r, gint row, gint column, 
1504                                                 GdkEventButton *event _U_, gpointer data)
1505 {
1506   info_stat *rs=(info_stat *)data;
1507   gchar *text;
1508
1509   gtk_clist_get_text(GTK_CLIST(clist_r), row, column, &text);
1510   /* XXX is this strtoul portable for guint32? */
1511   rs->ssrc_reversed = strtoul(text, (char **)NULL, 10);
1512   return;
1513 }
1514
1515 /* when we click apply button in ssrc reversed dialog */
1516 static void apply_selected_ssrc(GtkWidget *w _U_, gpointer data)
1517 {
1518   info_stat *rs=(info_stat *)data;
1519   add_rtp_notebook(rs);
1520 }
1521
1522 /* this function goes through all the packets that have the same ip and port combination 
1523  * (only inversed) as the forward direction (XXX what if the reversed direction doesn't use 
1524  * the same ports???) and looks for different SSRC values. This can happen if you capture
1525  * two RTP conversations one after another from the same pair of phones (PC's). 
1526  * Both have same IP's and can also have same port numbers, so they (should) differ only 
1527  * in SSRC values. In such case we get a list of ssrc values and we have to choose the right 
1528  * one from the list. If there is only one or none, we do it automatically */ 
1529 static void get_reversed_ssrc(void *prs)
1530 {
1531         info_stat *ri = prs;
1532         GtkWidget *scroll_r, *clist_r, *ok_bt, *label, *label2, *label1, *main_hbnbox;
1533         gchar temp[150];
1534         guint i;
1535
1536         switch(ri->reversed_ip_and_port)
1537         {
1538                 /* in case we haven't found any reversed ssrc */
1539                 /* XXX in this case we could look for the inversed IP only */
1540                 case 0: {
1541                         ri->ssrc_reversed = 0;
1542                         ri->search_ssrc = FALSE;
1543                         add_rtp_notebook(ri);
1544                         return;
1545                 }
1546                 /* in case we found exactly one matching ssrc for reversed connection */ 
1547                 case 1: { 
1548                         ri->ssrc_reversed = ri->ssrc_tmp[0];
1549                         ri->search_ssrc = FALSE;
1550                         add_rtp_notebook(ri);
1551                         return;
1552                 }
1553                 /* there is more then one matching ssrc, so we have to choose between them */
1554                 default: {
1555                         ri->search_ssrc = FALSE;
1556                         /* let's draw the window */
1557                         label = gtk_label_new("Found more SSRC values for the reversed\n"
1558                                                  "connection with following parameters:\n");
1559                         g_snprintf(temp, 149, "Source %s port %u Destination %s port %u", 
1560                                         ri->destination, ri->dstport, ri->source, ri->srcport);
1561                         label2 = gtk_label_new(temp);
1562                         gtk_box_pack_start(GTK_BOX(main_vb), label, FALSE, FALSE, 0);
1563                         gtk_box_pack_start(GTK_BOX(main_vb), label2, FALSE, FALSE, 0);
1564                         scroll_r = gtk_scrolled_window_new(NULL, NULL);
1565                         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_r), 
1566                                                 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1567                         clist_r = gtk_clist_new(1);
1568                         gtk_clist_set_column_width(GTK_CLIST(clist_r), 0, 80);
1569                         gtk_container_add(GTK_CONTAINER(scroll_r), clist_r);
1570                         gtk_box_pack_start(GTK_BOX(main_vb), scroll_r, TRUE, TRUE, 0);
1571                         label1 = gtk_label_new("Select one value and click apply");
1572                         gtk_box_pack_start(GTK_BOX(main_vb), label1, FALSE, FALSE, 0);
1573
1574                         main_hbnbox = gtk_hbutton_box_new();
1575                         gtk_box_pack_start(GTK_BOX(main_vb), main_hbnbox, FALSE, TRUE, 0);
1576                         gtk_container_set_border_width(GTK_CONTAINER(main_hbnbox), 10);
1577                         gtk_button_box_set_layout(GTK_BUTTON_BOX(main_hbnbox), 
1578                                                                 GTK_BUTTONBOX_SPREAD);
1579                         gtk_widget_show(main_hbnbox);
1580
1581                         ok_bt = gtk_button_new_with_label("Apply");
1582                         gtk_container_add(GTK_CONTAINER(main_hbnbox), ok_bt);
1583                         gtk_signal_connect(GTK_OBJECT(clist_r), "select_row", 
1584                                         GTK_SIGNAL_FUNC(get_selected_ssrc), ri);
1585                         gtk_signal_connect(GTK_OBJECT(ok_bt), "clicked", 
1586                                         GTK_SIGNAL_FUNC(apply_selected_ssrc), ri);
1587
1588                         /* add all the ssrc values in the clist */
1589                         /* XXX I'm sure the tmp variable could be avoided here
1590                          * i tried to assign guint32 from ri->ssrc_tmp somehow to gchar **text
1591                          * but gave up. So if you can do this, just go ahead */
1592                         for (i=0; i < ri->reversed_ip_and_port; i++) {
1593                                 gchar *text[1];
1594                                 gchar tmp[20];
1595                                 g_snprintf(tmp, 20, "%u", ri->ssrc_tmp[i]);
1596                                 text[0] = (gchar *)&tmp;
1597                                 gtk_clist_append(GTK_CLIST(clist_r), text);
1598                         }
1599                         
1600                         gtk_clist_select_row(GTK_CLIST(clist_r), 0, 0);
1601
1602                         gtk_widget_show(label);
1603                         gtk_widget_show(label1);
1604                         gtk_widget_show(label2);
1605                         gtk_widget_show(ok_bt);
1606                         gtk_widget_show(clist_r);
1607                         gtk_widget_show(scroll_r);
1608                 }
1609         }
1610 }
1611
1612 /* XXX only handles RTP over IPv4, should add IPv6 support */
1613 /* when the user clicks the RTP dialog button */
1614 static void rtp_analyse_cb(GtkWidget *w _U_, gpointer data _U_) 
1615
1616   info_stat *rs;
1617   gchar filter_text[256];
1618   dfilter_t *sfcode;
1619   capture_file *cf;
1620   epan_dissect_t *edt;
1621   gint err;
1622   gboolean frame_matched;
1623   frame_data *fdata;
1624   GString *error_string;
1625
1626   /* There's already a "Display Options" dialog box; reactivate it. */
1627   if (rtp_w != NULL) {
1628         reactivate_window(rtp_w);
1629         return;
1630   }
1631
1632   /* Try to compile the filter. */
1633   strcpy(filter_text,"rtp && ip");
1634   if (!dfilter_compile(filter_text, &sfcode)) {
1635         simple_dialog(ESD_TYPE_CRIT, NULL, dfilter_error_msg);
1636         return;
1637   }
1638   /* we load the current file into cf variable */
1639   cf = &cfile;
1640   fdata = cf->current_frame;
1641
1642   /* we are on the selected frame now */
1643   if (fdata == NULL)
1644         return; /* if we exit here it's an error */
1645
1646   /* XXX instead of looking for RTP protocol like this, we could do the process_node() staff */
1647   /* dissect the current frame */
1648   wtap_seek_read(cf->wth, fdata->file_off, &cf->pseudo_header, cf->pd, fdata->cap_len, &err);
1649   edt = epan_dissect_new(TRUE, FALSE);
1650   epan_dissect_prime_dfilter(edt, sfcode);
1651   epan_dissect_run(edt, &cf->pseudo_header, cf->pd, fdata, &cf->cinfo);
1652   frame_matched = dfilter_apply_edt(sfcode, edt);
1653
1654   /* if it is not an rtp frame, exit */
1655   frame_matched = dfilter_apply_edt(sfcode, edt);
1656   if (frame_matched != 1) {
1657         epan_dissect_free(edt);
1658         simple_dialog(ESD_TYPE_CRIT, NULL, "You didn't choose a RTP packet!");
1659         return;
1660         }
1661
1662   /* in rs we put all the info */
1663   rs=g_malloc(sizeof(info_stat));       
1664
1665   /* ok, it is a RTP frame, so let's get the ip and port values */
1666   rs->srcport = edt->pi.srcport;
1667   rs->dstport = edt->pi.destport;
1668   strncpy(rs->source, ip_to_str(edt->pi.src.data), 16);  
1669   strncpy(rs->destination, ip_to_str(edt->pi.dst.data), 16);  
1670
1671   /* now we need the SSRC value of the current frame */
1672   rs->ssrc_forward = process_tree(edt->tree);
1673   if (rs->ssrc_forward == 0) {
1674         simple_dialog(ESD_TYPE_CRIT, NULL, "SSRC value couldn't be found!");
1675         return;
1676   }
1677
1678   /* now we have all the information about the forwarding connection
1679    * we need to go through all the packets and search for reversed connection
1680    */
1681   rs->search_ssrc = TRUE;
1682   rs->ssrc_reversed = 0;        
1683   rs->reversed_ip = 0;
1684   rs->reversed_ip_and_port = 0;
1685   rs->ssrc_tmp = NULL;
1686
1687   sprintf(filter_text,"rtp && ip && !icmp && (( ip.src==%s && udp.srcport==%d && ip.dst==%s && udp.dstport==%d ) || ( ip.src==%s && udp.srcport==%d && ip.dst==%s && udp.dstport==%d ))",
1688           ip_to_str(edt->pi.src.data),
1689           edt->pi.srcport,
1690           ip_to_str(edt->pi.dst.data),
1691           edt->pi.destport,
1692           ip_to_str(edt->pi.dst.data),
1693           edt->pi.destport,
1694           ip_to_str(edt->pi.src.data),
1695           edt->pi.srcport
1696           );
1697 /* XXX compiler warning:passing arg 5 of `register_tap_listener' from incompatible pointer type */
1698   error_string = register_tap_listener("rtp", rs, filter_text, rtp_reset, rtp_packet, rtp_draw);
1699   if (error_string != NULL) {
1700         simple_dialog(ESD_TYPE_WARN, NULL, error_string->str);
1701         /* XXX is this enough or do I have to free anything else? */
1702         g_string_free(error_string, TRUE);
1703         g_free(rs);
1704         exit(1);
1705   }
1706
1707   /* let's draw the window */
1708   rtp_w = dlg_window_new("Ethereal: RTP Analyse");
1709   gtk_window_set_position (GTK_WINDOW (rtp_w), GTK_WIN_POS_CENTER);
1710   gtk_signal_connect(GTK_OBJECT(rtp_w), "destroy",
1711         GTK_SIGNAL_FUNC(rtp_destroy_cb), rs);
1712
1713   /* Container for each row of widgets */
1714   main_vb = gtk_vbox_new(FALSE, 3);
1715   gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
1716   gtk_container_add(GTK_CONTAINER(rtp_w), main_vb);
1717   gtk_widget_show(main_vb);
1718
1719   /* file names for storing sound data */
1720   tmpnam(f_tempname);
1721   tmpnam(r_tempname);
1722   rs->f_fp = NULL;
1723   rs->r_fp = NULL;
1724
1725   redissect_packets(cf);
1726
1727   /* so how many reversed connection we have ? */
1728   get_reversed_ssrc(rs);
1729
1730   /* and finally display this window */
1731   gtk_widget_show(rtp_w);
1732 }
1733
1734 static void
1735 rtp_analyse_init(char *dummy _U_)
1736 {
1737         rtp_analyse_cb(NULL, NULL);
1738 }
1739
1740 void
1741 register_tap_listener_gtkrtp(void)
1742 {
1743         register_ethereal_tap("rtp", rtp_analyse_init);
1744 }
1745
1746 void
1747 register_tap_menu_gtkrtp(void)
1748 {
1749         register_tap_menu_item("RTP Analysis...", rtp_analyse_cb);
1750 }
1751
1752
1753 /* here we save it into a file that user specified */
1754 /* XXX what about endians here? could go something wrong? */
1755 static gboolean copy_file(gchar *dest, gint channels, /*gint format,*/ void *data)
1756 {
1757         info_stat *rs=(info_stat *)data;
1758         int to_fd, forw_fd, rev_fd, fread = 0, rread = 0, fwritten, rwritten;
1759         gint16 f_pd;
1760         gint16 r_pd;
1761         gchar pd[1];
1762         guint32 f_write_silence = 0;
1763         guint32 r_write_silence = 0;
1764         progdlg_t *progbar;
1765         guint32 progbar_count, progbar_quantum, progbar_nextstep = 0, count = 0;
1766         gboolean stop_flag = FALSE;
1767
1768         forw_fd = open(f_tempname, O_RDONLY | O_BINARY);
1769         if (forw_fd < 0) 
1770                 return FALSE;
1771         rev_fd = open(r_tempname, O_RDONLY | O_BINARY);
1772         if (rev_fd < 0) {
1773                 close(forw_fd); 
1774                 return FALSE;
1775         }
1776
1777         /* open file for saving */
1778         to_fd = open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
1779         if (to_fd < 0) {
1780                 close(forw_fd);
1781                 close(rev_fd);
1782                 return FALSE;
1783         }
1784
1785         progbar = create_progress_dlg("Saving voice in a file", dest, "Stop", &stop_flag);
1786
1787         /* First we write the .au header. XXX Hope this is endian independant */
1788         /* the magic word 0x2e736e64 == .snd */
1789         *pd = (unsigned char)0x2e; write(to_fd, pd, 1);
1790         *pd = (unsigned char)0x73; write(to_fd, pd, 1);
1791         *pd = (unsigned char)0x6e; write(to_fd, pd, 1);
1792         *pd = (unsigned char)0x64; write(to_fd, pd, 1);
1793         /* header offset == 24 bytes */
1794         *pd = (unsigned char)0x00; write(to_fd, pd, 1);
1795         write(to_fd, pd, 1);
1796         write(to_fd, pd, 1);
1797         *pd = (unsigned char)0x18; write(to_fd, pd, 1);
1798         /* total length, it is permited to set this to 0xffffffff */
1799         *pd = (unsigned char)0xff; write(to_fd, pd, 1); 
1800         write(to_fd, pd, 1); 
1801         write(to_fd, pd, 1); 
1802         write(to_fd, pd, 1);
1803         /* encoding format == 8 bit ulaw */
1804         *pd = (unsigned char)0x00; write(to_fd, pd, 1);
1805         write(to_fd, pd, 1);
1806         write(to_fd, pd, 1);
1807         *pd = (unsigned char)0x01; write(to_fd, pd, 1);
1808         /* sample rate == 8000 Hz */
1809         *pd = (unsigned char)0x00; write(to_fd, pd, 1);
1810         write(to_fd, pd, 1);
1811         *pd = (unsigned char)0x1f; write(to_fd, pd, 1);
1812         *pd = (unsigned char)0x40; write(to_fd, pd, 1);
1813         /* channels == 1 */
1814         *pd = (unsigned char)0x00; write(to_fd, pd, 1);
1815         write(to_fd, pd, 1);
1816         write(to_fd, pd, 1);
1817         *pd = (unsigned char)0x01; write(to_fd, pd, 1);
1818         
1819         switch (channels) {
1820                 /* only forward direction */
1821                 case 1: {
1822                         progbar_count = rs->f_count;
1823                         progbar_quantum = rs->f_count/100;
1824                         while ((fread = read(forw_fd, &f_pd, 2)) > 0) {
1825                                 if(stop_flag) 
1826                                         break;
1827                                 if((count > progbar_nextstep) && (count <= progbar_count)) {
1828                                         update_progress_dlg(progbar, 
1829                                                 (gfloat) count/progbar_count, "Saving");
1830                                         progbar_nextstep = progbar_nextstep + progbar_quantum;
1831                                 }
1832                                 count++;
1833                                 *pd = (unsigned char)linear2ulaw(f_pd);
1834                                 fwritten = write(to_fd, pd, 1);
1835                                 if ((fwritten*2 < fread) || (fwritten < 0) || (fread < 0)) {
1836                                         close(forw_fd);
1837                                         close(rev_fd);
1838                                         close(to_fd);
1839                                         destroy_progress_dlg(progbar);
1840                                         return FALSE;
1841                                 }
1842                         }
1843                         break;
1844                 }
1845                 /* only reversed direction */
1846                 case 2: {
1847                         progbar_count = rs->r_count;
1848                         progbar_quantum = rs->r_count/100;
1849                         while ((rread = read(rev_fd, &r_pd, 2)) > 0) {
1850                                 if(stop_flag) 
1851                                         break;
1852                                 if((count > progbar_nextstep) && (count <= progbar_count)) {
1853                                         update_progress_dlg(progbar, 
1854                                                 (gfloat) count/progbar_count, "Saving");
1855                                         progbar_nextstep = progbar_nextstep + progbar_quantum;
1856                                 }
1857                                 count++;
1858                                 *pd = (unsigned char)linear2ulaw(r_pd);
1859                                 rwritten = write(to_fd, pd, 1);
1860                                 if ((rwritten*2 < rread) || (rwritten < 0) || (rread < 0)) {
1861                                         close(forw_fd);
1862                                         close(rev_fd);
1863                                         close(to_fd);
1864                                         destroy_progress_dlg(progbar);
1865                                         return FALSE;
1866                                 }
1867                         }
1868                         break;
1869                 }
1870                 /* both directions */
1871                 default: {
1872                         (rs->f_count > rs->r_count) ? (progbar_count = rs->f_count) : 
1873                                                                 (progbar_count = rs->r_count);
1874                         progbar_quantum = progbar_count/100;
1875                         /* since conversation in one way can start later than in the other one, 
1876                          * we have to write some silence information for one channel */
1877                         if (rs->f_start_time > rs->r_start_time) {
1878                                 f_write_silence = (rs->f_start_time-rs->r_start_time)*8000;
1879                         }
1880                         else if (rs->f_start_time < rs->r_start_time) {
1881                                 r_write_silence = (rs->r_start_time-rs->f_start_time)*8000;
1882                         }
1883                         for(;;) {
1884                                 if(stop_flag) 
1885                                         break;
1886                                 if((count > progbar_nextstep) && (count <= progbar_count)) {
1887                                         update_progress_dlg(progbar, 
1888                                                 (gfloat) count/progbar_count, "Saving");
1889                                         progbar_nextstep = progbar_nextstep + progbar_quantum;
1890                                 }
1891                                 count++;
1892                                 if(f_write_silence > 0) {
1893                                         rread = read(rev_fd, &r_pd, 2);
1894                                         f_pd = 0;
1895                                         fread = 1;
1896                                         f_write_silence--;
1897                                 }
1898                                 else if(r_write_silence > 0) {
1899                                         fread = read(forw_fd, &f_pd, 2);
1900                                         r_pd = 0;
1901                                         rread = 1;
1902                                         r_write_silence--;
1903                                 }
1904                                 else {
1905                                         fread = read(forw_fd, &f_pd, 2); 
1906                                         rread = read(rev_fd, &r_pd, 2);
1907                                 }
1908                                 if ((rread == 0) && (fread == 0)) 
1909                                         break;
1910                                 *pd = (unsigned char)linear2ulaw( (f_pd + r_pd)/2 );
1911                                 rwritten = write(to_fd, pd, 1);
1912                                 if ((rwritten < 0) || (rread < 0) || (fread < 0)) {
1913                                         close(forw_fd);
1914                                         close(rev_fd);
1915                                         close(to_fd);
1916                                         destroy_progress_dlg(progbar);
1917                                         return FALSE;
1918                                 }
1919                         }
1920                 }
1921         }
1922         destroy_progress_dlg(progbar);
1923         close(forw_fd);
1924         close(rev_fd);
1925         close(to_fd);
1926         return TRUE;
1927
1928 }