replace *a lot* of file related calls by their GLib counterparts. This is necessary...
[obnox/wireshark/wip.git] / gtk / rtp_stream.c
index 2b641e550b1f2c4920970e53ce670712e4ba8021..75b82fc65f1439542d20022239d7b14ffee505fd 100644 (file)
@@ -1,7 +1,7 @@
 /* rtp_stream.c
  * RTP streams summary addition for ethereal
  *
- * $Id: rtp_stream.c,v 1.9 2004/01/31 02:25:46 ulfl Exp $
+ * $Id$
  *
  * Copyright 2003, Alcatel Business Systems
  * By Lars Ruoff <lars.ruoff@gmx.net>
 
 #include "globals.h"
 
-#include "tap.h"
+#include <epan/tap.h>
 #include "register.h"
-#include "packet-rtp.h"
+#include <epan/dissectors/packet-rtp.h>
 
-#include <epan/filesystem.h>
 
+#include "alert_box.h"
 #include "simple_dialog.h"
+#include "file_util.h"
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
 
 #ifdef HAVE_SYS_TYPES_H
 # include <sys/types.h>
 #endif
 
 #include <string.h>
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
+#include <epan/addr_resolv.h>
 
 
 /****************************************************************************/
@@ -61,7 +63,7 @@ static rtpstream_tapinfo_t the_tapinfo_struct =
 
 /****************************************************************************/
 /* GCompareFunc style comparison function for _rtp_stream_info */
-gint rtp_stream_info_cmp(gconstpointer aa, gconstpointer bb)
+static gint rtp_stream_info_cmp(gconstpointer aa, gconstpointer bb)
 {
        const struct _rtp_stream_info* a = aa;
        const struct _rtp_stream_info* b = bb;
@@ -70,9 +72,9 @@ gint rtp_stream_info_cmp(gconstpointer aa, gconstpointer bb)
                return 0;
        if (a==NULL || b==NULL)
                return 1;
-       if ((a->src_addr == b->src_addr)
+       if (ADDRESSES_EQUAL(&(a->src_addr), &(b->src_addr))
                && (a->src_port == b->src_port)
-               && (a->dest_addr == b->dest_addr)
+               && ADDRESSES_EQUAL(&(a->dest_addr), &(b->dest_addr))
                && (a->dest_port == b->dest_port)
                && (a->ssrc == b->ssrc))
                return 0;
@@ -106,9 +108,14 @@ void rtpstream_reset(rtpstream_tapinfo_t *tapinfo)
        return;
 }
 
+static void rtpstream_reset_cb(void *arg)
+{
+       rtpstream_reset(arg);
+}
+
 /****************************************************************************/
 /* redraw the output */
-void rtpstream_draw(rtpstream_tapinfo_t *tapinfo _U_)
+static void rtpstream_draw(void *arg _U_)
 {
 /* XXX: see rtpstream_on_update in rtp_streams_dlg.c for comments
        gtk_signal_emit_by_name(top_level, "signal_rtpstream_update");
@@ -150,12 +157,12 @@ static void rtp_write_header(rtp_stream_info_t *strinfo, FILE *file)
        guint16 padding;       /* 2 padding bytes */
        
        fprintf(file, "#!rtpplay%s %s/%u\n", RTPFILE_VERSION,
-               ip_to_str((guint8*) &strinfo->dest_addr),
+               get_addr_name(&(strinfo->dest_addr)),
                strinfo->dest_port);
 
        start_sec = g_htonl(strinfo->start_sec);
        start_usec = g_htonl(strinfo->start_usec);
-       source = strinfo->src_addr; /* already is in network order */
+       source = *(strinfo->src_addr.data); /* rtpdump only accepts guint32 as source, will be fake for IPv6 */
        port = g_htons(strinfo->src_port);
        padding = 0;
 
@@ -187,18 +194,21 @@ static void rtp_write_sample(rtp_sample_t* sample, FILE* file)
 
 /****************************************************************************/
 /* whenever a RTP packet is seen by the tap listener */
-int rtpstream_packet(rtpstream_tapinfo_t *tapinfo _U_, packet_info *pinfo, epan_dissect_t *edt _U_, struct _rtp_info *rtpinfo _U_)
+static int rtpstream_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *arg2)
 {
+       rtpstream_tapinfo_t *tapinfo = arg;
+       const struct _rtp_info *rtpinfo = arg2;
        rtp_stream_info_t tmp_strinfo;
        rtp_stream_info_t *strinfo = NULL;
        GList* list;
-
        rtp_sample_t sample;
 
+       struct _rtp_conversation_info *p_conv_data = NULL;
+
        /* gather infos on the stream this packet is part of */
-       g_memmove(&(tmp_strinfo.src_addr), pinfo->src.data, 4);
+       COPY_ADDRESS(&(tmp_strinfo.src_addr), &(pinfo->src));
        tmp_strinfo.src_port = pinfo->srcport;
-       g_memmove(&(tmp_strinfo.dest_addr), pinfo->dst.data, 4);
+       COPY_ADDRESS(&(tmp_strinfo.dest_addr), &(pinfo->dst));
        tmp_strinfo.dest_port = pinfo->destport;
        tmp_strinfo.ssrc = rtpinfo->info_sync_src;
        tmp_strinfo.pt = rtpinfo->info_payload_type;
@@ -220,18 +230,62 @@ int rtpstream_packet(rtpstream_tapinfo_t *tapinfo _U_, packet_info *pinfo, epan_
                if (!strinfo) {
                        tmp_strinfo.npackets = 0;
                        tmp_strinfo.first_frame_num = pinfo->fd->num;
-                       tmp_strinfo.start_sec = pinfo->fd->abs_secs;
-                       tmp_strinfo.start_usec = pinfo->fd->abs_usecs;
+                       tmp_strinfo.start_sec = pinfo->fd->abs_ts.secs;
+                       tmp_strinfo.start_usec = pinfo->fd->abs_ts.nsecs/1000;
+                       tmp_strinfo.start_rel_sec = pinfo->fd->rel_ts.secs;
+                       tmp_strinfo.start_rel_usec = pinfo->fd->rel_ts.nsecs/1000;
                        tmp_strinfo.tag_vlan_error = 0;
                        tmp_strinfo.tag_diffserv_error = 0;
                        tmp_strinfo.vlan_id = 0;
+                       tmp_strinfo.problem = FALSE;
+
+                       /* reset RTP stats */
+                       tmp_strinfo.rtp_stats.first_packet = TRUE;
+                       tmp_strinfo.rtp_stats.max_delta = 0;
+                       tmp_strinfo.rtp_stats.max_jitter = 0;
+                       tmp_strinfo.rtp_stats.mean_jitter = 0;
+                       tmp_strinfo.rtp_stats.delta = 0;
+                       tmp_strinfo.rtp_stats.diff = 0;
+                       tmp_strinfo.rtp_stats.jitter = 0;
+                       tmp_strinfo.rtp_stats.bandwidth = 0;
+                       tmp_strinfo.rtp_stats.total_bytes = 0;
+                       tmp_strinfo.rtp_stats.bw_start_index = 0;
+                       tmp_strinfo.rtp_stats.bw_index = 0;
+                       tmp_strinfo.rtp_stats.timestamp = 0;
+                       tmp_strinfo.rtp_stats.max_nr = 0;
+                       tmp_strinfo.rtp_stats.total_nr = 0;
+                       tmp_strinfo.rtp_stats.sequence = 0;
+                       tmp_strinfo.rtp_stats.start_seq_nr = 0;
+                       tmp_strinfo.rtp_stats.stop_seq_nr = 0;
+                       tmp_strinfo.rtp_stats.cycles = 0;
+                       tmp_strinfo.rtp_stats.under = FALSE;
+                       tmp_strinfo.rtp_stats.start_time = 0;
+                       tmp_strinfo.rtp_stats.time = 0;
+                       tmp_strinfo.rtp_stats.reg_pt = PT_UNDEFINED;
+
+            /* Get the Setup frame number who set this RTP stream */
+            p_conv_data = p_get_proto_data(pinfo->fd, proto_get_id_by_filter_name("rtp"));
+            if (p_conv_data)
+                               tmp_strinfo.setup_frame_number = p_conv_data->frame_number;
+            else
+                tmp_strinfo.setup_frame_number = 0xFFFFFFFF;
+
                        strinfo = g_malloc(sizeof(rtp_stream_info_t));
                        *strinfo = tmp_strinfo;  /* memberwise copy of struct */
                        tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
                }
 
+               /* get RTP stats for the packet */
+               rtp_packet_analyse(&(strinfo->rtp_stats), pinfo, rtpinfo);
+               if (strinfo->rtp_stats.flags & STAT_FLAG_WRONG_TIMESTAMP
+                       || strinfo->rtp_stats.flags & STAT_FLAG_WRONG_SEQ)
+                       strinfo->problem = TRUE;
+
+
                /* increment the packets counter for this stream */
                ++(strinfo->npackets);
+               strinfo->stop_rel_sec = pinfo->fd->rel_ts.secs;
+               strinfo->stop_rel_usec = pinfo->fd->rel_ts.nsecs/1000;
 
                /* increment the packets counter of all streams */
                ++(tapinfo->npackets);
@@ -240,19 +294,22 @@ int rtpstream_packet(rtpstream_tapinfo_t *tapinfo _U_, packet_info *pinfo, epan_
        }
        else if (tapinfo->mode == TAP_SAVE) {
                if (rtp_stream_info_cmp(&tmp_strinfo, tapinfo->filter_stream_fwd)==0) {
+                       /* XXX - what if rtpinfo->info_all_data_present is
+                          FALSE, so that we don't *have* all the data? */
                        sample.header.rec_time = 
-                               (pinfo->fd->abs_usecs + 1000000 - tapinfo->filter_stream_fwd->start_usec)/1000
-                               + (pinfo->fd->abs_secs - tapinfo->filter_stream_fwd->start_sec - 1)*1000;
+                               (pinfo->fd->abs_ts.nsecs/1000 + 1000000 - tapinfo->filter_stream_fwd->start_usec)/1000
+                               + (pinfo->fd->abs_ts.secs - tapinfo->filter_stream_fwd->start_sec - 1)*1000;
                        sample.header.frame_length = rtpinfo->info_data_len;
                        sample.frame = rtpinfo->info_data;
                        rtp_write_sample(&sample, tapinfo->save_file);
                }
        }
        else if (tapinfo->mode == TAP_MARK) {
+
                if (rtp_stream_info_cmp(&tmp_strinfo, tapinfo->filter_stream_fwd)==0
                        || rtp_stream_info_cmp(&tmp_strinfo, tapinfo->filter_stream_rev)==0)
                {
-                       mark_frame(&cfile, pinfo->fd);
+                       cf_mark_frame(&cfile, pinfo->fd);
                }
        }
 
@@ -268,7 +325,7 @@ void rtpstream_scan(void)
                register_tap_listener_rtp_stream();
 
        the_tapinfo_struct.mode = TAP_ANALYSE;
-       retap_packets(&cfile);
+       cf_retap_packets(&cfile, FALSE);
 
        if (!was_registered)
                remove_tap_listener_rtp_stream();
@@ -281,17 +338,15 @@ gboolean rtpstream_save(rtp_stream_info_t* stream, const gchar *filename)
 {
        gboolean was_registered = the_tapinfo_struct.is_registered;
        /* open file for saving */
-       the_tapinfo_struct.save_file = fopen(filename, "wb");
+       the_tapinfo_struct.save_file = eth_fopen(filename, "wb");
        if (the_tapinfo_struct.save_file==NULL) {
-               simple_dialog(ESD_TYPE_ERROR, NULL,
-                   file_open_error_message(errno, TRUE), filename);
+               open_failure_alert_box(filename, errno, TRUE);
                return FALSE;
        }
 
        rtp_write_header(stream, the_tapinfo_struct.save_file);
        if (ferror(the_tapinfo_struct.save_file)) {
-               simple_dialog(ESD_TYPE_ERROR, NULL,
-                   file_write_error_message(errno), filename);
+               write_failure_alert_box(filename, errno);
                fclose(the_tapinfo_struct.save_file);
                return FALSE;
        }
@@ -301,22 +356,20 @@ gboolean rtpstream_save(rtp_stream_info_t* stream, const gchar *filename)
 
        the_tapinfo_struct.mode = TAP_SAVE;
        the_tapinfo_struct.filter_stream_fwd = stream;
-       retap_packets(&cfile);
+       cf_retap_packets(&cfile, FALSE);
        the_tapinfo_struct.mode = TAP_ANALYSE;
 
        if (!was_registered)
                remove_tap_listener_rtp_stream();
 
        if (ferror(the_tapinfo_struct.save_file)) {
-               simple_dialog(ESD_TYPE_ERROR, NULL,
-                   file_write_error_message(errno), filename);
+               write_failure_alert_box(filename, errno);
                fclose(the_tapinfo_struct.save_file);
                return FALSE;
        }
 
        if (fclose(the_tapinfo_struct.save_file) == EOF) {
-               simple_dialog(ESD_TYPE_ERROR, NULL,
-                   file_write_error_message(errno), filename);
+               write_failure_alert_box(filename, errno);
                return FALSE;
        }
        return TRUE;
@@ -334,7 +387,7 @@ void rtpstream_mark(rtp_stream_info_t* stream_fwd, rtp_stream_info_t* stream_rev
        the_tapinfo_struct.mode = TAP_MARK;
        the_tapinfo_struct.filter_stream_fwd = stream_fwd;
        the_tapinfo_struct.filter_stream_rev = stream_rev;
-       retap_packets(&cfile);
+       cf_retap_packets(&cfile, FALSE);
        the_tapinfo_struct.mode = TAP_ANALYSE;
 
        if (!was_registered)
@@ -353,14 +406,6 @@ const rtpstream_tapinfo_t* rtpstream_get_info(void)
 /* TAP INTERFACE */
 /****************************************************************************/
 
-/****************************************************************************/
-static void
-rtpstream_init_tap(char *dummy _U_)
-{
-       /* XXX: never called? */
-}
-
-
 /* XXX just copied from gtk/rpc_stat.c */
 void protect_thread_critical_region(void);
 void unprotect_thread_critical_region(void);
@@ -386,14 +431,13 @@ register_tap_listener_rtp_stream(void)
        GString *error_string;
 
        if (!the_tapinfo_struct.is_registered) {
-               register_ethereal_tap("rtp", rtpstream_init_tap);
-
                error_string = register_tap_listener("rtp", &the_tapinfo_struct,
-                       NULL,
-                       (void*)rtpstream_reset, (void*)rtpstream_packet, (void*)rtpstream_draw);
+                       NULL, rtpstream_reset_cb, rtpstream_packet,
+                       rtpstream_draw);
 
                if (error_string != NULL) {
-                       simple_dialog(ESD_TYPE_WARN | ESD_TYPE_MODAL, NULL, error_string->str);
+                       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+                                     error_string->str);
                        g_string_free(error_string, TRUE);
                        exit(1);
                }