root/rat/trunk/rtcp_pckt.c @ 1990

Revision 1990, 29.0 KB (checked in by ucaccsp, 16 years ago)

Fix compilation on Irix.

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