Fix "tap-rtp-common.c:440: warning: ‘current_diff’ may be used uninitialized...
[metze/wireshark/wip.git] / tap-rtp-common.c
1 /* tap-rtp-common.c
2  * RTP stream handler functions used by tshark and wireshark
3  *
4  * $Id$
5  *
6  * Copyright 2008, Ericsson AB
7  * By Balint Reczey <balint.reczey@ericsson.com>
8  *
9  * most functions are copied from gtk/rtp_stream.c and gtk/rtp_analisys.c
10  * Copyright 2003, Alcatel Business Systems
11  * By Lars Ruoff <lars.ruoff@gmx.net>
12  *
13  * Wireshark - Network traffic analyzer
14  * By Gerald Combs <gerald@wireshark.org>
15  * Copyright 1998 Gerald Combs
16  *
17  * This program is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU General Public License
19  * as published by the Free Software Foundation; either version 2
20  * of the License, or (at your option) any later version.
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, write to the Free Software
29  * Foundation,  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
30  */
31
32 #ifdef HAVE_CONFIG_H
33 # include "config.h"
34 #endif
35
36 #include <math.h>
37 #include "globals.h"
38
39 #include <epan/tap.h>
40 #include "register.h"
41 #include <string.h>
42 #include <epan/rtp_pt.h>
43 #include <epan/addr_resolv.h>
44 #include <epan/dissectors/packet-rtp.h>
45 #include "gtk/rtp_stream.h"
46 #include "tap-rtp-common.h"
47
48
49
50 /****************************************************************************/
51 /* GCompareFunc style comparison function for _rtp_stream_info */
52 gint rtp_stream_info_cmp(gconstpointer aa, gconstpointer bb)
53 {
54         const struct _rtp_stream_info* a = aa;
55         const struct _rtp_stream_info* b = bb;
56
57         if (a==b)
58                 return 0;
59         if (a==NULL || b==NULL)
60                 return 1;
61         if (ADDRESSES_EQUAL(&(a->src_addr), &(b->src_addr))
62                 && (a->src_port == b->src_port)
63                 && ADDRESSES_EQUAL(&(a->dest_addr), &(b->dest_addr))
64                 && (a->dest_port == b->dest_port)
65                 && (a->ssrc == b->ssrc))
66                 return 0;
67         else
68                 return 1;
69 }
70
71
72 /****************************************************************************/
73 /* when there is a [re]reading of packet's */
74 void rtpstream_reset(rtpstream_tapinfo_t *tapinfo)
75 {
76         GList* list;
77
78         if (tapinfo->mode == TAP_ANALYSE) {
79                 /* free the data items first */
80                 list = g_list_first(tapinfo->strinfo_list);
81                 while (list)
82                 {
83                         g_free(list->data);
84                         list = g_list_next(list);
85                 }
86                 g_list_free(tapinfo->strinfo_list);
87                 tapinfo->strinfo_list = NULL;
88                 tapinfo->nstreams = 0;
89                 tapinfo->npackets = 0;
90         }
91
92         ++(tapinfo->launch_count);
93
94         return;
95 }
96
97 void rtpstream_reset_cb(void *arg)
98 {
99         rtpstream_reset(arg);
100 }
101
102 /*
103 * rtpdump file format
104 *
105 * The file starts with the tool to be used for playing this file,
106 * the multicast/unicast receive address and the port.
107 *
108 * #!rtpplay1.0 224.2.0.1/3456\n
109 *
110 * This is followed by one binary header (RD_hdr_t) and one RD_packet_t
111 * structure for each received packet.  All fields are in network byte
112 * order.  We don't need the source IP address since we can do mapping
113 * based on SSRC.  This saves (a little) space, avoids non-IPv4
114 * problems and privacy/security concerns. The header is followed by
115 * the RTP/RTCP header and (optionally) the actual payload.
116 */
117
118 #define RTPFILE_VERSION "1.0"
119
120 /*
121 * Write a header to the current output file.
122 * The header consists of an identifying string, followed
123 * by a binary structure.
124 */
125 void rtp_write_header(rtp_stream_info_t *strinfo, FILE *file)
126 {
127         guint32 start_sec;     /* start of recording (GMT) (seconds) */
128         guint32 start_usec;    /* start of recording (GMT) (microseconds)*/
129         guint32 source;        /* network source (multicast address) */
130         size_t sourcelen;
131         guint16 port;          /* UDP port */
132         guint16 padding;       /* 2 padding bytes */
133         
134         fprintf(file, "#!rtpplay%s %s/%u\n", RTPFILE_VERSION,
135                 get_addr_name(&(strinfo->dest_addr)),
136                 strinfo->dest_port);
137
138         start_sec = g_htonl(strinfo->start_sec);
139         start_usec = g_htonl(strinfo->start_usec);
140         /* rtpdump only accepts guint32 as source, will be fake for IPv6 */
141         memset(&source, 0, sizeof source);
142         sourcelen = strinfo->src_addr.len;
143         if (sourcelen > sizeof source)
144                 sourcelen = sizeof source;
145         memcpy(&source, strinfo->src_addr.data, sourcelen);
146         port = g_htons(strinfo->src_port);
147         padding = 0;
148
149         if (fwrite(&start_sec, 4, 1, file) == 0)
150                 return;
151         if (fwrite(&start_usec, 4, 1, file) == 0)
152                 return;
153         if (fwrite(&source, 4, 1, file) == 0)
154                 return;
155         if (fwrite(&port, 2, 1, file) == 0)
156                 return;
157         if (fwrite(&padding, 2, 1, file) == 0)
158                 return;
159 }
160
161 /* utility function for writing a sample to file in rtpdump -F dump format (.rtp)*/
162 void rtp_write_sample(rtp_sample_t* sample, FILE* file)
163 {
164         guint16 length;    /* length of packet, including this header (may
165                              be smaller than plen if not whole packet recorded) */
166         guint16 plen;      /* actual header+payload length for RTP, 0 for RTCP */
167         guint32 offset;    /* milliseconds since the start of recording */
168
169         length = g_htons(sample->header.frame_length + 8);
170         plen = g_htons(sample->header.frame_length);
171         offset = g_htonl(sample->header.rec_time);
172
173         if (fwrite(&length, 2, 1, file) == 0)
174                 return;
175         if (fwrite(&plen, 2, 1, file) == 0)
176                 return;
177         if (fwrite(&offset, 4, 1, file) == 0)
178                 return;
179         if (fwrite(sample->frame, sample->header.frame_length, 1, file) == 0)
180                 return;
181 }
182
183
184 /****************************************************************************/
185 /* whenever a RTP packet is seen by the tap listener */
186 int rtpstream_packet(void *arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *arg2)
187 {
188         rtpstream_tapinfo_t *tapinfo = arg;
189         const struct _rtp_info *rtpinfo = arg2;
190         rtp_stream_info_t tmp_strinfo;
191         rtp_stream_info_t *strinfo = NULL;
192         GList* list;
193         rtp_sample_t sample;
194
195         struct _rtp_conversation_info *p_conv_data = NULL;
196
197         /* gather infos on the stream this packet is part of */
198         COPY_ADDRESS(&(tmp_strinfo.src_addr), &(pinfo->src));
199         tmp_strinfo.src_port = pinfo->srcport;
200         COPY_ADDRESS(&(tmp_strinfo.dest_addr), &(pinfo->dst));
201         tmp_strinfo.dest_port = pinfo->destport;
202         tmp_strinfo.ssrc = rtpinfo->info_sync_src;
203         tmp_strinfo.pt = rtpinfo->info_payload_type;
204         tmp_strinfo.info_payload_type_str = rtpinfo->info_payload_type_str;
205
206         if (tapinfo->mode == TAP_ANALYSE) {
207                 /* check whether we already have a stream with these parameters in the list */
208                 list = g_list_first(tapinfo->strinfo_list);
209                 while (list)
210                 {
211                         if (rtp_stream_info_cmp(&tmp_strinfo, (rtp_stream_info_t*)(list->data))==0)
212                         {
213                                 strinfo = (rtp_stream_info_t*)(list->data);  /*found!*/
214                                 break;
215                         }
216                         list = g_list_next(list);
217                 }
218
219                 /* not in the list? then create a new entry */
220                 if (!strinfo) {
221                         tmp_strinfo.npackets = 0;
222                         tmp_strinfo.first_frame_num = pinfo->fd->num;
223                         tmp_strinfo.start_sec = (guint32) pinfo->fd->abs_ts.secs;
224                         tmp_strinfo.start_usec = pinfo->fd->abs_ts.nsecs/1000;
225                         tmp_strinfo.start_rel_sec = (guint32) pinfo->fd->rel_ts.secs;
226                         tmp_strinfo.start_rel_usec = pinfo->fd->rel_ts.nsecs/1000;
227                         tmp_strinfo.tag_vlan_error = 0;
228                         tmp_strinfo.tag_diffserv_error = 0;
229                         tmp_strinfo.vlan_id = 0;
230                         tmp_strinfo.problem = FALSE;
231
232                         /* reset RTP stats */
233                         tmp_strinfo.rtp_stats.first_packet = TRUE;
234                         tmp_strinfo.rtp_stats.max_delta = 0;
235                         tmp_strinfo.rtp_stats.max_jitter = 0;
236                         tmp_strinfo.rtp_stats.mean_jitter = 0;
237                         tmp_strinfo.rtp_stats.delta = 0;
238                         tmp_strinfo.rtp_stats.diff = 0;
239                         tmp_strinfo.rtp_stats.jitter = 0;
240                         tmp_strinfo.rtp_stats.bandwidth = 0;
241                         tmp_strinfo.rtp_stats.total_bytes = 0;
242                         tmp_strinfo.rtp_stats.bw_start_index = 0;
243                         tmp_strinfo.rtp_stats.bw_index = 0;
244                         tmp_strinfo.rtp_stats.timestamp = 0;
245                         tmp_strinfo.rtp_stats.max_nr = 0;
246                         tmp_strinfo.rtp_stats.total_nr = 0;
247                         tmp_strinfo.rtp_stats.sequence = 0;
248                         tmp_strinfo.rtp_stats.start_seq_nr = 0;
249                         tmp_strinfo.rtp_stats.stop_seq_nr = 0;
250                         tmp_strinfo.rtp_stats.cycles = 0;
251                         tmp_strinfo.rtp_stats.under = FALSE;
252                         tmp_strinfo.rtp_stats.start_time = 0;
253                         tmp_strinfo.rtp_stats.time = 0;
254                         tmp_strinfo.rtp_stats.reg_pt = PT_UNDEFINED;
255
256             /* Get the Setup frame number who set this RTP stream */
257             p_conv_data = p_get_proto_data(pinfo->fd, proto_get_id_by_filter_name("rtp"));
258             if (p_conv_data)
259                                 tmp_strinfo.setup_frame_number = p_conv_data->frame_number;
260             else
261                 tmp_strinfo.setup_frame_number = 0xFFFFFFFF;
262
263                         strinfo = g_malloc(sizeof(rtp_stream_info_t));
264                         *strinfo = tmp_strinfo;  /* memberwise copy of struct */
265                         tapinfo->strinfo_list = g_list_append(tapinfo->strinfo_list, strinfo);
266                 }
267
268                 /* get RTP stats for the packet */
269                 rtp_packet_analyse(&(strinfo->rtp_stats), pinfo, rtpinfo);
270                 if (strinfo->rtp_stats.flags & STAT_FLAG_WRONG_TIMESTAMP
271                         || strinfo->rtp_stats.flags & STAT_FLAG_WRONG_SEQ)
272                         strinfo->problem = TRUE;
273
274
275                 /* increment the packets counter for this stream */
276                 ++(strinfo->npackets);
277                 strinfo->stop_rel_sec = (guint32) pinfo->fd->rel_ts.secs;
278                 strinfo->stop_rel_usec = pinfo->fd->rel_ts.nsecs/1000;
279
280                 /* increment the packets counter of all streams */
281                 ++(tapinfo->npackets);
282                 
283                 return 1;  /* refresh output */
284         }
285         else if (tapinfo->mode == TAP_SAVE) {
286                 if (rtp_stream_info_cmp(&tmp_strinfo, tapinfo->filter_stream_fwd)==0) {
287                         /* XXX - what if rtpinfo->info_all_data_present is
288                            FALSE, so that we don't *have* all the data? */
289                         sample.header.rec_time = 
290                                 (pinfo->fd->abs_ts.nsecs/1000 + 1000000 - tapinfo->filter_stream_fwd->start_usec)/1000
291                                 + (guint32) (pinfo->fd->abs_ts.secs - tapinfo->filter_stream_fwd->start_sec - 1)*1000;
292                         sample.header.frame_length = rtpinfo->info_data_len;
293                         sample.frame = rtpinfo->info_data;
294                         rtp_write_sample(&sample, tapinfo->save_file);
295                 }
296         }
297         else if (tapinfo->mode == TAP_MARK) {
298
299                 if (rtp_stream_info_cmp(&tmp_strinfo, tapinfo->filter_stream_fwd)==0
300                         || rtp_stream_info_cmp(&tmp_strinfo, tapinfo->filter_stream_rev)==0)
301                 {
302                         cf_mark_frame(&cfile, pinfo->fd);
303                 }
304         }
305
306         return 0;
307 }
308
309
310 typedef struct _key_value {
311   guint32  key;
312   guint32  value;
313 } key_value;
314
315
316 /* RTP sampling clock rates for fixed payload types as defined in
317  http://www.iana.org/assignments/rtp-parameters */
318 static const key_value clock_map[] = {
319         {PT_PCMU,       8000},
320         {PT_1016,       8000},
321         {PT_G721,       8000},
322         {PT_GSM,        8000},
323         {PT_G723,       8000},
324         {PT_DVI4_8000,  8000},
325         {PT_DVI4_16000, 16000},
326         {PT_LPC,        8000},
327         {PT_PCMA,       8000},
328         {PT_G722,       8000},
329         {PT_L16_STEREO, 44100},
330         {PT_L16_MONO,   44100},
331         {PT_QCELP,      8000},
332         {PT_CN,         8000},
333         {PT_MPA,        90000},
334         {PT_G728,       8000},
335         {PT_G728,       8000},
336         {PT_DVI4_11025, 11025},
337         {PT_DVI4_22050, 22050},
338         {PT_G729,       8000},
339         {PT_CN_OLD,     8000},
340         {PT_CELB,       90000},
341         {PT_JPEG,       90000},
342         {PT_NV,         90000},
343         {PT_H261,       90000},
344         {PT_MPV,        90000},
345         {PT_MP2T,       90000},
346         {PT_H263,       90000},
347 };
348
349 #define NUM_CLOCK_VALUES        (sizeof clock_map / sizeof clock_map[0])
350
351 static guint32
352 get_clock_rate(guint32 key)
353 {
354         size_t i;
355
356         for (i = 0; i < NUM_CLOCK_VALUES; i++) {
357                 if (clock_map[i].key == key)
358                         return clock_map[i].value;
359         }
360         return 0;
361 }
362
363 typedef struct _mimetype_and_clock {
364         const gchar   *pt_mime_name_str;
365         guint32 value;
366 } mimetype_and_clock;
367 /*      RTP sampling clock rates for
368         "In addition to the RTP payload formats (encodings) listed in the RTP
369         Payload Types table, there are additional payload formats that do not
370         have static RTP payload types assigned but instead use dynamic payload
371         type number assignment.  Each payload format is named by a registered
372         MIME subtype"
373         http://www.iana.org/assignments/rtp-parameters.
374
375         NOTE: Please keep the mimetypes in case insensitive alphabetical order.
376 */
377 static const mimetype_and_clock mimetype_and_clock_map[] = {
378         {"AMR",         8000},                  /* [RFC4867][RFC3267] */
379         {"AMR-WB",      16000},                 /* [RFC4867][RFC3267] */
380         {"BMPEG",       90000},                 /* [RFC2343],[RFC3555] */
381         {"BT656",       90000},                 /* [RFC2431],[RFC3555] */
382         {"DV",          90000},                 /* [RFC3189] */
383         {"EVRC",        8000},                  /* [RFC3558] */
384         {"EVRC0",       8000},                  /* [RFC4788] */
385         {"EVRC1",       8000},                  /* [RFC4788] */
386         {"EVRCB",       8000},                  /* [RFC4788] */
387         {"EVRCB0",      8000},                  /* [RFC4788] */
388         {"EVRCB1",      8000},                  /* [RFC4788] */
389         {"EVRCWB",      16000},                 /* [RFC5188] */
390         {"EVRCWB0",     16000},                 /* [RFC5188] */
391         {"EVRCWB1",     16000},                 /* [RFC5188] */
392         {"G7221",       16000},                 /* [RFC3047] */
393         {"G726-16",     8000},                  /* [RFC3551][RFC4856] */
394         {"G726-24",     8000},                  /* [RFC3551][RFC4856] */
395         {"G726-32",     8000},                  /* [RFC3551][RFC4856] */
396         {"G726-40",     8000},                  /* [RFC3551][RFC4856] */
397         {"G729D",       8000},                  /* [RFC3551][RFC4856] */
398         {"G729E",       8000},                  /* [RFC3551][RFC4856] */
399         {"GSM-EFR",     8000},                  /* [RFC3551] */
400         {"H263-1998",   90000},         /* [RFC2429],[RFC3555] */
401         {"H263-2000",   90000},         /* [RFC2429],[RFC3555] */
402         {"H264",        90000},         /* [RFC3984] */
403         {"MP1S",        90000},                 /* [RFC2250],[RFC3555] */
404         {"MP2P",        90000},                 /* [RFC2250],[RFC3555] */
405         {"MP4V-ES",     90000},                 /* [RFC3016] */
406         {"mpa-robust",  90000},         /* [RFC3119] */
407         {"pointer",     90000},                 /* [RFC2862] */
408         {"raw",         90000},                 /* [RFC4175] */
409         {"red",         1000},                  /* [RFC4102] */
410         {"SMV",         8000},                  /* [RFC3558] */
411         {"SMV0",        8000},                  /* [RFC3558] */
412         {"t140",        1000},                  /* [RFC4103] */
413         {"telephone-event", 8000},  /* [RFC4733] */
414 };
415
416 #define NUM_DYN_CLOCK_VALUES    (sizeof mimetype_and_clock_map / sizeof mimetype_and_clock_map[0])
417
418 static guint32
419 get_dyn_pt_clock_rate(gchar *payload_type_str)
420 {
421         int i;
422         
423         /* Search for matching mimetype in reverse order to avoid false matches
424          * when pt_mime_name_str is the prefix of payload_type_str */
425         for (i = NUM_DYN_CLOCK_VALUES - 1; i > -1 ; i--) {
426                 if (g_ascii_strncasecmp(mimetype_and_clock_map[i].pt_mime_name_str,payload_type_str,(strlen(mimetype_and_clock_map[i].pt_mime_name_str))) == 0)
427                         return mimetype_and_clock_map[i].value;
428         }
429
430         return 0;
431 }
432
433 /****************************************************************************/
434 int rtp_packet_analyse(tap_rtp_stat_t *statinfo,
435                               packet_info *pinfo,
436                               const struct _rtp_info *rtpinfo)
437 {
438         double current_time;
439         double current_jitter;
440         double current_diff = 0;
441         double nominaltime;
442         double arrivaltime;             /* Time relative to start_time */
443         double expected_time;
444         double absskew;
445         guint32 clock_rate;
446
447         /* Store the current time */
448         current_time = nstime_to_msec(&pinfo->fd->rel_ts);
449
450         /*  Is this the first packet we got in this direction? */
451         if (statinfo->first_packet) {
452                 statinfo->start_seq_nr = rtpinfo->info_seq_num;
453                 statinfo->stop_seq_nr = rtpinfo->info_seq_num;
454                 statinfo->seq_num = rtpinfo->info_seq_num;
455                 statinfo->start_time = current_time;
456                 statinfo->timestamp = rtpinfo->info_timestamp;
457                 statinfo->first_timestamp = rtpinfo->info_timestamp;
458                 statinfo->time = current_time;
459                 statinfo->pt = rtpinfo->info_payload_type;
460                 statinfo->reg_pt = rtpinfo->info_payload_type;
461                 statinfo->bw_history[statinfo->bw_index].bytes = rtpinfo->info_data_len + 28;
462                 statinfo->bw_history[statinfo->bw_index].time = current_time;
463                 statinfo->bw_index++;
464                 statinfo->total_bytes += rtpinfo->info_data_len + 28;
465                 statinfo->bandwidth = (double)(statinfo->total_bytes*8)/1000;
466                 /* Not needed ? initialised to zero? */
467                 statinfo->delta = 0;
468                 statinfo->jitter = 0;
469                 statinfo->diff = 0;
470
471                 statinfo->total_nr++;
472                 statinfo->flags |= STAT_FLAG_FIRST;
473                 if (rtpinfo->info_marker_set) {
474                         statinfo->flags |= STAT_FLAG_MARKER;
475                 }
476                 statinfo->first_packet = FALSE;
477                 return 0;
478         }
479
480         /* Reset flags */
481         statinfo->flags = 0;
482
483         /* check payload type */
484         if (rtpinfo->info_payload_type == PT_CN
485                 || rtpinfo->info_payload_type == PT_CN_OLD)
486                 statinfo->flags |= STAT_FLAG_PT_CN;
487         if (statinfo->pt == PT_CN
488                 || statinfo->pt == PT_CN_OLD)
489                 statinfo->flags |= STAT_FLAG_FOLLOW_PT_CN;
490         if (rtpinfo->info_payload_type != statinfo->pt)
491                 statinfo->flags |= STAT_FLAG_PT_CHANGE;
492         statinfo->pt = rtpinfo->info_payload_type;
493
494         /*
495          * Return 0 for unknown payload types
496          * Ignore jitter calculation for clockrate = 0
497          */
498         if (statinfo->pt < 96 ){
499                 clock_rate = get_clock_rate(statinfo->pt);
500         }else{ /* dynamic PT */
501                 if ( rtpinfo->info_payload_type_str != NULL )
502                         clock_rate = get_dyn_pt_clock_rate(rtpinfo-> info_payload_type_str);
503                 else
504                         clock_rate = 0;
505         }
506
507                 /* Handle wraparound ? */
508         arrivaltime = current_time - statinfo->start_time;
509
510         if (statinfo->first_timestamp > rtpinfo->info_timestamp){
511                 /* Handle wraparound */
512                 nominaltime = (double)(rtpinfo->info_timestamp + 0xffffffff - statinfo->first_timestamp + 1);
513         }else{
514                 nominaltime = (double)(rtpinfo->info_timestamp - statinfo->first_timestamp);
515         }
516
517         /* Can only analyze defined sampling rates */
518     if (clock_rate != 0) { 
519                 statinfo->clock_rate = clock_rate;
520                 /* Convert from sampling clock to ms */
521                 nominaltime = nominaltime /(clock_rate/1000);
522
523                 /* Calculate the current jitter(in ms) */
524                 if (!statinfo->first_packet) {
525                         expected_time = statinfo->time + (nominaltime - statinfo->lastnominaltime);
526                         current_diff = fabs(current_time - expected_time);
527                         current_jitter = (15 * statinfo->jitter + current_diff) / 16;
528
529                         statinfo->delta = current_time-(statinfo->time);
530                         statinfo->jitter = current_jitter;
531                         statinfo->diff = current_diff;
532                 }
533                 statinfo->lastnominaltime = nominaltime;
534                 /* Calculate skew, i.e. absolute jitter that also catches clock drift
535                  * Skew is positive if TS (nominal) is too fast
536                  */
537                 statinfo->skew    = nominaltime - arrivaltime;
538                 absskew = fabs(statinfo->skew);
539                 if(absskew > fabs(statinfo->max_skew)){
540                         statinfo->max_skew = statinfo->skew;
541                 }
542                 /* Gather data for calculation of average, minimum and maximum framerate based on timestamp */
543 #if 0
544                 if (numPackets > 0 && (!hardPayloadType || !alternatePayloadType)) { 
545                         /* Skip first packet and possibly alternate payload type packets */
546                         double dt;
547                         dt     = nominaltime - statinfo->lastnominaltime;
548                         sumdt += 1.0 * dt;
549                         numdt += (dt != 0 ? 1 : 0);
550                         mindt  = (dt < mindt ? dt : mindt);
551                         maxdt  = (dt > maxdt ? dt : maxdt);
552                 }
553 #endif
554                 /* Gather data for calculation of skew least square */
555                 statinfo->sumt   += 1.0 * current_time;
556                 statinfo->sumTS  += 1.0 * nominaltime;
557                 statinfo->sumt2  += 1.0 * current_time * current_time;
558                 statinfo->sumtTS += 1.0 * current_time * nominaltime;
559         }
560
561         /* calculate the BW in Kbps adding the IP+UDP header to the RTP -> 20bytes(IP)+8bytes(UDP) = 28bytes */
562         statinfo->bw_history[statinfo->bw_index].bytes = rtpinfo->info_data_len + 28;
563         statinfo->bw_history[statinfo->bw_index].time = current_time;
564
565         /* check if there are more than 1sec in the history buffer to calculate BW in bps. If so, remove those for the calculation */
566         while ((statinfo->bw_history[statinfo->bw_start_index].time+1000/* ms */)<current_time){
567                 statinfo->total_bytes -= statinfo->bw_history[statinfo->bw_start_index].bytes;
568                 statinfo->bw_start_index++;
569                 if (statinfo->bw_start_index == BUFF_BW) statinfo->bw_start_index=0;
570         };
571         statinfo->total_bytes += rtpinfo->info_data_len + 28;
572         statinfo->bandwidth = (double)(statinfo->total_bytes*8)/1000;
573         statinfo->bw_index++;
574         if (statinfo->bw_index == BUFF_BW) statinfo->bw_index = 0;
575
576
577         /*  is this the first packet we got in this direction? */
578         if (statinfo->first_packet) {
579                 statinfo->start_seq_nr = rtpinfo->info_seq_num;
580                 statinfo->start_time = current_time;
581                 statinfo->delta = 0;
582                 statinfo->jitter = 0;
583                 statinfo->diff = 0;
584                 statinfo->flags |= STAT_FLAG_FIRST;
585                 statinfo->first_packet = FALSE;
586         }
587         /* is it a packet with the mark bit set? */
588         if (rtpinfo->info_marker_set) {
589                 statinfo->delta_timestamp = rtpinfo->info_timestamp - statinfo->timestamp;
590                 if (rtpinfo->info_timestamp > statinfo->timestamp){
591                         statinfo->flags |= STAT_FLAG_MARKER;
592                 }
593                 else{
594                         statinfo->flags |= STAT_FLAG_WRONG_TIMESTAMP;
595                 }
596         }
597         /* is it a regular packet? */
598         if (!(statinfo->flags & STAT_FLAG_FIRST)
599                 && !(statinfo->flags & STAT_FLAG_MARKER)
600                 && !(statinfo->flags & STAT_FLAG_PT_CN)
601                 && !(statinfo->flags & STAT_FLAG_WRONG_TIMESTAMP)
602                 && !(statinfo->flags & STAT_FLAG_FOLLOW_PT_CN)) {
603                 /* include it in maximum delta calculation */
604                 if (statinfo->delta > statinfo->max_delta) {
605                         statinfo->max_delta = statinfo->delta;
606                         statinfo->max_nr = pinfo->fd->num;
607                 }
608                 if (clock_rate != 0) { 
609                         /* maximum and mean jitter calculation */
610                         if (statinfo->jitter > statinfo->max_jitter) {
611                                 statinfo->max_jitter = statinfo->jitter;
612                         }
613                         statinfo->mean_jitter = (statinfo->mean_jitter*statinfo->total_nr + current_diff) / (statinfo->total_nr+1);
614                 }
615         }
616         /* regular payload change? (CN ignored) */
617         if (!(statinfo->flags & STAT_FLAG_FIRST)
618                 && !(statinfo->flags & STAT_FLAG_PT_CN)) {
619                 if ((statinfo->pt != statinfo->reg_pt)
620                         && (statinfo->reg_pt != PT_UNDEFINED)) {
621                         statinfo->flags |= STAT_FLAG_REG_PT_CHANGE;
622                 }
623         }
624
625         /* set regular payload*/
626         if (!(statinfo->flags & STAT_FLAG_PT_CN)) {
627                 statinfo->reg_pt = statinfo->pt;
628         }
629
630
631         /* When calculating expected rtp packets the seq number can wrap around
632         * so we have to count the number of cycles
633         * Variable cycles counts the wraps around in forwarding connection and
634         * under is flag that indicates where we are
635         *
636         * XXX how to determine number of cycles with all possible lost, late
637         * and duplicated packets without any doubt? It seems to me, that
638         * because of all possible combination of late, duplicated or lost
639         * packets, this can only be more or less good approximation
640         *
641         * There are some combinations (rare but theoretically possible),
642         * where below code won't work correctly - statistic may be wrong then.
643         */
644
645         /* so if the current sequence number is less than the start one
646         * we assume, that there is another cycle running */
647         if ((rtpinfo->info_seq_num < statinfo->start_seq_nr) && (statinfo->under == FALSE)){
648                 statinfo->cycles++;
649                 statinfo->under = TRUE;
650         }
651         /* what if the start seq nr was 0? Then the above condition will never
652         * be true, so we add another condition. XXX The problem would arise
653         * if one of the packets with seq nr 0 or 65535 would be lost or late */
654         else if ((rtpinfo->info_seq_num == 0) && (statinfo->stop_seq_nr == 65535) &&
655                 (statinfo->under == FALSE)){
656                 statinfo->cycles++;
657                 statinfo->under = TRUE;
658         }
659         /* the whole round is over, so reset the flag */
660         else if ((rtpinfo->info_seq_num > statinfo->start_seq_nr) && (statinfo->under != FALSE)) {
661                 statinfo->under = FALSE;
662         }
663
664         /* Since it is difficult to count lost, duplicate or late packets separately,
665         * we would like to know at least how many times the sequence number was not ok */
666
667         /* if the current seq number equals the last one or if we are here for
668         * the first time, then it is ok, we just store the current one as the last one */
669         if ( (statinfo->seq_num+1 == rtpinfo->info_seq_num) || (statinfo->flags & STAT_FLAG_FIRST) )
670                 statinfo->seq_num = rtpinfo->info_seq_num;
671         /* if the first one is 65535. XXX same problem as above: if seq 65535 or 0 is lost... */
672         else if ( (statinfo->seq_num == 65535) && (rtpinfo->info_seq_num == 0) )
673                 statinfo->seq_num = rtpinfo->info_seq_num;
674         /* lost packets */
675         else if (statinfo->seq_num+1 < rtpinfo->info_seq_num) {
676                 statinfo->seq_num = rtpinfo->info_seq_num;
677                 statinfo->sequence++;
678                 statinfo->flags |= STAT_FLAG_WRONG_SEQ;
679         }
680         /* late or duplicated */
681         else if (statinfo->seq_num+1 > rtpinfo->info_seq_num) {
682                 statinfo->sequence++;
683                 statinfo->flags |= STAT_FLAG_WRONG_SEQ;
684         }
685         statinfo->time = current_time;
686         statinfo->timestamp = rtpinfo->info_timestamp;
687         statinfo->stop_seq_nr = rtpinfo->info_seq_num;
688         statinfo->total_nr++;
689
690         return 0;
691 }
692
693