root/rat/trunk/rtcp_pckt.c @ 2055

Revision 2055, 30.1 KB (checked in by ucaccsp, 15 years ago)

Fix muting of individual participants.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * Filename: rtcp_pckt.c
3 * Author:   Paul Stewart
4 * Modified: Vicky Hardman + Colin Perkins
5 * Purpose:  RTCP protocol routines
6 *
7 * $Revision$
8 * $Date$
9 *
10 * Copyright (c) 1995-98 University College London
11 * All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, is permitted, for non-commercial use only, provided
15 * that the following conditions are met:
16 * 1. Redistributions of source code must retain the above copyright
17 *    notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 *    notice, this list of conditions and the following disclaimer in the
20 *    documentation and/or other materials provided with the distribution.
21 * 3. All advertising materials mentioning features or use of this software
22 *    must display the following acknowledgement:
23 *      This product includes software developed by the Computer Science
24 *      Department at University College London
25 * 4. Neither the name of the University nor of the Department may be used
26 *    to endorse or promote products derived from this software without
27 *    specific prior written permission.
28 * Use of this software for commercial purposes is explicitly forbidden
29 * unless prior written permission is obtained from the authors.
30 *
31 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
32 * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
35 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
40 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 * SUCH DAMAGE.
42 *
43 * Copyright (c) 1994 Paul Stewart
44 * All rights reserved.
45 *
46 * Permission is hereby granted, without written agreement and without license
47 * or royalty fees, to use, copy, modify, and distribute this software and
48 * its documentation for any purpose, provided that the above copyright
49 * notice appears in all copies of this software.
50 */
51
52#include "config_unix.h"
53#include "config_win32.h"
54#include "assert.h"
55#include "debug.h"
56#include "memory.h"
57#include "version.h"
58#include "net_udp.h"
59#include "net.h"
60#include "rtcp_pckt.h"
61#include "rtcp_db.h"
62#include "session.h"
63#include "ui.h"
64#include "receive.h"
65#include "transmit.h"
66#include "timers.h"
67
68#define SECS_BETWEEN_1900_1970 2208988800u
69#define RTP_SSRC_EXPIRE        70u
70
71/*
72 * Sets the ntp 64 bit values, one 32 bit quantity at a time.
73 */
74static void 
75rtcp_ntp_format(u_int32 * sec, u_int32 * frac)
76{
77        struct timeval  tv;
78        u_int32 usec;
79
80        gettimeofday(&tv, 0);
81        *sec = tv.tv_sec + SECS_BETWEEN_1900_1970;
82        usec = tv.tv_usec;
83        *frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6);
84}
85
86u_int32
87ntp_time32(void)
88{
89        struct timeval  tv;
90        u_int32 sec, usec, frac;
91
92        gettimeofday(&tv, 0);
93        sec  = tv.tv_sec + SECS_BETWEEN_1900_1970;
94        usec = tv.tv_usec;
95        frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6);
96        return (sec & 0xffff) << 16 | frac >> 16;
97}
98
99int
100rtcp_check_rtcp_pkt(u_int8 *packet, int len)
101{
102        /* Validity check for a compound RTCP packet. This function returns */
103        /* TRUE if the packet is okay, FALSE if the validity check fails.   */
104        /*                                                                  */
105        /* The following checks can be applied to RTCP packets [RFC1889]:   */
106        /* o RTP version field must equal 2.                                */
107        /* o The payload type field of the first RTCP packet in a compound  */
108        /*   packet must be equal to SR or RR.                              */
109        /* o The padding bit (P) should be zero for the first packet of a   */
110        /*   compound RTCP packet because only the last should possibly     */
111        /*   need padding.                                                  */
112        /* o The length fields of the individual RTCP packets must total to */
113        /*   the overall length of the compound RTCP packet as received.    */
114        /*   This is a fairly strong check.                                 */
115
116        rtcp_t  *pkt  = (rtcp_t *) packet;
117        rtcp_t  *end  = (rtcp_t *) (((char *) pkt) + len);
118        rtcp_t  *r    = pkt;
119        int      l    = 0;
120        int      last = 0;
121
122        /* All RTCP packets must be compound packets (RFC1889, section 6.1) */
123        if (((ntohs(pkt->common.length) + 1) * 4) == len) {
124                debug_msg("Bogus RTCP packet: not a compound packet\n");
125                return FALSE;
126        }
127
128        /* Check the RTCP version, payload type and padding of the first in  */
129        /* the compund RTCP packet...                                        */
130        if (pkt->common.type != 2) {
131                debug_msg("Bogus RTCP packet: version number != 2 in the first sub-packet\n");
132                return FALSE;
133        }
134        if (pkt->common.p != 0) {
135                debug_msg("Bogus RTCP packet: padding bit is set, and this is the first packet in the compound\n");
136                return FALSE;
137        }
138        if ((pkt->common.pt != RTCP_SR) && (pkt->common.pt != RTCP_RR)) {
139                debug_msg("Bogus RTCP packet: compund packet does not start with SR or RR\n");
140                return FALSE;
141        }
142
143        /* Check all following parts of the compund RTCP packet. The RTP version */
144        /* number must be 2, and the padding bit must be zero on all apart from  */
145        /* the last packet.                                                      */
146        do {
147                if (r->common.type != 2) {
148                        debug_msg("Bogus RTCP packet: version number != 2\n");
149                        return FALSE;
150                }
151                if (last == 1) {
152                        debug_msg("Bogus RTCP packet: padding bit was set before the last packet in the compound\n");
153                        return FALSE;
154                }
155                if (r->common.p == 1) last = 1;
156                l += (ntohs(r->common.length) + 1) * 4;
157                r  = (rtcp_t *) (((u_int32 *) r) + ntohs(r->common.length) + 1);
158        } while (r < end);
159
160        /* Check that the length of the packets matches the length of the UDP */
161        /* packet in which they were received...                              */
162        if ((r != end) || (l != len))  {
163                debug_msg("Bogus RTCP packet: length of RTCP packet does not match length of UDP packet\n");
164                return FALSE;
165        }
166
167        return TRUE;
168}
169
170/*
171 * Fill out an SDES item.  I assume here that the item is a NULL terminated
172 * string.
173 */
174static int 
175rtcp_add_sdes_item(u_int8 *buf, int type, char *val)
176{
177        rtcp_sdes_item_t *shdr = (rtcp_sdes_item_t *) buf;
178        int             namelen;
179
180        if (val == NULL) {
181                debug_msg("Cannot format SDES item. type=%d val=%xp\n", type, val);
182                return 0;
183        }
184        shdr->type = type;
185        namelen = strlen(val);
186        shdr->length = namelen;
187        strcpy(shdr->data, val);
188        return namelen + 2;
189}
190
191/*
192 * Fill out a complete SDES packet.  This finds all set values in the
193 * database and compiles them into a complete SDES packet to be sent out.
194 */
195static u_int8 *
196rtcp_packet_fmt_sdes(session_struct *sp, u_int8 * ptr)
197{
198        rtcp_common_t  *hdr = (rtcp_common_t *) ptr;
199        int             i, len;
200
201        /* Format the SDES header... */
202        hdr->type  = 2;
203        hdr->p     = 0;
204        hdr->count = 1;
205        hdr->pt    = RTCP_SDES;
206        *((u_int32 *) ptr + 1) = htonl(sp->db->myssrc);
207        len = 8;
208
209        /* From draft-ietf-avt-profile-new-00:                             */
210        /* "Applications may use any of the SDES items described in the    */
211        /* RTP specification. While CNAME information is sent every        */
212        /* reporting interval, other items should be sent only every third */
213        /* reporting interval, with NAME sent seven out of eight times     */
214        /* within that slot and the remaining SDES items cyclically taking */
215        /* up the eighth slot, as defined in Section 6.2.2 of the RTP      */
216        /* specification. In other words, NAME is sent in RTCP packets 1,  */
217        /* 4, 7, 10, 13, 16, 19, while, say, EMAIL is used in RTCP packet  */
218        /* 22."                                                            */
219        len += rtcp_add_sdes_item(&ptr[len], RTCP_SDES_CNAME, sp->db->my_dbe->sentry->cname);
220        sp->db->sdes_pri_count++;
221        if ((sp->db->sdes_pri_count % 3) == 0) {
222                sp->db->sdes_sec_count++;
223                if ((sp->db->sdes_sec_count % 8) == 0) {
224                        sp->db->sdes_ter_count++;
225                        switch (sp->db->sdes_ter_count % 4) {
226                        case 0 : if (sp->db->my_dbe->sentry->email != NULL) {
227                                        len += rtcp_add_sdes_item(&ptr[len], RTCP_SDES_EMAIL, sp->db->my_dbe->sentry->email);
228                                        break;
229                                 }
230                        case 1 : if (sp->db->my_dbe->sentry->phone != NULL) {
231                                        len += rtcp_add_sdes_item(&ptr[len], RTCP_SDES_PHONE, sp->db->my_dbe->sentry->phone);
232                                        break;
233                                 }
234                        case 2 : if (sp->db->my_dbe->sentry->loc != NULL) {
235                                        len += rtcp_add_sdes_item(&ptr[len], RTCP_SDES_LOC, sp->db->my_dbe->sentry->loc);
236                                        break;
237                                 }
238                        case 3 : len += rtcp_add_sdes_item(&ptr[len], RTCP_SDES_TOOL, RAT_VERSION);
239                        }
240                } else {
241                        if (sp->db->my_dbe->sentry->name != NULL) {
242                                len += rtcp_add_sdes_item(&ptr[len], RTCP_SDES_NAME, sp->db->my_dbe->sentry->name);
243                        }
244                }
245        }
246        hdr->length = htons((u_int16)(len / 4));
247        for (i = len; i < ((int)(len / 4) + 1) * 4; i++) {
248                ptr[i] = 0;
249        }
250        return ptr + 4 * ((int)(len / 4) + 1);
251}
252
253/*
254 * Create a "BYE" packet.
255 */
256static u_int8 *
257rtcp_packet_fmt_bye(u_int8 *ptr, u_int32 ssrc, rtcp_dbentry *ssrc_db)
258{
259        rtcp_t       *pkt = (rtcp_t *) ptr;
260        rtcp_dbentry *entry;
261        u_short       count;
262
263        pkt->common.type   = 2;
264        pkt->common.p      = 0;
265        pkt->common.pt     = RTCP_BYE;
266        pkt->r.bye.src[0]  = htonl(ssrc);
267
268        count = 1;
269        for (entry = ssrc_db; entry != NULL; entry = entry->next) {
270                pkt->r.bye.src[count++] = htonl(entry->ssrc);
271        }
272        pkt->common.count  = count;
273        pkt->common.length = htons(count);
274
275        return ptr + 4 + (count * 4);
276}
277
278/*
279 * Format a sender report packet, from the information available in the
280 * database.
281 */
282static u_int8 *
283rtcp_packet_fmt_sr(session_struct *sp, u_int8 * ptr)
284{
285        rtcp_common_t  *hdr = (rtcp_common_t *) ptr;
286        u_int32         sec;
287        u_int32         frac;
288        hdr->type  = 2;
289        hdr->p     = 0;
290        hdr->count = 0;
291        hdr->pt    = RTCP_SR;
292        *((u_int32 *) ptr + 1) = htonl(sp->db->myssrc);
293        rtcp_ntp_format(&sec, &frac);
294        sp->db->map_ntp_time = (sec & 0xffff) << 16 | frac >> 16;
295        *((u_int32 *) ptr + 2) = htonl(sec);
296        *((u_int32 *) ptr + 3) = htonl(frac);
297
298        sp->db->map_rtp_time = get_time(sp->device_clock);
299        *((u_int32 *) ptr + 4) = htonl(sp->db->map_rtp_time);
300        *((u_int32 *) ptr + 5) = htonl(sp->db->pkt_count);
301        *((u_int32 *) ptr + 6) = htonl(sp->db->byte_count);
302        return ptr + 28;
303}
304
305/*
306 * Create a recipient report header.
307 */
308static u_int8 *
309rtcp_packet_fmt_rrhdr(session_struct *sp, u_int8 * ptr)
310{
311        rtcp_common_t  *hdr = (rtcp_common_t *) ptr;
312        u_int32         sec;
313        u_int32         frac;
314
315        /* Update local clock map */
316        rtcp_ntp_format(&sec, &frac);
317        sp->db->map_ntp_time = (sec & 0xffff) << 16 | frac >> 16;
318        sp->db->map_rtp_time = get_time(sp->device_clock);
319
320        hdr->type  = 2;
321        hdr->p     = 0;
322        hdr->count = 0;
323        hdr->pt    = RTCP_RR;
324        *((u_int32 *) ptr + 1) = htonl(sp->db->myssrc);
325        return ptr + 8;
326}
327
328/*
329 * Format a recipient report item, given the database item that this should
330 * refer to.
331 */
332static u_int8 *
333rtcp_packet_fmt_addrr(session_struct *sp, u_int8 * ptr, rtcp_dbentry * dbe)
334{
335        rtcp_rr_t      *rptr = (rtcp_rr_t *) ptr;
336        u_int32         ext_max, expected, expi, reci;
337        int32           losti;
338
339        ext_max = dbe->cycles + dbe->lastseqno;
340        expected = ext_max - dbe->firstseqno + 1;
341        dbe->lost_tot = expected - dbe->pckts_recv;
342
343        if (dbe->lost_tot < 0) dbe->lost_tot = 0;
344
345        expi = expected - dbe->expected_prior;
346        dbe->expected_prior = expected;
347        reci = dbe->pckts_recv - dbe->received_prior;
348        dbe->received_prior = dbe->pckts_recv;
349        losti = expi - reci;
350
351        if (expi == 0 || losti <= 0) {
352                dbe->lost_frac = 0;
353        } else {
354                dbe->lost_frac = (losti << 8) / expi;
355        }
356
357        if ((dbe->ui_last_update - get_time(dbe->clock)) >= (unsigned)get_freq(sp->device_clock)) {
358                double jit;
359                ui_update_duration(sp, dbe->sentry->cname, dbe->units_per_packet * 20);
360                ui_update_loss(sp, sp->db->my_dbe->sentry->cname, dbe->sentry->cname, (dbe->lost_frac * 100) >> 8);
361                jit = ceil(dbe->jitter * 1000/get_freq(dbe->clock));
362                ui_update_reception(sp, dbe->sentry->cname, dbe->pckts_recv, dbe->lost_tot, dbe->misordered, dbe->duplicates, (u_int32)jit, dbe->jit_TOGed);
363                ui_update_stats(sp, dbe);
364                dbe->ui_last_update = get_time(dbe->clock);
365                debug_msg("Updating\n");
366                if (playout_buffer_exists(sp->playout_buf_list, dbe)) {
367                        ui_info_activate(sp, dbe);
368                } else {
369                        ui_info_deactivate(sp, dbe);
370                }
371        }
372
373        rptr->ssrc     = htonl(dbe->ssrc);
374        rptr->loss     = htonl(dbe->lost_frac << 24 | (dbe->lost_tot & 0xffffff));
375        rptr->last_seq = htons((u_int16)(dbe->cycles + dbe->lastseqno));
376        rptr->jitter   = htonl((u_long) dbe->jitter);
377
378        rptr->lsr      = htonl(dbe->last_sr);
379        rptr->dlsr     = htonl(ntp_time32() - dbe->last_sr_rx);
380        return ptr + 24;
381}
382
383static u_int8 *
384rtcp_packet_fmt_srrr(session_struct *sp, u_int8 *ptr)
385{
386        u_int8         *packet  = ptr;
387        rtcp_common_t  *hdr     = (rtcp_common_t *) ptr;
388        rtcp_dbentry   *sptr    = sp->db->ssrc_db;
389        rtcp_dbentry   *sptmp   = NULL;
390        u_int32         now     = get_time(sp->device_clock);
391        u_int32         expiry  = get_freq(sp->device_clock) * RTP_SSRC_EXPIRE;
392        u_short         packlen = 0;
393        u_short         offset  = 0;
394
395        sp->db->senders = 0;
396        if (sp->db->sending) {
397                ptr = rtcp_packet_fmt_sr(sp, ptr);
398                sp->db->senders++;
399        } else {
400                ptr = rtcp_packet_fmt_rrhdr(sp, ptr);
401        }
402        while (sptr) {
403                sptmp = sptr->next;     /* We may free things below */
404                if (now - sptr->last_active > expiry) {
405                        rtcp_delete_dbentry(sp, sptr->ssrc);
406                } else {
407                        if (sptr->is_sender) {
408                                sp->db->senders++;
409                                sptr->is_sender = 0;    /* Reset this every report time */
410                                ptr = rtcp_packet_fmt_addrr(sp, ptr, sptr);
411                                hdr->count++;
412                                packlen = ptr - packet;
413                                hdr->length = htons((u_int16)((packlen - offset) / 4 - 1));
414                                if (packlen + 84 > MAX_PACKLEN) {
415                                        /* Too many sources sent data, and the result doesn't fit into a */
416                                        /* single SR/RR packet. We just ignore the excess here. Oh well. */
417                                        break;
418                                }
419                        }
420                }
421                sptr = sptmp;
422        }
423        packlen = ptr - (u_int8 *) packet;
424        hdr->length = htons((u_int16)((packlen - offset) / 4 - 1));
425        return ptr;
426}
427
428static void
429rtcp_forward(rtcp_t *pckt, session_struct *sp1, session_struct *sp2)
430{
431        u_int32         packet[MAX_PACKLEN / 4];
432        u_int8         *ptr     = (u_int8 *) packet;
433        int             packlen = 0;
434        /* XXX why are these ints */
435        u_int32         now     = get_time(sp2->device_clock);
436
437        if (sp1 == NULL || sp1->mode != TRANSCODER || sp2->mode != TRANSCODER)
438                return;
439
440        ptr = rtcp_packet_fmt_srrr(sp2, ptr);
441        memcpy(ptr, pckt, (ntohs(pckt->common.length)+1)*4);
442        ptr += (ntohs(pckt->common.length)+1)*4;
443        packlen = ptr - (u_int8 *) packet;
444        net_write(sp1->rtcp_socket, (u_int8 *)packet, packlen, PACKET_RTCP);
445        sp2->db->last_rpt = now;
446}
447
448
449/*
450 *  Decode an RTCP packet.
451 *
452 *  We must be careful not to decode loopback packets! This is relatively easy: all RTCP packets MUST start with
453 *  either an SR or RR sub-packet. We check the SSRC of that sub-packet, and if it's our SSRC then throw out the
454 *  packet. [csp]
455 */
456void 
457rtcp_decode_rtcp_pkt(session_struct *sp, session_struct *sp2, u_int8 *packet, int len, u_int32 cur_time, u_int32 real_time)
458{
459        rtcp_t                  *pkt = (rtcp_t *) packet;
460        rtcp_dbentry            *dbe, *other_source;
461        rtcp_sdes_item_t        *sdes;
462        u_int32                 ssrc;
463        u_int32                 *alignptr;
464        int                     i, lenstr;
465        rtcp_user_rr            *rr, *tmp_rr;
466        u_int32                 sec, frac;
467
468        len /= 4;
469        while (len > 0) {
470                len -= ntohs(pkt->common.length) + 1;
471                if (len < 0 || pkt->common.length == 0) {
472                        debug_msg("Ignoring RTCP packet with weird format...\n");
473                        return;
474                }
475                switch (pkt->common.pt) {
476                case RTCP_SR:
477                        ssrc = ntohl(pkt->r.sr.ssrc);
478                        if (ssrc == sp->db->myssrc && sp->filter_loopback) {
479                                /* Loopback packet, discard it... */
480                                return;
481                        }
482                        dbe = rtcp_getornew_dbentry(sp, ssrc, cur_time);
483
484                        /* Take note of mapping to use in synchronisation */
485                        dbe->mapping_valid = TRUE;
486                        dbe->last_ntp_sec  = ntohl(pkt->r.sr.ntp_sec);
487                        dbe->last_ntp_frac = ntohl(pkt->r.sr.ntp_frac);
488                        dbe->last_rtp_ts   = ntohl(pkt->r.sr.rtp_ts);
489
490                        /* Update local clock map, need it for the sync [dm] */
491                        rtcp_ntp_format(&sec, &frac);
492                        sp->db->map_ntp_time = (sec & 0xffff) << 16 | frac >> 16;
493                        sp->db->map_rtp_time = get_time(sp->device_clock);
494
495                        dbe->last_active = cur_time;
496                        dbe->last_sr     = ((dbe->last_ntp_sec & 0xffff) << 16) | (((dbe->last_ntp_frac & 0xffff0000) >> 16) & 0xffffffff);
497                        dbe->last_sr_rx  = real_time;
498                        debug_msg("%x %x %x\n", dbe->last_sr, dbe->last_ntp_sec, dbe->last_ntp_frac);
499
500                        /* Store the reception statistics for that user... */
501                        /* Clear the old RR list... */
502                        rr = dbe->rr;
503                        while (rr != NULL) {
504                                tmp_rr = rr->next;
505                                xfree(rr);
506                                rr = tmp_rr;
507                        }
508                        dbe->rr = NULL;
509                        /* Fill in the new RR list... */
510                        for (i = 0; i < pkt->common.count; i++) {
511                                rr = (rtcp_user_rr *) xmalloc(sizeof(rtcp_user_rr));
512                                rr->next          = dbe->rr;
513                                rr->ssrc          = ntohl(pkt->r.sr.rr[i].ssrc);
514                                rr->fraction_lost = (u_int8) (ntohl(pkt->r.sr.rr[i].loss) >> 24);
515                                rr->pckts_lost    = ntohl(pkt->r.sr.rr[i].loss) & 0x00ffffff;
516                                rr->ext_seq_num   = ntohl(pkt->r.sr.rr[i].last_seq);
517                                rr->jitter        = ntohl(pkt->r.sr.rr[i].jitter);
518                                rr->lsr           = ntohl(pkt->r.sr.rr[i].lsr);
519                                rr->dlsr          = ntohl(pkt->r.sr.rr[i].dlsr);
520                                dbe->rr      = rr;
521                                other_source = rtcp_getornew_dbentry(sp, rr->ssrc, cur_time);
522                                if (dbe->sentry->cname != NULL) {
523                                        ui_update_loss(sp, dbe->sentry->cname, other_source->sentry->cname, (int) ((rr->fraction_lost / 2.56)+0.5));
524                                }
525                                /* is it reporting on my traffic? */
526                                if ((rr->ssrc == sp->db->myssrc) && (dbe->sentry->cname != NULL)) {
527                                        /* Need to store stats in ssrc's db */
528                                        dbe->loss_from_me = rr->fraction_lost;
529                                        dbe->last_rr_for_me = cur_time;
530                                        ui_update_loss(sp, dbe->sentry->cname, sp->db->my_dbe->sentry->cname, (int) ((rr->fraction_lost / 2.56)+0.5));
531                                        /* Work out the round-trip-time... */
532                                        debug_msg("rtt %x %f\n", ntohl(pkt->r.sr.ssrc), ((double) (real_time - rr->lsr - rr->dlsr)) / 65536.0);
533                                }
534                        }
535                        break;
536                case RTCP_RR:
537                        ssrc = ntohl(pkt->r.sr.ssrc);
538                        if (ssrc == sp->db->myssrc && sp->filter_loopback) {
539                                /* Loopback packet, discard it... */
540                                return;
541                        }
542                        dbe = rtcp_getornew_dbentry(sp, ntohl(pkt->r.rr.ssrc), cur_time);
543                        dbe->last_active = cur_time;
544
545                        /* Store the reception statistics for that user... */
546                        /* Clear the old RR list... */
547                        rr = dbe->rr;
548                        while (rr != NULL) {
549                                tmp_rr = rr->next;
550                                xfree(rr);
551                                rr = tmp_rr;
552                        }
553                        dbe->rr = NULL;
554                        /* Fill in the new RR list... */
555                        for (i = 0; i < pkt->common.count; i++) {
556                                rr = (rtcp_user_rr *) xmalloc(sizeof(rtcp_user_rr));
557                                rr->next          = dbe->rr;
558                                rr->ssrc          = ntohl(pkt->r.rr.rr[i].ssrc);
559                                rr->fraction_lost = (u_int8) (ntohl(pkt->r.rr.rr[i].loss) >> 24);
560                                rr->pckts_lost    = ntohl(pkt->r.rr.rr[i].loss) & 0x00ffffff;
561                                rr->ext_seq_num   = ntohl(pkt->r.rr.rr[i].last_seq);
562                                rr->jitter        = ntohl(pkt->r.rr.rr[i].jitter);
563                                rr->lsr           = ntohl(pkt->r.rr.rr[i].lsr);
564                                rr->dlsr          = ntohl(pkt->r.rr.rr[i].dlsr);
565                                dbe->rr = rr;
566                                other_source =  rtcp_getornew_dbentry(sp, rr->ssrc, cur_time);
567                                if (dbe->sentry->cname != NULL) {
568                                        ui_update_loss(sp, dbe->sentry->cname, other_source->sentry->cname, (int) ((rr->fraction_lost / 2.56)+0.5));
569                                }
570                                /* is it reporting on my traffic? */
571                                if ((rr->ssrc == sp->db->myssrc) && (dbe->sentry->cname != NULL)) {
572                                        /* Need to store stats in ssrc's db not r.rr.ssrc's */
573                                        dbe->loss_from_me = rr->fraction_lost;
574                                        dbe->last_rr_for_me = cur_time;
575                                        ui_update_loss(sp, dbe->sentry->cname, sp->db->my_dbe->sentry->cname, (int) ((rr->fraction_lost / 2.56)+0.5));
576                                        /* Work out the round-trip-time... */
577                                        debug_msg("rtt %x %f\n", ntohl(pkt->r.rr.ssrc), ((double) (real_time - rr->lsr - rr->dlsr)) / 65536.0);
578                                }
579                        }
580
581                        break;
582                case RTCP_BYE:
583                        rtcp_forward(pkt, sp2, sp);
584                        for (i = 0; i < pkt->common.count; i++) {
585                                rtcp_delete_dbentry(sp, ntohl(pkt->r.bye.src[i]));
586                        }
587                        break;
588                case RTCP_SDES:
589                        rtcp_forward(pkt, sp2, sp);
590                        alignptr = (u_int32 *) pkt->r.sdes.s;
591                        for (i = 0; i < pkt->common.count; i++) {
592                                ssrc = ntohl(*alignptr);
593                                dbe = rtcp_getornew_dbentry(sp, ssrc, cur_time);
594                                dbe->last_active = cur_time;
595                                sdes = (rtcp_sdes_item_t *) (alignptr + 1);
596                                while (sdes->type) {
597                                        lenstr = sdes->length;
598                                        sdes->length += 2;
599                                        switch (sdes->type) {
600                                        case RTCP_SDES_CNAME:
601                                                if (dbe->sentry->cname) {
602                                                        if (strncmp(dbe->sentry->cname, sdes->data, lenstr) != 0) {
603                                                                debug_msg("CNAME change %d : [%s] --> [%s]\n", lenstr, dbe->sentry->cname, sdes->data);
604                                                        }
605                                                        break;
606                                                }
607                                                dbe->sentry->cname = (char *) xmalloc(lenstr + 1);
608                                                memcpy(dbe->sentry->cname, sdes->data, lenstr);
609                                                dbe->sentry->cname[lenstr] = '\0';
610                                                if (ssrc == sp->db->myssrc && sp->db->my_dbe->sentry->cname &&
611                                                                strcmp(dbe->sentry->cname, sp->db->my_dbe->sentry->cname)) {
612                                                        sp->db->old_ssrc   = sp->db->myssrc;
613                                                        sp->db->myssrc     = lrand48();
614                                                        sp->db->pkt_count  = 0;
615                                                        sp->db->byte_count = 0;
616                                                }
617                                                ui_info_update_cname(sp, dbe);
618                                                break;
619                                        case RTCP_SDES_NAME:
620                                                if (dbe->sentry->name) {
621                                                        if (!strncmp(dbe->sentry->name, sdes->data, lenstr)) {
622                                                                break;
623                                                        }
624                                                        xfree(dbe->sentry->name);
625                                                }
626                                                dbe->sentry->name = (char *) xmalloc(lenstr + 1);
627                                                memcpy(dbe->sentry->name, sdes->data, lenstr);
628                                                dbe->sentry->name[lenstr] = '\0';
629                                                ui_info_update_name(sp, dbe);
630                                                break;
631                                        case RTCP_SDES_EMAIL:
632                                                if (dbe->sentry->email) {
633                                                        if (!strncmp(dbe->sentry->email, sdes->data, lenstr)) {
634                                                                break;
635                                                        }
636                                                        xfree(dbe->sentry->email);
637                                                }
638                                                dbe->sentry->email = (char *) xmalloc(lenstr + 1);
639                                                memcpy(dbe->sentry->email, sdes->data, lenstr);
640                                                dbe->sentry->email[lenstr] = '\0';
641                                                ui_info_update_email(sp, dbe);
642                                                break;
643                                        case RTCP_SDES_PHONE:
644                                                if (dbe->sentry->phone) {
645                                                        if (!strncmp(dbe->sentry->phone, sdes->data, lenstr)) {
646                                                                break;
647                                                        }
648                                                        xfree(dbe->sentry->phone);
649                                                }
650                                                dbe->sentry->phone = (char *) xmalloc(lenstr + 1);
651                                                memcpy(dbe->sentry->phone, sdes->data, lenstr);
652                                                dbe->sentry->phone[lenstr] = '\0';
653                                                ui_info_update_phone(sp, dbe);
654                                                break;
655                                        case RTCP_SDES_LOC:
656                                                if (dbe->sentry->loc) {
657                                                        if (!strncmp(dbe->sentry->loc, sdes->data, lenstr)) {
658                                                                break;
659                                                        }
660                                                        xfree(dbe->sentry->loc);
661                                                }
662                                                dbe->sentry->loc = (char *) xmalloc(lenstr + 1);
663                                                memcpy(dbe->sentry->loc, sdes->data, lenstr);
664                                                dbe->sentry->loc[lenstr] = '\0';
665                                                ui_info_update_loc(sp, dbe);
666                                                break;
667                                        case RTCP_SDES_TOOL:
668                                                if (dbe->sentry->tool) {
669                                                        if (!strncmp(dbe->sentry->tool, sdes->data, lenstr)) {
670                                                                break;
671                                                        }
672                                                        xfree(dbe->sentry->tool);
673                                                }
674                                                dbe->sentry->tool = (char *) xmalloc(lenstr + 1);
675                                                memcpy(dbe->sentry->tool, sdes->data, lenstr);
676                                                dbe->sentry->tool[lenstr] = '\0';
677                                                ui_info_update_tool(sp, dbe);
678                                                break;
679                                        case RTCP_SDES_NOTE:
680                                                if (dbe->sentry->note) {
681                                                        if (!strncmp(dbe->sentry->note, sdes->data, lenstr)) {
682                                                                break;
683                                                        }
684                                                        xfree(dbe->sentry->note);
685                                                }
686                                                dbe->sentry->note = (char *) xmalloc(lenstr + 1);
687                                                memcpy(dbe->sentry->note, sdes->data, lenstr);
688                                                dbe->sentry->note[lenstr] = '\0';
689                                                ui_info_update_note(sp, dbe);
690                                                break;
691                                        default:
692                                                debug_msg("SDES packet type %d ignored\n", sdes->type);
693                                                break;
694                                        }
695                                        sdes = (rtcp_sdes_item_t *) ((u_int8 *) sdes + sdes->length);
696                                }
697                                while ((u_int8 *) sdes >= (u_int8 *) alignptr) {
698                                        alignptr++;     /* Next 32bit boundary */
699                                }
700                        }
701                        break;
702                case RTCP_APP
703                        break;
704                default:
705                        break;
706                }
707                pkt = (rtcp_t *) ((u_int32 *) pkt + ntohs(pkt->common.length) + 1);
708        }
709}
710
711/*
712 * Calculate the RTCP report interval. This function is copied from rfc1889 [csp]
713 */
714u_int32 rtcp_interval(int        members,
715                      int        senders,
716                      double     rtcp_bw,
717                      int        we_sent,
718                      int        packet_size,
719                      int       *avg_rtcp_size,
720                      int        initial,
721                      u_int32    clock_freq)
722{
723    double RTCP_MIN_TIME           = 5.0;                               /* Min time between report, in seconds    */
724    double RTCP_SENDER_BW_FRACTION = 0.25;                              /* Fraction of RTCP bandwidth used for SR */
725    double RTCP_RCVR_BW_FRACTION   = (1-RTCP_SENDER_BW_FRACTION);       /* Fraction of RTCP bandwidth used for RR */
726    int    RTCP_SIZE_GAIN          = 16;                                /*                                        */
727    double t;                                                           /* interval                               */
728    double rtcp_min_time           = RTCP_MIN_TIME;                     /*                                        */
729    int n;                                                              /* no. of members for computation         */
730
731#ifdef DEBUG_RTCP
732    printf("members=%d, senders=%d, rtcp_bw=%f, we_sent=%d, packet_size=%d, avg_rtcp_size=%d, initial=%d\n",
733            members, senders, rtcp_bw, we_sent, packet_size, *avg_rtcp_size, initial);
734#endif
735    /* Very first call at application start-up uses half the min     */
736    /* delay for quicker notification while still allowing some time */
737    /* before reporting for randomization and to learn about other   */
738    /* sources so the report interval will converge to the correct   */
739    /* interval more quickly.  The average RTCP size is initialized  */
740    /* to 128 octets which is conservative (it assumes everyone else */
741    /* is generating SRs instead of RRs: 20 IP + 8 UDP + 52 SR + 48  */
742    /* SDES CNAME).                                                  */
743    if (initial) {
744        rtcp_min_time /= 2;
745        *avg_rtcp_size = 128;
746    }
747
748    /* If there were active senders, give them at least a minimum     */
749    /* share of the RTCP bandwidth.  Otherwise all participants share */
750    /* the RTCP bandwidth equally.                                    */
751    n = members;
752    if (senders > 0 && senders < members * RTCP_SENDER_BW_FRACTION) {
753        if (we_sent) {
754            rtcp_bw *= RTCP_SENDER_BW_FRACTION;
755            n = senders;
756        } else {
757            rtcp_bw *= RTCP_RCVR_BW_FRACTION;
758            n -= senders;
759        }
760    }
761
762    /* Update the average size estimate by the size of the report */
763    /* packet we just sent.                                       */
764    *avg_rtcp_size += (packet_size - *avg_rtcp_size) / RTCP_SIZE_GAIN;
765
766    /* The effective number of sites times the average packet size is */
767    /* the total number of octets sent when each site sends a report. */
768    /* Dividing this by the effective bandwidth gives the time        */
769    /* interval over which those packets must be sent in order to     */
770    /* meet the bandwidth target, with a minimum enforced.  In that   */
771    /* time interval we send one report so this time is also our      */
772    /* average time between reports.                                  */
773    t = (*avg_rtcp_size) * n / rtcp_bw;
774    if (t < rtcp_min_time) t = rtcp_min_time;
775
776    /* To avoid traffic bursts from unintended synchronization with   */
777    /* other sites, we then pick our actual next report interval as a */
778    /* random number uniformly distributed between 0.5*t and 1.5*t.   */
779#ifdef DEBUG_RTCP
780    printf("RTCP reporting interval is %f seconds\n", t);
781#endif
782    return (u_int32) (t * (drand48() + 0.5)) * clock_freq;
783}
784
785void 
786rtcp_exit(session_struct *sp1, session_struct *sp2, socket_udp *s)
787{
788        u_int8           packet[MAX_PACKLEN];
789        u_int8          *ptr = packet;
790        rtcp_dbentry    *src;
791
792        /* We should do RTCP BYE reconsideration here... instead we take */
793        /* the easy way out and only send BYE packets if there are less  */
794        /* than 50 members in the group. This is ugly, but DOES conform  */
795        /* to draft-ietf-avt-rtp-new-01.txt (section 6.3.7)        [csp] */
796        if (sp1->db->members < 50) {
797                /* Send an RTCP BYE packet... */
798                ptr = rtcp_packet_fmt_srrr(sp1, ptr);
799                ptr = rtcp_packet_fmt_bye(ptr, sp1->db->myssrc, sp1->mode == TRANSCODER? sp2->db->ssrc_db: (rtcp_dbentry *) NULL);
800                net_write(s, packet, ptr - packet, PACKET_RTCP);
801        }
802
803        while ((src = sp1->db->ssrc_db) != NULL) {
804                rtcp_delete_dbentry(sp1, src->ssrc);
805        }
806        if (sp1->mode == TRANSCODER) {
807                rtcp_free_dbentry(sp2->db->my_dbe);
808                while ((src = sp2->db->ssrc_db) != NULL) {
809                        rtcp_delete_dbentry(sp2, src->ssrc);
810                }
811        }
812        rtcp_db_exit(sp1);
813        if (sp2 && sp2->db) rtcp_db_exit(sp2);
814}
815
816/*
817 * rtcp_update() Performs the following periodic functions:
818 *   Expires elements from the SSRC database
819 *   Sends out sender reports/receiver reports
820 *   Sends the obligatory BYE packet if SSRC was changed
821 *
822 */
823void 
824rtcp_update(session_struct *sp, socket_udp *s)
825{
826        u_int8          packet[MAX_PACKLEN];
827        u_int8         *ptr     = packet;
828        int             packlen = 0;
829        u_int32         now     = get_time(sp->device_clock);
830
831        if (sp->db->old_ssrc) {
832                /* Our SSRC has changed, so send a BYE packet for that SSRC */
833                ptr = rtcp_packet_fmt_srrr(sp, ptr);
834                ptr = rtcp_packet_fmt_bye(ptr, sp->db->old_ssrc, sp->mode==TRANSCODER?sp->db->ssrc_db:(rtcp_dbentry *)NULL);
835                packlen = ptr - (u_int8 *) packet;
836                net_write(s, (unsigned char *) packet, packlen, PACKET_RTCP);
837                sp->db->last_rpt = now;
838                sp->db->old_ssrc = 0;
839        }
840
841        /* Check if it's time to send an RTCP packet... */
842        if ((now - sp->db->last_rpt) > sp->db->report_interval) {
843                ptr = rtcp_packet_fmt_srrr(sp, ptr);
844                ptr = rtcp_packet_fmt_sdes(sp, ptr);
845                packlen = ptr - packet;
846                net_write(s, packet, packlen, PACKET_RTCP);
847
848                /* Calculate the interval until we're due to send another RTCP packet... */
849                sp->db->report_interval = rtcp_interval(sp->db->members, sp->db->senders, sp->db->rtcp_bw, sp->db->sending,
850                                                        packlen, &(sp->db->avg_size), sp->db->initial_rtcp, get_freq(sp->device_clock));
851                /* Reset per-report statistics... */
852                sp->db->last_rpt     = now;
853                sp->db->initial_rtcp = FALSE;
854                sp->db->sending      = FALSE;
855                sp->db->senders      = 0;
856        }
857}
Note: See TracBrowser for help on using the browser.