UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
rtp.c File Reference
#include <errno.h>
#include <inttypes.h>
#include <stdatomic.h>
#include "memory.h"
#include "debug.h"
#include "net_udp.h"
#include "crypto/crypt_des.h"
#include "crypto/crypt_aes.h"
#include "tv.h"
#include "crypto/md5.h"
#include "ntp.h"
#include "rtp.h"
#include "utils/misc.h"
#include "utils/net.h"
#include "utils/random.h"
Include dependency graph for rtp.c:

Go to the source code of this file.

Classes

struct  _rtcp_rr_wrapper
 
struct  _source
 
struct  options
 
struct  rtcp_common
 
struct  rtcp_t
 
struct  rtp
 

Macros

#define IPPORT_DYNAMIC   ((1U<<15U) + (1U<<14U))
 
#define IPPORT_MAX   ((1U<<16U) - 1U)
 
#define max(a, b)
 
#define MAX_DROPOUT   3000
 
#define MAX_ENCRYPTION_PAD   16
 
#define MAX_MISORDER   100
 
#define MAXCNAMELEN   255
 
#define min(a, b)
 
#define MIN_SEQUENTIAL   2
 
#define MOD_NAME   "[rtp] "
 
#define RTCP_APP   204
 
#define RTCP_BYE   203
 
#define RTCP_RR   201
 
#define RTCP_RX   205
 
#define RTCP_SDES   202
 
#define RTCP_SR   200
 
#define RTP_DB_SIZE   11
 
#define RTP_LOWER_LAYER_OVERHEAD   28 /* IPv4 + UDP */
 
#define RTP_MAX_SDES_LEN   256
 
#define RTP_SEQ_MOD   0x10000
 

Typedefs

typedef struct _rtcp_rr_wrapper rtcp_rr_wrapper
 
typedef bool(* rtp_decrypt_func) (struct rtp *, unsigned char *data, unsigned int size, unsigned char *initvec)
 
typedef int(* rtp_encrypt_func) (struct rtp *, unsigned char *data, unsigned int size, unsigned char *initvec)
 
typedef struct _source source
 

Functions

static int add_sdes_item (uint8_t *buf, int buflen, int type, const char *val)
 
static void check_database (struct rtp *session)
 
static void check_source (source *s)
 
static void compute_loss_intervals (struct rtp *session, rtp_packet *packet)
 
static uint32_t compute_rtt (struct rtp *session, rtcp_rx *rrx)
 
static source * create_source (struct rtp *session, uint32_t ssrc, int probation)
 
static void delete_source (struct rtp *session, uint32_t ssrc)
 
static bool des_decrypt (struct rtp *session, unsigned char *data, unsigned int size, unsigned char *initVec)
 
static int des_encrypt (struct rtp *session, unsigned char *data, unsigned int size, unsigned char *initVec)
 
static bool des_initialize (struct rtp *session, const u_char *hash, int hash_len)
 
static int filter_event (struct rtp *session, uint32_t ssrc)
 
static int format_report_blocks (rtcp_rr *rrp, int remaining_length, struct rtp *session)
 
static uint8_t * format_rtcp_app (uint8_t *buffer, int buflen, uint32_t ssrc, rtcp_app *app)
 
static uint8_t * format_rtcp_rr (uint8_t *buffer, int buflen, struct rtp *session)
 
static uint8_t * format_rtcp_sdes (uint8_t *buffer, int buflen, uint32_t ssrc, struct rtp *session)
 
static uint8_t * format_rtcp_sr (uint8_t *buffer, int buflen, struct rtp *session, uint32_t rtp_ts)
 
static char * get_cname (socket_udp *s)
 
static const rtcp_rr * get_rr (struct rtp *session, uint32_t reporter_ssrc, uint32_t reportee_ssrc)
 
static source * get_source (struct rtp *session, uint32_t ssrc)
 
static void init_opt (struct rtp *session)
 
static void init_seq (source *s, uint16_t seq)
 
static void insert_rr (struct rtp *session, uint32_t reporter_ssrc, rtcp_rr *rr, rtcp_rx *rx)
 
static uint32_t next_csrc (struct rtp *session)
 
static void process_report_blocks (struct rtp *session, rtcp_t *packet, uint32_t ssrc, rtcp_rr *rrp, rtcp_rx *rrx)
 
static void process_rtcp_app (struct rtp *session, rtcp_t *packet)
 
static void process_rtcp_bye (struct rtp *session, rtcp_t *packet)
 
static void process_rtcp_rr (struct rtp *session, rtcp_t *packet)
 
static void process_rtcp_rx (struct rtp *session, rtcp_t *packet)
 
static void process_rtcp_sdes (struct rtp *session, rtcp_t *packet)
 
static void process_rtcp_sr (struct rtp *session, rtcp_t *packet)
 
static void process_rtp (struct rtp *session, uint32_t curr_rtp_ts, rtp_packet *packet, source *s)
 
static source * really_create_source (struct rtp *session, uint32_t ssrc, int probation, source *s)
 
static void remove_rr (struct rtp *session, uint32_t ssrc)
 
static bool rijndael_decrypt (struct rtp *session, unsigned char *data, unsigned int size, unsigned char *initVec)
 
static int rijndael_encrypt (struct rtp *session, unsigned char *data, unsigned int size, unsigned char *initVec)
 
static bool rijndael_initialize (struct rtp *session, const u_char *hash, int hash_len)
 
static double rtcp_interval (struct rtp *session)
 
bool rtcp_recv_r (struct rtp *session, struct timeval *timeout, uint32_t curr_rtp_ts)
 
static void rtcp_udp_send (struct rtp *session, int len, char *buffer)
 
bool rtp_add_csrc (struct rtp *session, uint32_t csrc)
 
void rtp_async_start (struct rtp *session, int nr_packets)
 
void rtp_async_wait (struct rtp *session)
 
int rtp_compute_fract_lost (struct rtp *session, uint32_t ssrc)
 
bool rtp_del_csrc (struct rtp *session, uint32_t csrc)
 
void rtp_done (struct rtp *session)
 
void rtp_flush_recv_buf (struct rtp *session)
 
uint64_t rtp_get_bytes_sent (struct rtp *session)
 
bool rtp_get_option (struct rtp *session, rtp_option optname, int *optval)
 
int rtp_get_recv_buf (struct rtp *session)
 
const rtcp_rr * rtp_get_rr (struct rtp *session, uint32_t reporter, uint32_t reportee)
 
const char * rtp_get_sdes (struct rtp *session, uint32_t ssrc, rtcp_sdes_type type)
 
const rtcp_sr * rtp_get_sr (struct rtp *session, uint32_t ssrc)
 
struct socket_udp_local * rtp_get_udp_local_socket (struct rtp *session)
 
int rtp_get_udp_rx_port (struct rtp *session)
 
uint8_t * rtp_get_userdata (struct rtp *session)
 
bool rtp_has_receiver (struct rtp *session)
 
struct rtp * rtp_init (const char *addr, uint16_t rx_port, uint16_t tx_port, int ttl, double rtcp_bw, int tfrc_on, rtp_callback callback, uint8_t *userdata, int force_ip_version, bool multithreaded)
 
struct rtp * rtp_init_if (const char *addr, const char *iface, uint16_t rx_port, uint16_t tx_port, int ttl, double rtcp_bw, int tfrc_on, rtp_callback callback, uint8_t *userdata, int force_ip_version, bool multithreaded)
 
rtp_t rtp_init_with_udp_socket (struct socket_udp_local *l, struct sockaddr *sa, socklen_t len, rtp_callback callback)
 
bool rtp_is_ipv6 (struct rtp *session)
 
uint32_t rtp_my_ssrc (struct rtp *session)
 
static void rtp_process_ctrl (struct rtp *session, uint8_t *buffer, int buflen)
 
static void rtp_process_data (struct rtp *session, uint32_t curr_rtp_ts, uint8_t *buffer, rtp_packet *packet, int buflen)
 
bool rtp_recv (struct rtp *session, struct timeval *timeout, uint32_t curr_rtp_ts)
 
static int rtp_recv_data (struct rtp *session, uint32_t curr_rtp_ts)
 
int rtp_recv_poll_r (struct rtp **sessions, struct timeval *timeout, uint32_t curr_rtp_ts)
 
bool rtp_recv_r (struct rtp *session, struct timeval *timeout, uint32_t curr_rtp_ts)
 Receive RTP packets and dispatch them.
 
void rtp_send_bye (struct rtp *session)
 
static void rtp_send_bye_now (struct rtp *session)
 
void rtp_send_ctrl (struct rtp *session, uint32_t rtp_ts, rtcp_app_callback appcallback, time_ns_t curr_time)
 
int rtp_send_data (struct rtp *session, uint32_t rtp_ts, char pt, int m, int cc, const uint32_t *csrc, char *data, int data_len, char *extn, uint16_t extn_len, uint16_t extn_type)
 
int rtp_send_data_hdr (struct rtp *session, uint32_t rtp_ts, char pt, int m, int cc, const uint32_t *csrc, char *phdr, int phdr_len, char *data, int data_len, char *extn, uint16_t extn_len, uint16_t extn_type)
 
int rtp_send_raw_rtp_data (struct rtp *session, char *buffer, int buffer_len)
 
bool rtp_set_encryption_key (struct rtp *session, const char *passphrase)
 
bool rtp_set_my_ssrc (struct rtp *session, uint32_t ssrc)
 
bool rtp_set_option (struct rtp *session, rtp_option optname, int optval)
 
bool rtp_set_recv_buf (struct rtp *session, int bufsize)
 
void rtp_set_recv_iov (struct rtp *session, struct msghdr *m)
 
bool rtp_set_sdes (struct rtp *session, uint32_t ssrc, rtcp_sdes_type type, const char *value, int length)
 
bool rtp_set_send_buf (struct rtp *session, int bufsize)
 
void rtp_update (struct rtp *session, time_ns_t curr_time)
 
static void send_rtcp (struct rtp *session, uint32_t rtp_ts, rtcp_app_callback appcallback)
 
static int ssrc_hash (uint32_t ssrc)
 
static void timeout_rr (struct rtp *session, time_ns_t curr_ts)
 
static int update_seq (source *s, uint16_t seq)
 
static int validate_rtcp (uint8_t *packet, int len)
 
static bool validate_rtp (struct rtp *session, rtp_packet *packet, int len, int vlen)
 
static bool validate_rtp2 (rtp_packet *packet, int len, int vlen)
 

Detailed Description

Bug
The struct rtp is inherently not thread safe in general, although it works most of the time (but see bug in check_database()).

Definition in file rtp.c.

Macro Definition Documentation

◆ IPPORT_DYNAMIC

#define IPPORT_DYNAMIC   ((1U<<15U) + (1U<<14U))

Definition at line 102 of file rtp.c.

Referenced by rtp_init_if().

◆ IPPORT_MAX

#define IPPORT_MAX   ((1U<<16U) - 1U)

Definition at line 103 of file rtp.c.

Referenced by rtp_init_if().

◆ max

◆ MAX_DROPOUT

#define MAX_DROPOUT   3000

Definition at line 125 of file rtp.c.

Referenced by update_seq().

◆ MAX_ENCRYPTION_PAD

#define MAX_ENCRYPTION_PAD   16

Definition at line 109 of file rtp.c.

Referenced by rtp_send_bye_now(), and send_rtcp().

◆ MAX_MISORDER

#define MAX_MISORDER   100

Definition at line 126 of file rtp.c.

Referenced by update_seq().

◆ MAXCNAMELEN

#define MAXCNAMELEN   255

Definition at line 905 of file rtp.c.

Referenced by get_cname().

◆ min

◆ MIN_SEQUENTIAL

#define MIN_SEQUENTIAL   2

Definition at line 127 of file rtp.c.

Referenced by rtp_process_data(), and update_seq().

◆ MOD_NAME

#define MOD_NAME   "[rtp] "

Definition at line 104 of file rtp.c.

◆ RTCP_APP

#define RTCP_APP   204

Definition at line 142 of file rtp.c.

Referenced by format_rtcp_app(), rtp_process_ctrl(), and validate_rtcp().

◆ RTCP_BYE

#define RTCP_BYE   203

Definition at line 141 of file rtp.c.

Referenced by rtp_process_ctrl(), rtp_send_bye_now(), and validate_rtcp().

◆ RTCP_RR

#define RTCP_RR   201

Definition at line 139 of file rtp.c.

Referenced by format_rtcp_rr(), rtp_process_ctrl(), and validate_rtcp().

◆ RTCP_RX

#define RTCP_RX   205

Definition at line 143 of file rtp.c.

Referenced by rtp_process_ctrl().

◆ RTCP_SDES

#define RTCP_SDES   202

Definition at line 140 of file rtp.c.

Referenced by format_rtcp_sdes(), rtp_process_ctrl(), and validate_rtcp().

◆ RTCP_SR

#define RTCP_SR   200

Definition at line 138 of file rtp.c.

Referenced by format_rtcp_sr(), rtp_process_ctrl(), and validate_rtcp().

◆ RTP_DB_SIZE

◆ RTP_LOWER_LAYER_OVERHEAD

#define RTP_LOWER_LAYER_OVERHEAD   28 /* IPv4 + UDP */

Definition at line 136 of file rtp.c.

Referenced by rtp_process_ctrl(), and rtp_send_bye().

◆ RTP_MAX_SDES_LEN

#define RTP_MAX_SDES_LEN   256

Definition at line 134 of file rtp.c.

◆ RTP_SEQ_MOD

#define RTP_SEQ_MOD   0x10000

Definition at line 133 of file rtp.c.

Referenced by init_seq(), and update_seq().

Typedef Documentation

◆ rtcp_rr_wrapper

◆ rtp_decrypt_func

typedef bool(* rtp_decrypt_func) (struct rtp *, unsigned char *data, unsigned int size, unsigned char *initvec)

Definition at line 267 of file rtp.c.

◆ rtp_encrypt_func

typedef int(* rtp_encrypt_func) (struct rtp *, unsigned char *data, unsigned int size, unsigned char *initvec)

Definition at line 265 of file rtp.c.

◆ source

typedef struct _source source

Function Documentation

◆ add_sdes_item()

static int add_sdes_item ( uint8_t * buf,
int buflen,
int type,
const char * val )
static

Definition at line 3075 of file rtp.c.

3076{
3077 /* Fill out an SDES item. It is assumed that the item is a NULL */
3078 /* terminated string. */
3079 rtcp_sdes_item *shdr = (rtcp_sdes_item *) buf;
3080 int namelen;
3081
3082 if (val == NULL) {
3083 debug_msg("Cannot format SDES item. type=%d val=%p\n", type,
3084 val);
3085 return 0;
3086 }
3087 shdr->type = type;
3088 namelen = strlen(val);
3089 shdr->length = namelen;
3090 strncpy(shdr->data, val, buflen - 2); /* The "-2" accounts for the other shdr fields */
3091 return namelen + 2;
3092}
int void * val
#define debug_msg(...)
#define debug_msg(...) log_msg(LOG_LEVEL_DEBUG, "[pid/%d +%d %s] ", getpid(), LINE,...
Definition debug.h:92
Option::OptType type
Definition settings.cpp:194
uint8_t type
Definition rtp.h:221
uint8_t length
Definition rtp.h:222
char data[1]
Definition rtp.h:223

References rtcp_sdes_item::data, debug_msg, rtcp_sdes_item::length, rtcp_sdes_item::type, type, and val.

Referenced by format_rtcp_sdes().

◆ check_database()

static void check_database ( struct rtp * session)
inlinestatic

Definition at line 540 of file rtp.c.

541{
542 /* This routine performs a sanity check on the database. */
543 /* This should not call any of the other routines which */
544 /* manipulate the database, to avoid common failures. */
545#if defined DEBUG && ! defined SUPPRESS_BUGS
546 source *s;
547 int source_count;
548 int chain;
549
550 assert(session != NULL);
551 assert(session->magic == 0xfeedface);
552 /* Check that we have a database entry for our ssrc... */
553 /* We only do this check if ssrc_count > 0 since it is */
554 /* performed during initialisation whilst creating the */
555 /* source entry for my_ssrc. */
556 if (session->ssrc_count > 0) {
557 for (s = session->db[ssrc_hash(session->my_ssrc)]; s != NULL;
558 s = s->next) {
559 if (s->ssrc == session->my_ssrc) {
560 break;
561 }
562 }
563 assert(s != NULL);
564 }
565
566 source_count = 0;
567 for (chain = 0; chain < RTP_DB_SIZE; chain++) {
568 /* Check that the linked lists making up the chains in */
569 /* the hash table are correctly linked together... */
570 for (s = session->db[chain]; s != NULL; s = s->next) {
571 check_source(s);
572 source_count++;
573 if (s->prev == NULL) {
574 assert(s == session->db[chain]);
575 } else {
576 assert(s->prev->next == s);
577 }
578 if (s->next != NULL) {
579 assert(s->next->prev == s);
580 }
581 /* Check that the SR is for this source... */
582 if (s->sr != NULL) {
584 assert(s->sr->ssrc == s->ssrc);
585 }
586 }
587 }
588 /* Check that the number of entries in the hash table */
589 /* matches session->ssrc_count */
590 assert(source_count == session->ssrc_count);
591#else
592 UNUSED(session);
593#endif
594}
#define UNUSED(x)
static int ssrc_hash(uint32_t ssrc)
Definition rtp.c:371
static void check_source(source *s)
Definition rtp.c:530
#define RTP_DB_SIZE
Definition rtp.c:247
Definition rtp.c:206
rtcp_sr *_Atomic sr
Definition rtp.c:218
uint32_t ssrc
Definition rtp.c:209
struct _source * prev
Definition rtp.c:208
struct _source * next
Definition rtp.c:207
uint32_t ssrc
Definition rtp.h:131
int ssrc_count
Definition rtp.c:290
uint32_t my_ssrc
Definition rtp.c:280
uint32_t magic
Definition rtp.c:335
source * db[RTP_DB_SIZE]
Definition rtp.c:282

References check_source(), rtp::db, rtp::magic, rtp::my_ssrc, _source::next, _source::prev, RTP_DB_SIZE, _source::sr, _source::ssrc, rtcp_sr::ssrc, rtp::ssrc_count, ssrc_hash(), and UNUSED.

Referenced by delete_source(), des_initialize(), get_source(), really_create_source(), rtcp_recv_r(), rtp_add_csrc(), rtp_del_csrc(), rtp_done(), rtp_get_rr(), rtp_get_sdes(), rtp_get_sr(), rtp_get_userdata(), rtp_my_ssrc(), rtp_recv(), rtp_recv_poll_r(), rtp_recv_r(), rtp_send_bye(), rtp_send_bye_now(), rtp_send_ctrl(), rtp_send_data_hdr(), rtp_set_encryption_key(), rtp_set_sdes(), rtp_update(), and send_rtcp().

Here is the call graph for this function:

◆ check_source()

static void check_source ( source * s)
inlinestatic

Definition at line 530 of file rtp.c.

531{
532#ifdef DEBUG
533 assert(s != NULL);
534 assert(s->magic == 0xc001feed);
535#else
536 UNUSED(s);
537#endif
538}
uint32_t magic
Definition rtp.c:235

References _source::magic, and UNUSED.

Referenced by check_database(), delete_source(), format_report_blocks(), get_source(), init_seq(), process_rtcp_app(), process_rtcp_bye(), rtp_add_csrc(), rtp_compute_fract_lost(), rtp_del_csrc(), rtp_get_sdes(), rtp_get_sr(), rtp_send_ctrl(), rtp_set_sdes(), rtp_update(), and update_seq().

◆ compute_loss_intervals()

static void compute_loss_intervals ( struct rtp * session,
rtp_packet * packet )
static

Definition at line 1466 of file rtp.c.

1467{
1468 UNUSED(session);
1469 UNUSED(packet);
1470
1471}

References UNUSED.

Referenced by process_rtp().

◆ compute_rtt()

static uint32_t compute_rtt ( struct rtp * session,
rtcp_rx * rrx )
static

Definition at line 2120 of file rtp.c.

2121{
2122 UNUSED(rrx);
2123 UNUSED(session);
2124 return 0;
2125}

References UNUSED.

Referenced by rtp_process_ctrl().

◆ create_source()

static source * create_source ( struct rtp * session,
uint32_t ssrc,
int probation )
inlinestatic

Definition at line 660 of file rtp.c.

662{
663 source *s = get_source(session, ssrc);
664 if (s == NULL) {
665 return really_create_source(session, ssrc, probation, s);
666 }
667 /* Source is already in the database... Mark it as */
668 /* active and exit (this is the common case...) */
670 return s;
671}
static source * get_source(struct rtp *session, uint32_t ssrc)
Definition rtp.c:596
static source * really_create_source(struct rtp *session, uint32_t ssrc, int probation, source *s)
Definition rtp.c:610
time_ns_t last_active
Definition rtp.c:221
static time_ns_t get_time_in_ns()
Definition tv.h:101

References get_source(), get_time_in_ns(), _source::last_active, and really_create_source().

Referenced by process_report_blocks(), process_rtcp_app(), process_rtcp_bye(), process_rtcp_rr(), process_rtcp_rx(), process_rtcp_sdes(), process_rtcp_sr(), process_rtp(), rtp_add_csrc(), rtp_init_if(), rtp_init_with_udp_socket(), and rtp_process_data().

Here is the call graph for this function:

◆ delete_source()

static void delete_source ( struct rtp * session,
uint32_t ssrc )
static

Definition at line 673 of file rtp.c.

674{
675 /* Remove a source from the RTP database... */
676 source *s = get_source(session, ssrc);
677 int h = ssrc_hash(ssrc);
678 rtp_event event;
679 time_ns_t event_ts = get_time_in_ns();
680
681 assert(s != NULL); /* Deleting a source which doesn't exist is an error... */
682
683 check_source(s);
684 check_database(session);
685 if (session->db[h] == s) {
686 /* It's the first entry in this chain... */
687 session->db[h] = s->next;
688 if (s->next != NULL) {
689 s->next->prev = NULL;
690 }
691 } else {
692 assert(s->prev != NULL); /* Else it would be the first in the chain... */
693 s->prev->next = s->next;
694 if (s->next != NULL) {
695 s->next->prev = s->prev;
696 }
697 }
698 /* Free the memory allocated to a source... */
699 if (s->sdes_cname != NULL)
700 free(s->sdes_cname);
701 if (s->sdes_name != NULL)
702 free(s->sdes_name);
703 if (s->sdes_email != NULL)
704 free(s->sdes_email);
705 if (s->sdes_phone != NULL)
706 free(s->sdes_phone);
707 if (s->sdes_loc != NULL)
708 free(s->sdes_loc);
709 if (s->sdes_tool != NULL)
710 free(s->sdes_tool);
711 if (s->sdes_note != NULL)
712 free(s->sdes_note);
713 if (s->sdes_priv != NULL)
714 free(s->sdes_priv);
715 if (s->sr != NULL)
716 free(s->sr);
717
718 remove_rr(session, ssrc);
719
720 /* Reduce our SSRC count, and perform reverse reconsideration on the RTCP */
721 /* reporting interval (draft-ietf-avt-rtp-new-05.txt, section 6.3.4). To */
722 /* make the transmission rate of RTCP packets more adaptive to changes in */
723 /* group membership, the following "reverse reconsideration" algorithm */
724 /* SHOULD be executed when a BYE packet is received that reduces members */
725 /* to a value less than pmembers: */
726 /* o The value for tn is updated according to the following formula: */
727 /* tn = tc + (members/pmembers)(tn - tc) */
728 /* o The value for tp is updated according the following formula: */
729 /* tp = tc - (members/pmembers)(tc - tp). */
730 /* o The next RTCP packet is rescheduled for transmission at time tn, */
731 /* which is now earlier. */
732 /* o The value of pmembers is set equal to members. */
733 session->ssrc_count--;
734 if (session->ssrc_count < session->ssrc_count_prev) {
735 session->next_rtcp_send_time =
737 session->next_rtcp_send_time +=
738 (session->ssrc_count / session->ssrc_count_prev)
739 * (session->next_rtcp_send_time - event_ts) * NS_IN_SEC;
740 session->last_rtcp_send_time -=
741 ((session->ssrc_count / session->ssrc_count_prev)
742 * (event_ts - session->last_rtcp_send_time)) * NS_IN_SEC;
743 session->ssrc_count_prev = session->ssrc_count;
744 }
745
746 /* Reduce our csrc count... */
747 if (s->should_advertise_sdes == TRUE) {
748 session->csrc_count--;
749 }
750 if (session->last_advertised_csrc == session->csrc_count) {
751 session->last_advertised_csrc = 0;
752 }
753
754 /* Signal to the application that this source is dead... */
755 if (!filter_event(session, ssrc)) {
756 event.ssrc = ssrc;
757 event.type = SOURCE_DELETED;
758 event.data = NULL;
759 session->callback(session, &event);
760 }
761 free(s);
762 check_database(session);
763}
#define TRUE
static void check_database(struct rtp *session)
Definition rtp.c:540
static void remove_rr(struct rtp *session, uint32_t ssrc)
Definition rtp.c:432
static int filter_event(struct rtp *session, uint32_t ssrc)
Definition rtp.c:338
@ SOURCE_DELETED
Definition rtp.h:188
int should_advertise_sdes
Definition rtp.c:222
char * sdes_loc
Definition rtp.c:214
char * sdes_cname
Definition rtp.c:210
char * sdes_tool
Definition rtp.c:215
char * sdes_priv
Definition rtp.c:217
char * sdes_note
Definition rtp.c:216
char * sdes_name
Definition rtp.c:211
char * sdes_email
Definition rtp.c:212
char * sdes_phone
Definition rtp.c:213
int csrc_count
Definition rtp.c:289
int last_advertised_csrc
Definition rtp.c:281
time_ns_t last_rtcp_send_time
Definition rtp.c:300
int ssrc_count_prev
Definition rtp.c:291
rtp_callback callback
Definition rtp.c:332
time_ns_t next_rtcp_send_time
Definition rtp.c:301
long long time_ns_t
Definition tv.h:81
#define NS_IN_SEC
Definition tv.h:92

References rtp::callback, check_database(), check_source(), rtp::csrc_count, rtp::db, filter_event(), get_source(), get_time_in_ns(), rtp::last_advertised_csrc, rtp::last_rtcp_send_time, _source::next, rtp::next_rtcp_send_time, NS_IN_SEC, _source::prev, remove_rr(), _source::sdes_cname, _source::sdes_email, _source::sdes_loc, _source::sdes_name, _source::sdes_note, _source::sdes_phone, _source::sdes_priv, _source::sdes_tool, _source::should_advertise_sdes, SOURCE_DELETED, _source::sr, rtp::ssrc_count, rtp::ssrc_count_prev, ssrc_hash(), and TRUE.

Referenced by rtp_done(), and rtp_update().

Here is the call graph for this function:

◆ des_decrypt()

static bool des_decrypt ( struct rtp * session,
unsigned char * data,
unsigned int size,
unsigned char * initVec )
static

Definition at line 3863 of file rtp.c.

3865{
3866 qfDES_CBC_d((unsigned char *)session->crypto_state.des.encryption_key,
3867 data, size, initVec);
3868 return true;
3869}
#define qfDES_CBC_d(_key, _data, _size, _initVec)
Definition crypt_des.h:38
struct rtp::@38::@40 des
char * encryption_key
Definition rtp.c:329
union rtp::@38 crypto_state

References rtp::crypto_state, rtp::des, rtp::encryption_key, and qfDES_CBC_d.

Referenced by des_initialize().

◆ des_encrypt()

static int des_encrypt ( struct rtp * session,
unsigned char * data,
unsigned int size,
unsigned char * initVec )
static

Definition at line 3855 of file rtp.c.

3857{
3858 qfDES_CBC_e((unsigned char *)session->crypto_state.des.encryption_key,
3859 data, size, initVec);
3860 return TRUE;
3861}
#define qfDES_CBC_e(_key, _data, _size, _initVec)
Definition crypt_des.h:37

References rtp::crypto_state, rtp::des, rtp::encryption_key, qfDES_CBC_e, and TRUE.

Referenced by des_initialize().

◆ des_initialize()

static bool des_initialize ( struct rtp * session,
const u_char * hash,
int hash_len )
static

Definition at line 3816 of file rtp.c.

3817{
3818 UNUSED(hash_len);
3819
3820 session->encryption_pad_length = 8;
3821 session->encrypt_func = des_encrypt;
3822 session->decrypt_func = des_decrypt;
3823
3824 if (session->crypto_state.des.encryption_key != NULL) {
3825 free(session->crypto_state.des.encryption_key);
3826 }
3827
3828 char *key = session->crypto_state.des.encryption_key = (char *)malloc(8);
3829
3830 /* Step 3: take first 56 bits of the MD5 hash */
3831 key[0] = hash[0];
3832 key[1] = hash[0] << 7 | hash[1] >> 1;
3833 key[2] = hash[1] << 6 | hash[2] >> 2;
3834 key[3] = hash[2] << 5 | hash[3] >> 3;
3835 key[4] = hash[3] << 4 | hash[4] >> 4;
3836 key[5] = hash[4] << 3 | hash[5] >> 5;
3837 key[6] = hash[5] << 2 | hash[6] >> 6;
3838 key[7] = hash[6] << 1;
3839
3840 /* Step 4: add parity bits */
3841 for (int i = 0; i < 8; ++i) {
3842 int k = key[i] & 0xfe;
3843 int j = k;
3844 j ^= j >> 4;
3845 j ^= j >> 2;
3846 j ^= j >> 1;
3847 j = (j & 1) ^ 1;
3848 key[i] = k | j;
3849 }
3850
3851 check_database(session);
3852 return true;
3853}
static int des_encrypt(struct rtp *session, unsigned char *data, unsigned int size, unsigned char *initVec)
Definition rtp.c:3855
static bool des_decrypt(struct rtp *session, unsigned char *data, unsigned int size, unsigned char *initVec)
Definition rtp.c:3863
rtp_encrypt_func encrypt_func
Definition rtp.c:319
int encryption_pad_length
Definition rtp.c:321
rtp_decrypt_func decrypt_func
Definition rtp.c:320
const char * key
Definition cineform.cpp:125

References check_database(), rtp::crypto_state, rtp::decrypt_func, rtp::des, des_decrypt(), des_encrypt(), rtp::encrypt_func, rtp::encryption_key, rtp::encryption_pad_length, key, and UNUSED.

Referenced by rtp_set_encryption_key().

Here is the call graph for this function:

◆ filter_event()

static int filter_event ( struct rtp * session,
uint32_t ssrc )
inlinestatic

Definition at line 338 of file rtp.c.

339{
340 return session->opt->filter_my_packets
341 && (ssrc == rtp_my_ssrc(session));
342}
uint32_t rtp_my_ssrc(struct rtp *session)
Definition rtp.c:1401
int filter_my_packets
Definition rtp.c:256
options * opt
Definition rtp.c:284

References options::filter_my_packets, rtp::opt, and rtp_my_ssrc().

Referenced by delete_source(), process_report_blocks(), process_rtcp_app(), process_rtcp_bye(), process_rtcp_sdes(), process_rtcp_sr(), process_rtp(), really_create_source(), rtp_process_ctrl(), and timeout_rr().

Here is the call graph for this function:

◆ format_report_blocks()

static int format_report_blocks ( rtcp_rr * rrp,
int remaining_length,
struct rtp * session )
static

Definition at line 2935 of file rtp.c.

2937{
2938 int nblocks = 0;
2939 int h;
2940 source *s;
2941 uint32_t now_sec;
2942 uint32_t now_frac;
2943
2944 for (h = 0; h < RTP_DB_SIZE; h++) {
2945 for (s = session->db[h]; s != NULL; s = s->next) {
2946 check_source(s);
2947 if ((nblocks == 31) || (remaining_length < 24)) {
2948 break; /* Insufficient space for more report blocks... */
2949 }
2950 if (s->sender) {
2951 /* Much of this is taken from A.3 of draft-ietf-avt-rtp-new-01.txt */
2952 int extended_max = s->cycles + s->max_seq;
2953 int expected = extended_max - s->base_seq + 1;
2954 int lost = expected - s->received;
2955 int expected_interval =
2956 expected - s->expected_prior;
2957 int received_interval =
2958 s->received - s->received_prior;
2959 int lost_interval =
2960 expected_interval - received_interval;
2961 int fraction;
2962 uint32_t lsr;
2963 uint32_t dlsr;
2964
2965 //printf("lost_interval %d\n", lost_interval);
2966 s->expected_prior = expected;
2967 s->received_prior = s->received;
2968 if (expected_interval == 0
2969 || lost_interval <= 0) {
2970 fraction = 0;
2971 } else {
2972 fraction =
2973 (lost_interval << 8) /
2974 expected_interval;
2975 }
2976
2977 if (s->sr == NULL) {
2978 lsr = 0;
2979 dlsr = 0;
2980 } else {
2981 ntp64_time(&now_sec, &now_frac);
2982 lsr =
2984 s->sr->ntp_frac);
2985 dlsr =
2986 ntp64_to_ntp32(now_sec,
2987 now_frac) -
2989 s->last_sr_frac);
2990 }
2991 rrp->ssrc = htonl(s->ssrc);
2992 rrp->fract_lost = fraction;
2993 rrp->total_lost = lost & 0x00ffffff;
2994 rrp->last_seq = htonl(extended_max);
2995 rrp->jitter = htonl(s->jitter / 16);
2996 rrp->lsr = htonl(lsr);
2997 rrp->dlsr = htonl(dlsr);
2998 rrp++;
2999 remaining_length -= 24;
3000 nblocks++;
3001 s->sender = FALSE;
3002 session->sender_count--;
3003 if (session->sender_count == 0) {
3004 break; /* No point continuing, since we've reported on all senders... */
3005 }
3006 }
3007 }
3008 }
3009 return nblocks;
3010}
#define FALSE
void ntp64_time(uint32_t *ntp_sec, uint32_t *ntp_frac)
Definition ntp.c:26
#define ntp64_to_ntp32(ntp_sec, ntp_frac)
Definition ntp.h:23
uint16_t max_seq
Definition rtp.c:226
uint32_t jitter
Definition rtp.c:233
int received_prior
Definition rtp.c:230
int sender
Definition rtp.c:223
int expected_prior
Definition rtp.c:231
uint32_t last_sr_frac
Definition rtp.c:220
uint32_t base_seq
Definition rtp.c:225
int received
Definition rtp.c:229
uint32_t last_sr_sec
Definition rtp.c:219
uint32_t cycles
Definition rtp.c:228
uint32_t lsr
Definition rtp.h:150
uint32_t dlsr
Definition rtp.h:151
uint32_t total_lost
Definition rtp.h:143
uint32_t jitter
Definition rtp.h:149
uint32_t fract_lost
Definition rtp.h:142
uint32_t ssrc
Definition rtp.h:140
uint32_t last_seq
Definition rtp.h:148
uint32_t ntp_frac
Definition rtp.h:133
uint32_t ntp_sec
Definition rtp.h:132
int sender_count
Definition rtp.c:292

References _source::base_seq, check_source(), _source::cycles, rtp::db, rtcp_rr::dlsr, _source::expected_prior, FALSE, rtcp_rr::fract_lost, _source::jitter, rtcp_rr::jitter, rtcp_rr::last_seq, _source::last_sr_frac, _source::last_sr_sec, rtcp_rr::lsr, _source::max_seq, _source::next, ntp64_time(), ntp64_to_ntp32, rtcp_sr::ntp_frac, rtcp_sr::ntp_sec, _source::received, _source::received_prior, RTP_DB_SIZE, _source::sender, rtp::sender_count, _source::sr, _source::ssrc, rtcp_rr::ssrc, and rtcp_rr::total_lost.

Referenced by format_rtcp_rr(), and format_rtcp_sr().

Here is the call graph for this function:

◆ format_rtcp_app()

static uint8_t * format_rtcp_app ( uint8_t * buffer,
int buflen,
uint32_t ssrc,
rtcp_app * app )
static

Definition at line 3234 of file rtp.c.

3236{
3237 /* Write an RTCP APP into the outgoing packet buffer. */
3238 rtcp_app *packet = (rtcp_app *)(void *) buffer;
3239 int pkt_octets = (app->length + 1) * 4;
3240 int data_octets = pkt_octets - 12;
3241
3242 assert(data_octets >= 0); /* ...else not a legal APP packet. */
3243 assert(buflen >= pkt_octets); /* ...else there isn't space for the APP packet. */
3244
3245 /* Copy one APP packet from "app" to "packet". */
3246 packet->version = RTP_VERSION;
3247 packet->p = app->p;
3248 packet->subtype = app->subtype;
3249 packet->pt = RTCP_APP;
3250 packet->length = htons(app->length);
3251 packet->ssrc = htonl(ssrc);
3252 memcpy(packet->name, app->name, 4);
3253 memcpy(packet->data, app->data, data_octets);
3254
3255 /* Return a pointer to the byte that immediately follows the last byte written. */
3256 return buffer + pkt_octets;
3257}
#define RTCP_APP
Definition rtp.c:142
#define RTP_VERSION
Definition rtp.h:59
unsigned short version
Definition rtp.h:163
unsigned short pt
Definition rtp.h:171
uint32_t ssrc
Definition rtp.h:173
unsigned short subtype
Definition rtp.h:165
char data[1]
Definition rtp.h:175
unsigned short p
Definition rtp.h:164
char name[4]
Definition rtp.h:174
uint16_t length
Definition rtp.h:172
static const ULWord app
Definition aja.cpp:162

References app, rtcp_app::data, rtcp_app::length, rtcp_app::name, rtcp_app::p, rtcp_app::pt, RTCP_APP, RTP_VERSION, rtcp_app::ssrc, rtcp_app::subtype, and rtcp_app::version.

Referenced by send_rtcp().

◆ format_rtcp_rr()

static uint8_t * format_rtcp_rr ( uint8_t * buffer,
int buflen,
struct rtp * session )
static

Definition at line 3048 of file rtp.c.

3050{
3051 /* Write an RTCP RR into buffer, returning a pointer to */
3052 /* the next byte after the header we have just written. */
3053 rtcp_t *packet = (rtcp_t *)(void *) buffer;
3054 int remaining_length;
3055
3056 assert(buflen >= 8); /* ...else there isn't space for the header */
3057
3058 packet->common.version = 2;
3059 packet->common.p = 0;
3060 packet->common.count = 0;
3061 packet->common.pt = RTCP_RR;
3062 packet->common.length = htons(1);
3063 packet->r.rr.ssrc = htonl(session->my_ssrc);
3064
3065 /* Add report blocks, until we either run out of senders */
3066 /* to report upon or we run out of space in the buffer. */
3067 remaining_length = buflen - 8;
3068 packet->common.count =
3069 format_report_blocks(packet->r.rr.rr, remaining_length, session);
3070 packet->common.length =
3071 htons((uint16_t) (1 + (packet->common.count * 6)));
3072 return buffer + 8 + (24 * packet->common.count);
3073}
static int format_report_blocks(rtcp_rr *rrp, int remaining_length, struct rtp *session)
Definition rtp.c:2935
#define RTCP_RR
Definition rtp.c:139
unsigned short count
Definition rtp.c:152
unsigned short p
Definition rtp.c:153
unsigned short pt
Definition rtp.c:155
uint16_t length
Definition rtp.c:157
unsigned short version
Definition rtp.c:154
Definition rtp.c:160
rtcp_rr rr[1]
Definition rtp.c:165
union rtcp_t::@32 r
rtcp_common common
Definition rtp.c:161

References rtcp_t::common, rtcp_common::count, format_report_blocks(), rtcp_common::length, rtp::my_ssrc, rtcp_common::p, rtcp_common::pt, rtcp_t::r, rtcp_t::rr, RTCP_RR, rtcp_rr::ssrc, and rtcp_common::version.

Referenced by rtp_send_bye_now(), and send_rtcp().

Here is the call graph for this function:

◆ format_rtcp_sdes()

static uint8_t * format_rtcp_sdes ( uint8_t * buffer,
int buflen,
uint32_t ssrc,
struct rtp * session )
static

Definition at line 3094 of file rtp.c.

3096{
3097 /* From draft-ietf-avt-profile-new-00: */
3098 /* "Applications may use any of the SDES items described in the */
3099 /* RTP specification. While CNAME information is sent every */
3100 /* reporting interval, other items should be sent only every third */
3101 /* reporting interval, with NAME sent seven out of eight times */
3102 /* within that slot and the remaining SDES items cyclically taking */
3103 /* up the eighth slot, as defined in Section 6.2.2 of the RTP */
3104 /* specification. In other words, NAME is sent in RTCP packets 1, */
3105 /* 4, 7, 10, 13, 16, 19, while, say, EMAIL is used in RTCP packet */
3106 /* 22". */
3107 uint8_t *packet = buffer;
3108 rtcp_common *common = (rtcp_common *)(void *) buffer;
3109 const char *item;
3110 size_t remaining_len;
3111 int pad;
3112
3113 assert(buflen > (int)sizeof(rtcp_common));
3114
3115 common->version = 2;
3116 common->p = 0;
3117 common->count = 1;
3118 common->pt = RTCP_SDES;
3119 common->length = 0;
3120 packet += sizeof(rtcp_common);
3121
3122 *((uint32_t *)(void *) packet) = htonl(ssrc);
3123 packet += 4;
3124
3125 remaining_len = buflen - (packet - buffer);
3126 item = rtp_get_sdes(session, ssrc, RTCP_SDES_CNAME);
3127 if ((item != NULL) && ((strlen(item) + (size_t) 2) <= remaining_len)) {
3128 packet +=
3129 add_sdes_item(packet, remaining_len, RTCP_SDES_CNAME, item);
3130 }
3131
3132 remaining_len = buflen - (packet - buffer);
3133 item = rtp_get_sdes(session, ssrc, RTCP_SDES_NOTE);
3134 if ((item != NULL) && ((strlen(item) + (size_t) 2) <= remaining_len)) {
3135 packet +=
3136 add_sdes_item(packet, remaining_len, RTCP_SDES_NOTE, item);
3137 }
3138
3139 remaining_len = buflen - (packet - buffer);
3140 if ((session->sdes_count_pri % 3) == 0) {
3141 session->sdes_count_sec++;
3142 if ((session->sdes_count_sec % 8) == 0) {
3143 /* Note that the following is supposed to fall-through the cases */
3144 /* until one is found to send... The lack of break statements in */
3145 /* the switch is not a bug. */
3146 switch (session->sdes_count_ter % 5) {
3147 case 0:
3148 item =
3149 rtp_get_sdes(session, ssrc, RTCP_SDES_TOOL);
3150 if ((item != NULL)
3151 && ((strlen(item) + (size_t) 2) <=
3152 remaining_len)) {
3153 packet +=
3154 add_sdes_item(packet, remaining_len,
3156 break;
3157 }
3158 /* fall through */
3159 case 1:
3160 item =
3161 rtp_get_sdes(session, ssrc,
3163 if ((item != NULL)
3164 && ((strlen(item) + (size_t) 2) <=
3165 remaining_len)) {
3166 packet +=
3167 add_sdes_item(packet, remaining_len,
3169 item);
3170 break;
3171 }
3172 /* fall through */
3173 case 2:
3174 item =
3175 rtp_get_sdes(session, ssrc,
3177 if ((item != NULL)
3178 && ((strlen(item) + (size_t) 2) <=
3179 remaining_len)) {
3180 packet +=
3181 add_sdes_item(packet, remaining_len,
3183 item);
3184 break;
3185 }
3186 /* fall through */
3187 case 3:
3188 item =
3189 rtp_get_sdes(session, ssrc, RTCP_SDES_LOC);
3190 if ((item != NULL)
3191 && ((strlen(item) + (size_t) 2) <=
3192 remaining_len)) {
3193 packet +=
3194 add_sdes_item(packet, remaining_len,
3196 break;
3197 }
3198 /* fall through */
3199 case 4:
3200 item =
3201 rtp_get_sdes(session, ssrc, RTCP_SDES_PRIV);
3202 if ((item != NULL)
3203 && ((strlen(item) + (size_t) 2) <=
3204 remaining_len)) {
3205 packet +=
3206 add_sdes_item(packet, remaining_len,
3208 break;
3209 }
3210 }
3211 session->sdes_count_ter++;
3212 } else {
3213 item = rtp_get_sdes(session, ssrc, RTCP_SDES_NAME);
3214 if (item != NULL) {
3215 packet +=
3216 add_sdes_item(packet, remaining_len,
3218 }
3219 }
3220 }
3221 session->sdes_count_pri++;
3222
3223 /* Pad to a multiple of 4 bytes... */
3224 pad = 4 - ((packet - buffer) & 0x3);
3225 while (pad--) {
3226 *packet++ = RTCP_SDES_END;
3227 }
3228
3229 common->length = htons((uint16_t) (((int)(packet - buffer) / 4) - 1));
3230
3231 return packet;
3232}
static int add_sdes_item(uint8_t *buf, int buflen, int type, const char *val)
Definition rtp.c:3075
const char * rtp_get_sdes(struct rtp *session, uint32_t ssrc, rtcp_sdes_type type)
Definition rtp.c:2631
#define RTCP_SDES
Definition rtp.c:140
@ RTCP_SDES_NOTE
Definition rtp.h:216
@ RTCP_SDES_CNAME
Definition rtp.h:210
@ RTCP_SDES_PHONE
Definition rtp.h:213
@ RTCP_SDES_TOOL
Definition rtp.h:215
@ RTCP_SDES_LOC
Definition rtp.h:214
@ RTCP_SDES_EMAIL
Definition rtp.h:212
@ RTCP_SDES_END
Definition rtp.h:209
@ RTCP_SDES_NAME
Definition rtp.h:211
@ RTCP_SDES_PRIV
Definition rtp.h:217
Definition hd-rum.c:27
int sdes_count_sec
Definition rtp.c:304
int sdes_count_pri
Definition rtp.c:303
int sdes_count_ter
Definition rtp.c:305

References add_sdes_item(), rtcp_common::count, rtcp_common::length, rtcp_common::p, rtcp_common::pt, RTCP_SDES, RTCP_SDES_CNAME, RTCP_SDES_EMAIL, RTCP_SDES_END, RTCP_SDES_LOC, RTCP_SDES_NAME, RTCP_SDES_NOTE, RTCP_SDES_PHONE, RTCP_SDES_PRIV, RTCP_SDES_TOOL, rtp_get_sdes(), rtp::sdes_count_pri, rtp::sdes_count_sec, rtp::sdes_count_ter, and rtcp_common::version.

Referenced by send_rtcp().

Here is the call graph for this function:

◆ format_rtcp_sr()

static uint8_t * format_rtcp_sr ( uint8_t * buffer,
int buflen,
struct rtp * session,
uint32_t rtp_ts )
static

Definition at line 3012 of file rtp.c.

3014{
3015 /* Write an RTCP SR into buffer, returning a pointer to */
3016 /* the next byte after the header we have just written. */
3017 rtcp_t *packet = (rtcp_t *)(void *) buffer;
3018 int remaining_length;
3019 uint32_t ntp_sec, ntp_frac;
3020
3021 assert(buflen >= 28); /* ...else there isn't space for the header and sender report */
3022
3023 packet->common.version = 2;
3024 packet->common.p = 0;
3025 packet->common.count = 0;
3026 packet->common.pt = RTCP_SR;
3027 packet->common.length = htons(1);
3028
3029 ntp64_time(&ntp_sec, &ntp_frac);
3030
3031 packet->r.sr.sr.ssrc = htonl(rtp_my_ssrc(session));
3032 packet->r.sr.sr.ntp_sec = htonl(ntp_sec);
3033 packet->r.sr.sr.ntp_frac = htonl(ntp_frac);
3034 packet->r.sr.sr.rtp_ts = htonl(rtp_ts);
3035 packet->r.sr.sr.sender_pcount = htonl(session->rtp_pcount);
3036 packet->r.sr.sr.sender_bcount = htonl(session->rtp_bcount);
3037
3038 /* Add report blocks, until we either run out of senders */
3039 /* to report upon or we run out of space in the buffer. */
3040 remaining_length = buflen - 28;
3041 packet->common.count =
3042 format_report_blocks(packet->r.sr.rr, remaining_length, session);
3043 packet->common.length =
3044 htons((uint16_t) (6 + (packet->common.count * 6)));
3045 return buffer + 28 + (24 * packet->common.count);
3046}
#define RTCP_SR
Definition rtp.c:138
uint32_t sender_pcount
Definition rtp.h:135
uint32_t sender_bcount
Definition rtp.h:136
uint32_t rtp_ts
Definition rtp.h:134
rtcp_sr sr
Definition rtp.c:164
uint32_t rtp_pcount
Definition rtp.c:307
uint32_t rtp_bcount
Definition rtp.c:308

References rtcp_t::common, rtcp_common::count, format_report_blocks(), rtcp_common::length, ntp64_time(), rtcp_sr::ntp_frac, rtcp_sr::ntp_sec, rtcp_common::p, rtcp_common::pt, rtcp_t::r, RTCP_SR, rtp::rtp_bcount, rtp_my_ssrc(), rtp::rtp_pcount, rtcp_sr::rtp_ts, rtcp_sr::sender_bcount, rtcp_sr::sender_pcount, rtcp_t::sr, rtcp_sr::ssrc, and rtcp_common::version.

Referenced by send_rtcp().

Here is the call graph for this function:

◆ get_cname()

static char * get_cname ( socket_udp * s)
static

Definition at line 907 of file rtp.c.

908{
909 /* Set the CNAME. This is "user@hostname" or just "hostname" if the username cannot be found. */
910 char *hname;
911 char *uname;
912 char *cname;
913#ifndef _WIN32
914 struct passwd *pwent;
915#else
916 char *name;
917 DWORD namelen;
918#endif
919
920 cname = (char *)malloc(MAXCNAMELEN + 1);
921 cname[0] = '\0';
922
923 /* First, fill in the username... */
924#ifdef _WIN32
925 name = NULL;
926 namelen = 0;
927 GetUserName(NULL, &namelen);
928 if (namelen > 0) {
929 name = (char *)malloc(namelen + 1);
930 GetUserName(name, &namelen);
931 } else {
932 uname = getenv("USER");
933 if (uname != NULL) {
934 name = strdup(uname);
935 }
936 }
937 if (name != NULL) {
938 strncpy(cname, name, MAXCNAMELEN - 1);
939 strcat(cname, "@");
940 free(name);
941 }
942#else
943 uname = NULL;
944 pwent = getpwuid(getuid());
945 if (pwent != NULL) {
946 uname = pwent->pw_name;
947 }
948 if (uname != NULL) {
949 strncpy(cname, uname, MAXCNAMELEN - 1);
950 strcat(cname, "@"); // NOLINT(clang-analyzer-security.insecureAPI.strcpy)
951 }
952#endif
953
954 /* Now the hostname. Must be dotted-quad IP address. */
955 hname = udp_host_addr(s);
956 if (hname == NULL) {
957 /* If we can't get our IP address we use the loopback address... */
958 /* This is horrible, but it stops the code from failing. */
959 hname = strdup("127.0.0.1");
960 }
961 strncpy(cname + strlen(cname), hname, MAXCNAMELEN - strlen(cname));
962 free(hname);
963 return cname;
964}
char * udp_host_addr(socket_udp *s)
Definition net_udp.c:1367
#define MAXCNAMELEN
Definition rtp.c:905
const char * name
Definition settings.cpp:193

References MAXCNAMELEN, name, and udp_host_addr().

Referenced by rtp_init_if(), and rtp_init_with_udp_socket().

Here is the call graph for this function:

◆ get_rr()

static const rtcp_rr * get_rr ( struct rtp * session,
uint32_t reporter_ssrc,
uint32_t reportee_ssrc )
static

Definition at line 512 of file rtp.c.

514{
515 rtcp_rr_wrapper *cur, *start;
516
517 start =
518 &session->rr[ssrc_hash(reporter_ssrc)][ssrc_hash(reportee_ssrc)];
519 cur = start->next;
520 while (cur != start) {
521 if (cur->reporter_ssrc == reporter_ssrc &&
522 cur->rr->ssrc == reportee_ssrc) {
523 return cur->rr;
524 }
525 cur = cur->next;
526 }
527 return NULL;
528}
static void start()
Definition sdp.c:202
uint32_t reporter_ssrc
Definition rtp.c:195
struct _rtcp_rr_wrapper * next
Definition rtp.c:193
rtcp_rr * rr
Definition rtp.c:196
rtcp_rr_wrapper rr[RTP_DB_SIZE][RTP_DB_SIZE]
Definition rtp.c:283

References _rtcp_rr_wrapper::next, _rtcp_rr_wrapper::reporter_ssrc, _rtcp_rr_wrapper::rr, rtp::rr, rtcp_rr::ssrc, ssrc_hash(), and start().

Referenced by rtp_get_rr().

Here is the call graph for this function:

◆ get_source()

static source * get_source ( struct rtp * session,
uint32_t ssrc )
inlinestatic

Definition at line 596 of file rtp.c.

597{
598 source *s;
599
600 check_database(session);
601 for (s = session->db[ssrc_hash(ssrc)]; s != NULL; s = s->next) {
602 if (s->ssrc == ssrc) {
603 check_source(s);
604 return s;
605 }
606 }
607 return NULL;
608}

References check_database(), check_source(), rtp::db, _source::next, _source::ssrc, and ssrc_hash().

Referenced by create_source(), delete_source(), process_rtcp_app(), process_rtcp_bye(), rtp_add_csrc(), rtp_del_csrc(), rtp_get_sdes(), rtp_get_sr(), rtp_process_data(), and rtp_set_sdes().

Here is the call graph for this function:

◆ init_opt()

static void init_opt ( struct rtp * session)
static

Definition at line 966 of file rtp.c.

967{
968 /* Default option settings. */
975}
bool rtp_set_option(struct rtp *session, rtp_option optname, int optval)
Definition rtp.c:1308
@ RTP_OPT_REUSE_PACKET_BUFS
Definition rtp.h:231
@ RTP_OPT_FILTER_MY_PACKETS
Definition rtp.h:230
@ RTP_OPT_PROMISC
Definition rtp.h:228
@ RTP_OPT_WEAK_VALIDATION
Definition rtp.h:229
@ RTP_OPT_SEND_BACK
Definition rtp.h:236
@ RTP_OPT_RECORD_SOURCE
Definition rtp.h:234

References FALSE, RTP_OPT_FILTER_MY_PACKETS, RTP_OPT_PROMISC, RTP_OPT_RECORD_SOURCE, RTP_OPT_REUSE_PACKET_BUFS, RTP_OPT_SEND_BACK, RTP_OPT_WEAK_VALIDATION, and rtp_set_option().

Referenced by rtp_init_if(), and rtp_init_with_udp_socket().

Here is the call graph for this function:

◆ init_seq()

static void init_seq ( source * s,
uint16_t seq )
inlinestatic

Definition at line 765 of file rtp.c.

766{
767 /* Taken from draft-ietf-avt-rtp-new-01.txt */
768 check_source(s);
769 s->base_seq = seq;
770 s->max_seq = seq;
771 s->bad_seq = RTP_SEQ_MOD + 1;
772 s->cycles = 0;
773 s->received = 0;
774 s->received_prior = 0;
775 s->expected_prior = 0;
776}
#define RTP_SEQ_MOD
Definition rtp.c:133
uint32_t bad_seq
Definition rtp.c:227
uint32_t seq
Definition tfrc.c:100

References _source::bad_seq, _source::base_seq, check_source(), _source::cycles, _source::expected_prior, _source::max_seq, _source::received, _source::received_prior, RTP_SEQ_MOD, and seq.

Referenced by update_seq().

Here is the call graph for this function:

◆ insert_rr()

static void insert_rr ( struct rtp * session,
uint32_t reporter_ssrc,
rtcp_rr * rr,
rtcp_rx * rx )
static

Definition at line 386 of file rtp.c.

388{
389 /* Insert the reception report into the receiver report */
390 /* database. This database is a two dimensional table of */
391 /* rr_wrappers indexed by hashes of reporter_ssrc and */
392 /* reportee_src. The rr_wrappers in the database are */
393 /* sentinels to reduce conditions in list operations. */
394 /* The ts is used to determine when to timeout this rr. */
395
396 rtcp_rr_wrapper *cur, *start;
397
398 start = &session->rr[ssrc_hash(reporter_ssrc)][ssrc_hash(rr->ssrc)];
399 cur = start->next;
400
401 while (cur != start) {
402 if (cur->reporter_ssrc == reporter_ssrc
403 && cur->rr->ssrc == rr->ssrc) {
404 /* Replace existing entry in the database */
405 free(cur->rr);
406 if (cur->rx)
407 free(cur->rx);
408 cur->rr = rr;
409 cur->rx = rx;
410 cur->ts = get_time_in_ns();
411 return;
412 }
413 cur = cur->next;
414 }
415
416 /* No entry in the database so create one now. */
417 cur = (rtcp_rr_wrapper *) malloc(sizeof(rtcp_rr_wrapper));
418 cur->reporter_ssrc = reporter_ssrc;
419 cur->rr = rr;
420 cur->rx = rx;
421 cur->ts = get_time_in_ns();
422 /* Fix links */
423 cur->next = start->next;
424 cur->next->prev = cur;
425 cur->prev = start;
426 cur->prev->next = cur;
427
428 debug_msg("Created new rr entry for 0x%08" PRIx32 " from source 0x%08" PRIx32 "\n",
429 rr->ssrc, reporter_ssrc);
430}
rtcp_rx * rx
Definition rtp.c:197
struct _rtcp_rr_wrapper * prev
Definition rtp.c:194
time_ns_t ts
Definition rtp.c:198

References debug_msg, get_time_in_ns(), _rtcp_rr_wrapper::next, _rtcp_rr_wrapper::prev, _rtcp_rr_wrapper::reporter_ssrc, _rtcp_rr_wrapper::rr, rtp::rr, _rtcp_rr_wrapper::rx, rtcp_rr::ssrc, ssrc_hash(), start(), and _rtcp_rr_wrapper::ts.

Referenced by process_report_blocks().

Here is the call graph for this function:

◆ next_csrc()

static uint32_t next_csrc ( struct rtp * session)
static

Definition at line 344 of file rtp.c.

345{
346 int cc = 0;
347 for (int chain = 0; chain < RTP_DB_SIZE; chain++) {
348 /* Check that the linked lists making up the chains in */
349 /* the hash table are correctly linked together... */
350 for (source *s = session->db[chain]; s != NULL; s = s->next) {
351 if (!s->should_advertise_sdes)
352 continue;
353
354 if (cc != session->last_advertised_csrc) {
355 cc++;
356 continue;
357 }
358
359 session->last_advertised_csrc++;
360 if (session->last_advertised_csrc == session->csrc_count) {
361 session->last_advertised_csrc = 0;
362 }
363 /* This returns each source marked "should_advertise_sdes" in turn. */
364 return s->ssrc;
365 }
366 }
367 /* We should never get here... */
368 abort();
369}

References rtp::csrc_count, rtp::db, rtp::last_advertised_csrc, _source::next, and RTP_DB_SIZE.

Referenced by send_rtcp().

◆ process_report_blocks()

static void process_report_blocks ( struct rtp * session,
rtcp_t * packet,
uint32_t ssrc,
rtcp_rr * rrp,
rtcp_rx * rrx )
static

Definition at line 1846 of file rtp.c.

1848{
1849 int i;
1850 rtp_event event;
1851 rtcp_rr *rr;
1852 rtcp_rx *rx = NULL;
1853
1854 /* ...process RRs... */
1855 if (packet->common.count == 0) {
1856 if (!filter_event(session, ssrc)) {
1857 event.ssrc = ssrc;
1858 event.type = RX_RR_EMPTY;
1859 event.data = NULL;
1860 session->callback(session, &event);
1861 }
1862 } else {
1863 for (i = 0; i < packet->common.count; i++, rrp++) {
1864 rr = (rtcp_rr *) malloc(sizeof(rtcp_rr));
1865 rr->ssrc = ntohl(rrp->ssrc);
1866 rr->fract_lost = rrp->fract_lost; /* Endian conversion handled in the */
1867 rr->total_lost = rrp->total_lost; /* definition of the rtcp_rr type. */
1868 rr->last_seq = ntohl(rrp->last_seq);
1869 rr->jitter = ntohl(rrp->jitter);
1870 rr->lsr = ntohl(rrp->lsr);
1871 rr->dlsr = ntohl(rrp->dlsr);
1872
1873 if (rrx) {
1874 rx = (rtcp_rx *) malloc(sizeof(rtcp_rx));
1875 rx->ts = ntohl(rrx->ts);
1876 rx->tdelay = ntohl(rrx->tdelay);
1877 rx->x_recv = ntohl(rrx->x_recv);
1878 rx->p = ntohl(rrx->p);
1879 }
1880
1881 /* Create a database entry for this SSRC, if one doesn't already exist... */
1882 create_source(session, rr->ssrc, FALSE);
1883
1884 /* Call the event handler... */
1885 if (!filter_event(session, ssrc)) {
1886 event.ssrc = ssrc;
1887 event.type = RX_RR;
1888 event.data = (void *)rr;
1889 session->callback(session, &event);
1890 }
1891
1892 /* Store the RR for later use... */
1893 insert_rr(session, ssrc, rr, rx);
1894 }
1895 }
1896}
static void insert_rr(struct rtp *session, uint32_t reporter_ssrc, rtcp_rr *rr, rtcp_rx *rx)
Definition rtp.c:386
static source * create_source(struct rtp *session, uint32_t ssrc, int probation)
Definition rtp.c:660
@ RX_RR_EMPTY
Definition rtp.h:189
@ RX_RR
Definition rtp.h:183
Definition rtp.h:139
Definition rtp.h:154
uint32_t p
Definition rtp.h:158
uint32_t tdelay
Definition rtp.h:156
uint32_t ts
Definition rtp.h:155
uint32_t x_recv
Definition rtp.h:157

References rtp::callback, rtcp_t::common, rtcp_common::count, create_source(), rtcp_rr::dlsr, FALSE, filter_event(), rtcp_rr::fract_lost, insert_rr(), rtcp_rr::jitter, rtcp_rr::last_seq, rtcp_rr::lsr, rtcp_rx::p, RX_RR, RX_RR_EMPTY, rtcp_rr::ssrc, rtcp_rx::tdelay, rtcp_rr::total_lost, rtcp_rx::ts, and rtcp_rx::x_recv.

Referenced by process_rtcp_rr(), process_rtcp_rx(), and process_rtcp_sr().

Here is the call graph for this function:

◆ process_rtcp_app()

static void process_rtcp_app ( struct rtp * session,
rtcp_t * packet )
static

Definition at line 2074 of file rtp.c.

2075{
2076 uint32_t ssrc;
2077 rtp_event event;
2078 rtcp_app *app;
2079 source *s;
2080 int data_len;
2081
2082 /* Update the database for this source. */
2083 ssrc = ntohl(packet->r.app.ssrc);
2084 create_source(session, ssrc, FALSE);
2085 s = get_source(session, ssrc);
2086 if (s == NULL) {
2087 /* This should only occur in the event of database malfunction. */
2088 debug_msg("Source 0x%08x invalid, skipping...\n", ssrc);
2089 return;
2090 }
2091 check_source(s);
2092
2093 /* Copy the entire packet, converting the header (only) into host byte order. */
2094 app = (rtcp_app *) malloc(RTP_MAX_PACKET_LEN);
2095 app->version = packet->common.version;
2096 app->p = packet->common.p;
2097 app->subtype = packet->common.count;
2098 app->pt = packet->common.pt;
2099 app->length = ntohs(packet->common.length);
2100 app->ssrc = ssrc;
2101 app->name[0] = packet->r.app.name[0];
2102 app->name[1] = packet->r.app.name[1];
2103 app->name[2] = packet->r.app.name[2];
2104 app->name[3] = packet->r.app.name[3];
2105 data_len = (app->length - 2) * 4;
2106 memcpy(app->data, packet->r.app.data, data_len);
2107
2108 /* Callback to the application to process the app packet... */
2109 if (!filter_event(session, ssrc)) {
2110 event.ssrc = ssrc;
2111 event.type = RX_APP;
2112 event.data = (void *)app; /* The callback function MUST free this! */
2113 session->callback(session, &event);
2114 } else {
2115 free(app);
2116 }
2117}
@ RX_APP
Definition rtp.h:193
#define RTP_MAX_PACKET_LEN
Definition rtp.h:61
uint8_t data[1]
Definition rtp.c:187
struct rtcp_t::@32::@37 app
uint32_t ssrc
Definition rtp.c:168
uint8_t name[4]
Definition rtp.c:186

References app, rtcp_t::app, rtp::callback, check_source(), rtcp_t::common, rtcp_common::count, create_source(), rtcp_t::data, debug_msg, FALSE, filter_event(), get_source(), rtcp_common::length, rtcp_t::name, rtcp_common::p, rtcp_common::pt, rtcp_t::r, RTP_MAX_PACKET_LEN, RX_APP, rtcp_t::ssrc, and rtcp_common::version.

Referenced by rtp_process_ctrl().

Here is the call graph for this function:

◆ process_rtcp_bye()

static void process_rtcp_bye ( struct rtp * session,
rtcp_t * packet )
static

Definition at line 2045 of file rtp.c.

2046{
2047 int i;
2048 uint32_t ssrc;
2049 rtp_event event;
2050 source *s;
2051
2052 for (i = 0; i < packet->common.count; i++) {
2053 ssrc = ntohl(packet->r.bye.ssrc[i]);
2054 /* This is kind-of strange, since we create a source we are about to delete. */
2055 /* This is done to ensure that the source mentioned in the event which is */
2056 /* passed to the user of the RTP library is valid, and simplify client code. */
2057 create_source(session, ssrc, FALSE);
2058 /* Call the event handler... */
2059 if (!filter_event(session, ssrc)) {
2060 event.ssrc = ssrc;
2061 event.type = RX_BYE;
2062 event.data = NULL;
2063 session->callback(session, &event);
2064 }
2065 /* Mark the source as ready for deletion. Sources are not deleted immediately */
2066 /* since some packets may be delayed and arrive after the BYE... */
2067 s = get_source(session, ssrc);
2068 s->got_bye = TRUE;
2069 check_source(s);
2070 session->bye_count++;
2071 }
2072}
@ RX_BYE
Definition rtp.h:186
int got_bye
Definition rtp.c:224
struct rtcp_t::@32::@36 bye
int bye_count
Definition rtp.c:288

References rtcp_t::bye, rtp::bye_count, rtp::callback, check_source(), rtcp_t::common, rtcp_common::count, create_source(), FALSE, filter_event(), get_source(), _source::got_bye, rtcp_t::r, RX_BYE, rtcp_t::ssrc, and TRUE.

Referenced by rtp_process_ctrl().

Here is the call graph for this function:

◆ process_rtcp_rr()

static void process_rtcp_rr ( struct rtp * session,
rtcp_t * packet )
static

Definition at line 1948 of file rtp.c.

1949{
1950 uint32_t ssrc;
1951 source *s;
1952
1953 ssrc = ntohl(packet->r.rr.ssrc);
1954 s = create_source(session, ssrc, FALSE);
1955 if (s == NULL) {
1956 debug_msg("Source 0x%08x invalid, skipping...\n", ssrc);
1957 return;
1958 }
1959
1960 process_report_blocks(session, packet, ssrc, packet->r.rr.rr, NULL);
1961
1962 if (((packet->common.count * 6) + 1) < ntohs(packet->common.length)) {
1963 debug_msg("Profile specific RR extension ignored\n");
1964 }
1965}
static void process_report_blocks(struct rtp *session, rtcp_t *packet, uint32_t ssrc, rtcp_rr *rrp, rtcp_rx *rrx)
Definition rtp.c:1846

References rtcp_t::common, rtcp_common::count, create_source(), debug_msg, FALSE, rtcp_common::length, process_report_blocks(), rtcp_t::r, rtcp_t::rr, and rtcp_rr::ssrc.

Referenced by rtp_process_ctrl().

Here is the call graph for this function:

◆ process_rtcp_rx()

static void process_rtcp_rx ( struct rtp * session,
rtcp_t * packet )
static

Definition at line 1967 of file rtp.c.

1968{
1969 uint32_t ssrc;
1970 source *s;
1971
1972 ssrc = ntohl(packet->r.rx.ssrc);
1973 s = create_source(session, ssrc, FALSE);
1974 if (s == NULL) {
1975 debug_msg("Source 0x%08x invalid, skipping...\n", ssrc);
1976 return;
1977 }
1978
1979 process_report_blocks(session, packet, ssrc, packet->r.rx.rr,
1980 packet->r.rx.rx);
1981
1982 if (((packet->common.count * 6) + 1) < ntohs(packet->common.length)) {
1983 debug_msg("Profile specific RR/RX extension ignored\n");
1984 }
1985}
rtcp_rx rx[1]
Definition rtp.c:174

References rtcp_t::common, rtcp_common::count, create_source(), debug_msg, FALSE, rtcp_common::length, process_report_blocks(), rtcp_t::r, and rtcp_t::rx.

Referenced by rtp_process_ctrl().

Here is the call graph for this function:

◆ process_rtcp_sdes()

static void process_rtcp_sdes ( struct rtp * session,
rtcp_t * packet )
static

Definition at line 1987 of file rtp.c.

1988{
1989 int count = packet->common.count;
1990 struct rtcp_sdes_t *sd = &packet->r.sdes;
1991 rtcp_sdes_item *rsp;
1992 rtcp_sdes_item *rspn;
1993 rtcp_sdes_item *end =
1994 (rtcp_sdes_item *) ((uint32_t *) packet + packet->common.length +
1995 1);
1996 source *s;
1997 rtp_event event;
1998
1999 while (--count >= 0) {
2000 rsp = &sd->item[0];
2001 if (rsp >= end) {
2002 break;
2003 }
2004 sd->ssrc = ntohl(sd->ssrc);
2005 s = create_source(session, sd->ssrc, FALSE);
2006 if (s == NULL) {
2007 debug_msg
2008 ("Can't get valid source entry for 0x%08x, skipping...\n",
2009 sd->ssrc);
2010 } else {
2011 for (; rsp->type; rsp = rspn) {
2012 rspn =
2013 (rtcp_sdes_item *) ((char *)rsp +
2014 rsp->length + 2);
2015 if (rspn >= end) {
2016 rsp = rspn;
2017 break;
2018 }
2019 if (rtp_set_sdes
2020 (session, sd->ssrc, rsp->type, rsp->data,
2021 rsp->length)) {
2022 if (!filter_event(session, sd->ssrc)) {
2023 event.ssrc = sd->ssrc;
2024 event.type = RX_SDES;
2025 event.data = (void *)rsp;
2026 session->callback(session,
2027 &event);
2028 }
2029 } else {
2030 debug_msg
2031 ("Invalid sdes item for source 0x%08x, skipping...\n",
2032 sd->ssrc);
2033 }
2034 }
2035 }
2036 sd = (struct rtcp_sdes_t *)((uint32_t *) sd +
2037 (((char *)rsp - (char *)sd) >> 2) +
2038 1);
2039 }
2040 if (count >= 0) {
2041 debug_msg("Invalid RTCP SDES packet, some items ignored.\n");
2042 }
2043}
int count
Definition hd-rum.c:44
bool rtp_set_sdes(struct rtp *session, uint32_t ssrc, rtcp_sdes_type type, const char *value, int length)
Definition rtp.c:2546
@ RX_SDES
Definition rtp.h:185
struct rtcp_t::@32::rtcp_sdes_t sdes

References rtp::callback, rtcp_t::common, count, rtcp_common::count, create_source(), rtcp_sdes_item::data, debug_msg, FALSE, filter_event(), rtcp_common::length, rtcp_sdes_item::length, rtcp_t::r, rtp_set_sdes(), RX_SDES, rtcp_t::sdes, and rtcp_sdes_item::type.

Referenced by rtp_process_ctrl().

Here is the call graph for this function:

◆ process_rtcp_sr()

static void process_rtcp_sr ( struct rtp * session,
rtcp_t * packet )
static

Definition at line 1898 of file rtp.c.

1899{
1900 uint32_t ssrc;
1901 rtp_event event;
1902 rtcp_sr * _Atomic sr;
1903 source *s;
1904
1905 ssrc = ntohl(packet->r.sr.sr.ssrc);
1906 s = create_source(session, ssrc, FALSE);
1907 if (s == NULL) {
1908 debug_msg("Source 0x%08x invalid, skipping...\n", ssrc);
1909 return;
1910 }
1911
1912 /* Mark as an active sender, if we get a sender report... */
1913 if (s->sender == FALSE) {
1914 s->sender = TRUE;
1915 session->sender_count++;
1916 }
1917
1918 /* Process the SR... */
1919 sr = malloc(sizeof(rtcp_sr));
1920 sr->ssrc = ssrc;
1921 sr->ntp_sec = ntohl(packet->r.sr.sr.ntp_sec);
1922 sr->ntp_frac = ntohl(packet->r.sr.sr.ntp_frac);
1923 sr->rtp_ts = ntohl(packet->r.sr.sr.rtp_ts);
1924 sr->sender_pcount = ntohl(packet->r.sr.sr.sender_pcount);
1925 sr->sender_bcount = ntohl(packet->r.sr.sr.sender_bcount);
1926
1927 /* Store the SR for later retrieval... */
1928 sr = atomic_exchange(&s->sr, sr);
1929 free(sr);
1931
1932 /* Call the event handler... */
1933 if (!filter_event(session, ssrc)) {
1934 event.ssrc = ssrc;
1935 event.type = RX_SR;
1936 event.data = (void *)s->sr;
1937 session->callback(session, &event);
1938 }
1939
1940 process_report_blocks(session, packet, ssrc, packet->r.sr.rr, NULL);
1941
1942 if (((packet->common.count * 6) + 1) <
1943 (ntohs(packet->common.length) - 5)) {
1944 debug_msg("Profile specific SR extension ignored\n");
1945 }
1946}
@ RX_SR
Definition rtp.h:182
Definition rtp.h:130

References rtp::callback, rtcp_t::common, rtcp_common::count, create_source(), debug_msg, FALSE, filter_event(), _source::last_sr_frac, _source::last_sr_sec, rtcp_common::length, ntp64_time(), rtcp_sr::ntp_frac, rtcp_sr::ntp_sec, process_report_blocks(), rtcp_t::r, rtcp_sr::rtp_ts, RX_SR, _source::sender, rtcp_sr::sender_bcount, rtp::sender_count, rtcp_sr::sender_pcount, _source::sr, rtcp_t::sr, rtcp_sr::ssrc, and TRUE.

Referenced by rtp_process_ctrl().

Here is the call graph for this function:

◆ process_rtp()

static void process_rtp ( struct rtp * session,
uint32_t curr_rtp_ts,
rtp_packet * packet,
source * s )
static

Definition at line 1474 of file rtp.c.

1476{
1477 int i, d, transit;
1478 rtp_event event;
1479
1480 if (packet->cc > 0) {
1481 for (i = 0; i < packet->cc; i++) {
1482 create_source(session, packet->csrc[i], FALSE);
1483 }
1484 }
1485 /* Update the source database... */
1486 if (s->sender == FALSE) {
1487 s->sender = TRUE;
1488 session->sender_count++;
1489 }
1490
1491 if (session->tfrc_on)
1492 compute_loss_intervals(session, packet);
1493
1494 transit = curr_rtp_ts - packet->ts;
1495 d = transit - s->transit;
1496 s->transit = transit;
1497 if (d < 0) {
1498 d = -d;
1499 }
1500 s->jitter += d - ((s->jitter + 8) / 16);
1501
1502 /* Callback to the application to process the packet... */
1503 if (!filter_event(session, packet->ssrc)) {
1504 event.ssrc = packet->ssrc;
1505 event.type = RX_RTP;
1506
1507 // printf("This packet is going to have size %d\n",sizeof(packet));
1508 event.data = (void *)packet; /* The callback function MUST free this! */
1509 session->callback(session, &event);
1510 }
1511}
static void compute_loss_intervals(struct rtp *session, rtp_packet *packet)
Definition rtp.c:1466
@ RX_RTP
Definition rtp.h:180
uint32_t transit
Definition rtp.c:234
int tfrc_on
Definition rtp.c:310

References rtp::callback, compute_loss_intervals(), create_source(), FALSE, filter_event(), _source::jitter, RX_RTP, _source::sender, rtp::sender_count, rtp::tfrc_on, _source::transit, and TRUE.

Referenced by rtp_process_data().

Here is the call graph for this function:

◆ really_create_source()

static source * really_create_source ( struct rtp * session,
uint32_t ssrc,
int probation,
source * s )
static

Definition at line 610 of file rtp.c.

612{
613 /* Create a new source entry, and add it to the database. */
614 /* The database is a hash table, using the separate chaining */
615 /* algorithm. */
616 rtp_event event;
617 int h;
618
619 check_database(session);
620 /* This is a new source, we have to create it... */
621 h = ssrc_hash(ssrc);
622 s = (source *) malloc(sizeof(source));
623 memset(s, 0, sizeof(source));
624 s->magic = 0xc001feed;
625 s->next = session->db[h];
626 s->ssrc = ssrc;
627 if (probation) {
628 /* This is a probationary source, which only counts as */
629 /* valid once several consecutive packets are received */
630 s->probation = -1;
631 } else {
632 s->probation = 0;
633 }
634
636 /* Now, add it to the database... */
637 if (session->db[h] != NULL) {
638 session->db[h]->prev = s;
639 }
640 session->db[ssrc_hash(ssrc)] = s;
641 session->ssrc_count++;
642 check_database(session);
643
644 debug_msg("Created database entry 0x%08x (%d sources)\n", ssrc,
645 session->ssrc_count);
646 if (ssrc != session->my_ssrc) {
647 /* Do not send during rtp_init since application cannot map the address */
648 /* of the rtp session to anything since rtp_init has not returned yet. */
649 if (!filter_event(session, ssrc)) {
650 event.ssrc = ssrc;
651 event.type = SOURCE_CREATED;
652 event.data = NULL;
653 session->callback(session, &event);
654 }
655 }
656
657 return s;
658}
@ SOURCE_CREATED
Definition rtp.h:187
int probation
Definition rtp.c:232

References rtp::callback, check_database(), rtp::db, debug_msg, filter_event(), get_time_in_ns(), _source::last_active, _source::magic, rtp::my_ssrc, _source::next, _source::prev, _source::probation, SOURCE_CREATED, _source::ssrc, rtp::ssrc_count, and ssrc_hash().

Referenced by create_source().

Here is the call graph for this function:

◆ remove_rr()

static void remove_rr ( struct rtp * session,
uint32_t ssrc )
static

Definition at line 432 of file rtp.c.

433{
434 /* Remove any RRs from "s" which refer to "ssrc" as either */
435 /* reporter or reportee. */
436 rtcp_rr_wrapper *start, *cur, *tmp;
437 int i;
438
439 /* Remove rows, i.e. ssrc == reporter_ssrc */
440 for (i = 0; i < RTP_DB_SIZE; i++) {
441 start = &session->rr[ssrc_hash(ssrc)][i];
442 cur = start->next;
443 while (cur != start) {
444 if (cur->reporter_ssrc == ssrc) {
445 tmp = cur;
446 cur = cur->prev;
447 tmp->prev->next = tmp->next;
448 tmp->next->prev = tmp->prev;
449 free(tmp->rr);
450 free(tmp);
451 }
452 cur = cur->next;
453 }
454 }
455
456 /* Remove columns, i.e. ssrc == reporter_ssrc */
457 for (i = 0; i < RTP_DB_SIZE; i++) {
458 start = &session->rr[i][ssrc_hash(ssrc)];
459 cur = start->next;
460 while (cur != start) {
461 if (cur->rr->ssrc == ssrc) {
462 tmp = cur;
463 cur = cur->prev;
464 tmp->prev->next = tmp->next;
465 tmp->next->prev = tmp->prev;
466 free(tmp->rr);
467 free(tmp);
468 }
469 cur = cur->next;
470 }
471 }
472}

References _rtcp_rr_wrapper::next, _rtcp_rr_wrapper::prev, _rtcp_rr_wrapper::reporter_ssrc, _rtcp_rr_wrapper::rr, rtp::rr, RTP_DB_SIZE, rtcp_rr::ssrc, ssrc_hash(), and start().

Referenced by delete_source().

Here is the call graph for this function:

◆ rijndael_decrypt()

static bool rijndael_decrypt ( struct rtp * session,
unsigned char * data,
unsigned int size,
unsigned char * initVec )
static

Definition at line 3917 of file rtp.c.

3919{
3920 int rc;
3921 UNUSED(initVec);
3922
3923 /*
3924 * Try doing this in place. If it doesn't work that way,
3925 * we'll have to allocate a buffer and copy back.
3926 */
3929 data, size * 8, data);
3930 return rc;
3931}
int blockDecrypt(cipherInstance *cipher, keyInstance *key, BYTE *input, int inputLen, BYTE *outBuffer)
Definition crypt_aes.c:287
keyInstance keyInstDecrypt
Definition rtp.c:325
struct rtp::@38::@39 rijndael
cipherInstance cipherInst
Definition rtp.c:326

References blockDecrypt(), rtp::cipherInst, rtp::crypto_state, rtp::keyInstDecrypt, rtp::rijndael, and UNUSED.

Referenced by rijndael_initialize().

Here is the call graph for this function:

◆ rijndael_encrypt()

static int rijndael_encrypt ( struct rtp * session,
unsigned char * data,
unsigned int size,
unsigned char * initVec )
static

Definition at line 3900 of file rtp.c.

3902{
3903 int rc;
3904
3905 UNUSED(initVec);
3906
3907 /*
3908 * Try doing this in place. If it doesn't work that way,
3909 * we'll have to allocate a buffer and copy back.
3910 */
3913 data, size * 8, data);
3914 return rc;
3915}
int blockEncrypt(cipherInstance *cipher, keyInstance *key, BYTE *input, int inputLen, BYTE *outBuffer)
Definition crypt_aes.c:145
keyInstance keyInstEncrypt
Definition rtp.c:324

References blockEncrypt(), rtp::cipherInst, rtp::crypto_state, rtp::keyInstEncrypt, rtp::rijndael, and UNUSED.

Referenced by rijndael_initialize().

Here is the call graph for this function:

◆ rijndael_initialize()

static bool rijndael_initialize ( struct rtp * session,
const u_char * hash,
int hash_len )
static

Definition at line 3871 of file rtp.c.

3872{
3873 session->encryption_pad_length = 16;
3874 session->encrypt_func = rijndael_encrypt;
3875 session->decrypt_func = rijndael_decrypt;
3876
3877 int rc = makeKey(&session->crypto_state.rijndael.keyInstEncrypt,
3878 DIR_ENCRYPT, hash_len * 8, (const char *)hash);
3879 if (rc < 0) {
3880 debug_msg("makeKey failed: %d\n", rc);
3881 return false;
3882 }
3883
3885 DIR_DECRYPT, hash_len * 8, (const char *)hash);
3886 if (rc < 0) {
3887 debug_msg("makeKey failed: %d\n", rc);
3888 return false;
3889 }
3890
3892 MODE_ECB, NULL);
3893 if (rc < 0) {
3894 debug_msg("cipherInst failed: %d\n", rc);
3895 return false;
3896 }
3897 return true;
3898}
int makeKey(keyInstance *key, BYTE direction, int keyLen, const char *keyMaterial)
Definition crypt_aes.c:45
int cipherInit(cipherInstance *cipher, BYTE mode, char *IV)
Definition crypt_aes.c:105
#define DIR_DECRYPT
Definition crypt_aes.h:46
#define MODE_ECB
Definition crypt_aes.h:47
#define DIR_ENCRYPT
Definition crypt_aes.h:45
static bool rijndael_decrypt(struct rtp *session, unsigned char *data, unsigned int size, unsigned char *initVec)
Definition rtp.c:3917
static int rijndael_encrypt(struct rtp *session, unsigned char *data, unsigned int size, unsigned char *initVec)
Definition rtp.c:3900

References cipherInit(), rtp::cipherInst, rtp::crypto_state, debug_msg, rtp::decrypt_func, DIR_DECRYPT, DIR_ENCRYPT, rtp::encrypt_func, rtp::encryption_pad_length, rtp::keyInstDecrypt, rtp::keyInstEncrypt, makeKey(), MODE_ECB, rtp::rijndael, rijndael_decrypt(), and rijndael_encrypt().

Referenced by rtp_set_encryption_key().

Here is the call graph for this function:

◆ rtcp_interval()

static double rtcp_interval ( struct rtp * session)
static

Definition at line 832 of file rtp.c.

833{
834 /* Minimum average time between RTCP packets from this site (in */
835 /* seconds). This time prevents the reports from `clumping' when */
836 /* sessions are small and the law of large numbers isn't helping */
837 /* to smooth out the traffic. It also keeps the report interval */
838 /* from becoming ridiculously small during transient outages like */
839 /* a network partition. */
840 double const RTCP_MIN_TIME = 5.0;
841 /* Fraction of the RTCP bandwidth to be shared among active */
842 /* senders. (This fraction was chosen so that in a typical */
843 /* session with one or two active senders, the computed report */
844 /* time would be roughly equal to the minimum report time so that */
845 /* we don't unnecessarily slow down receiver reports.) The */
846 /* receiver fraction must be 1 - the sender fraction. */
847 double const RTCP_SENDER_BW_FRACTION = 0.25;
848 double const RTCP_RCVR_BW_FRACTION = (1 - RTCP_SENDER_BW_FRACTION);
849 /* To compensate for "unconditional reconsideration" converging */
850 /* to a value below the intended average. */
851 double const COMPENSATION = 2.71828 - 1.5;
852
853 double t; /* interval */
854 double rtcp_min_time = RTCP_MIN_TIME;
855 int n; /* no. of members for computation */
856 double rtcp_bw = session->rtcp_bw;
857
858 /* Very first call at application start-up uses half the min */
859 /* delay for quicker notification while still allowing some time */
860 /* before reporting for randomization and to learn about other */
861 /* sources so the report interval will converge to the correct */
862 /* interval more quickly. */
863 if (session->initial_rtcp) {
864 rtcp_min_time /= 2;
865 }
866
867 /* If there were active senders, give them at least a minimum */
868 /* share of the RTCP bandwidth. Otherwise all participants share */
869 /* the RTCP bandwidth equally. */
870 if (session->sending_bye) {
871 n = session->bye_count;
872 } else {
873 n = session->ssrc_count;
874 }
875 if (session->sender_count > 0
876 && session->sender_count < n * RTCP_SENDER_BW_FRACTION) {
877 if (session->we_sent) {
878 rtcp_bw *= RTCP_SENDER_BW_FRACTION;
879 n = session->sender_count;
880 } else {
881 rtcp_bw *= RTCP_RCVR_BW_FRACTION;
882 n -= session->sender_count;
883 }
884 }
885
886 /* The effective number of sites times the average packet size is */
887 /* the total number of octets sent when each site sends a report. */
888 /* Dividing this by the effective bandwidth gives the time */
889 /* interval over which those packets must be sent in order to */
890 /* meet the bandwidth target, with a minimum enforced. In that */
891 /* time interval we send one report so this time is also our */
892 /* average time between reports. */
893 t = session->avg_rtcp_size * n / rtcp_bw;
894 if (t < rtcp_min_time) {
895 t = rtcp_min_time;
896 }
897 session->rtcp_interval = t;
898
899 /* To avoid traffic bursts from unintended synchronization with */
900 /* other sites, we then pick our actual next report interval as a */
901 /* random number uniformly distributed between 0.5*t and 1.5*t. */
902 return (t * (ug_drand() + 0.5)) / COMPENSATION;
903}
int initial_rtcp
Definition rtp.c:293
double rtcp_bw
Definition rtp.c:297
int we_sent
Definition rtp.c:296
int sending_bye
Definition rtp.c:294
double avg_rtcp_size
Definition rtp.c:295
double rtcp_interval
Definition rtp.c:302
double ug_drand()
Definition random.c:111

References rtp::avg_rtcp_size, rtp::bye_count, rtp::initial_rtcp, rtp::rtcp_bw, rtp::rtcp_interval, rtp::sender_count, rtp::sending_bye, rtp::ssrc_count, ug_drand(), and rtp::we_sent.

Referenced by rtp_init_if(), rtp_init_with_udp_socket(), rtp_send_bye(), rtp_send_ctrl(), and rtp_update().

Here is the call graph for this function:

◆ rtcp_recv_r()

bool rtcp_recv_r ( struct rtp * session,
struct timeval * timeout,
uint32_t curr_rtp_ts )

Similar to rtp_recv_r(), expect that it only receives data from RTCP socket. This should be used when the socket acts as a sender only, therefore rtp_recv_r() is not called. Running rtp_recv_r() instead would cause leaks in this context (because RTP packets are usually pushed into PBUF which is not processed by sender and thus it will grow indefinitely).

Definition at line 2398 of file rtp.c.

2399{
2400 UNUSED(curr_rtp_ts);
2401 struct udp_fd_r fd;
2402
2403 check_database(session);
2404 udp_fd_zero_r(&fd);
2405 udp_fd_set_r(session->rtcp_socket, &fd);
2406 if (udp_select_r(timeout, &fd) > 0) {
2407 if (udp_fd_isset_r(session->rtcp_socket, &fd)) {
2408 uint8_t buffer[RTP_MAX_PACKET_LEN];
2409 int buflen;
2410 session->rtcp_dest_len = sizeof(session->rtcp_dest);
2411 buflen =
2412 udp_recvfrom(session->rtcp_socket, (char *)buffer,
2414 (struct sockaddr *) &session->rtcp_dest, &session->rtcp_dest_len);
2415 rtp_process_ctrl(session, buffer, buflen);
2416 }
2417 check_database(session);
2418 return true;
2419 }
2420 check_database(session);
2421 return false;
2422}
int udp_recvfrom(socket_udp *s, char *buffer, int buflen, struct sockaddr *src_addr, socklen_t *addrlen)
Definition net_udp.c:1245
int udp_select_r(struct timeval *timeout, struct udp_fd_r *fd_struct)
Definition net_udp.c:1355
void udp_fd_zero_r(struct udp_fd_r *fd_struct)
Definition net_udp.c:961
void udp_fd_set_r(socket_udp *s, struct udp_fd_r *fd_struct)
Definition net_udp.c:1312
int udp_fd_isset_r(socket_udp *s, struct udp_fd_r *fd_struct)
Definition net_udp.c:1336
static void rtp_process_ctrl(struct rtp *session, uint8_t *buffer, int buflen)
Definition rtp.c:2127
socklen_t rtcp_dest_len
Definition rtp.c:278
struct sockaddr_storage rtcp_dest
Definition rtp.c:277
socket_udp * rtcp_socket
Definition rtp.c:276

References check_database(), rtp::rtcp_dest, rtp::rtcp_dest_len, rtp::rtcp_socket, RTP_MAX_PACKET_LEN, rtp_process_ctrl(), udp_fd_isset_r(), udp_fd_set_r(), udp_fd_zero_r(), udp_recvfrom(), udp_select_r(), and UNUSED.

Referenced by audio_sender_thread(), and ultragrid_rtp_video_rxtx::send_frame_async().

Here is the call graph for this function:

◆ rtcp_udp_send()

static void rtcp_udp_send ( struct rtp * session,
int len,
char * buffer )
static

Sends the RTCP packet over UDP to either a configured host (if specified on the command-line) or to the destination from which we are receiving RTCP.

Definition at line 3263 of file rtp.c.

3264{
3265 if (!session->send_rtcp_to_origin) {
3266 int rc = udp_send(session->rtcp_socket, buffer, len);
3267 if (rc == -1) {
3268 log_msg(LOG_LEVEL_WARNING, "sending RTCP packet: %s\n",
3269 ug_strerror(errno));
3270 }
3271 } else {
3272 if (session->rtcp_dest_len > 0) {
3273 int rc = udp_sendto(session->rtcp_socket, buffer, len,
3274 (struct sockaddr *) &session->rtcp_dest, session->rtcp_dest_len);
3275 if (rc == -1) {
3277 "sending RTCP packet: %s\n",
3278 ug_strerror(errno));
3279 }
3280 }
3281 }
3282}
int void size_t * len
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
const char * ug_strerror(int errnum)
Definition misc.cpp:203
int udp_sendto(socket_udp *s, char *buffer, int buflen, struct sockaddr *dst_addr, socklen_t addrlen)
Definition net_udp.c:1038
int udp_send(socket_udp *s, char *buffer, int buflen)
Definition net_udp.c:1028
bool send_rtcp_to_origin
Definition rtp.c:279

References len, LOG_LEVEL_WARNING, log_msg(), rtp::rtcp_dest, rtp::rtcp_dest_len, rtp::rtcp_socket, rtp::send_rtcp_to_origin, udp_send(), udp_sendto(), and ug_strerror().

Referenced by rtp_send_bye_now(), and send_rtcp().

Here is the call graph for this function:

◆ rtp_add_csrc()

bool rtp_add_csrc ( struct rtp * session,
uint32_t csrc )

rtp_add_csrc: @session: the session pointer (returned by rtp_init()) @csrc: Constributing SSRC identifier

Adds @csrc to list of contributing sources used in SDES items. Used by mixers and transcoders.

Return value: true.

Definition at line 2478 of file rtp.c.

2479{
2480 /* Mark csrc as something for which we should advertise RTCP SDES items, */
2481 /* in addition to our own SDES. */
2482 source *s;
2483
2484 check_database(session);
2485 s = get_source(session, csrc);
2486 if (s == NULL) {
2487 s = create_source(session, csrc, FALSE);
2488 debug_msg("Created source 0x%08x as CSRC\n", csrc);
2489 }
2490 check_source(s);
2491 if (!s->should_advertise_sdes) {
2493 session->csrc_count++;
2494 debug_msg("Added CSRC 0x%08" PRIx32 " as CSRC %d\n", csrc,
2495 session->csrc_count);
2496 }
2497 return true;
2498}

References check_database(), check_source(), create_source(), rtp::csrc_count, debug_msg, FALSE, get_source(), _source::should_advertise_sdes, and TRUE.

Here is the call graph for this function:

◆ rtp_async_start()

void rtp_async_start ( struct rtp * session,
int nr_packets )

Definition at line 4027 of file rtp.c.

4028{
4029 udp_async_start(session->rtp_socket, nr_packets);
4030}
void udp_async_start(socket_udp *s, int nr_packets)
Definition net_udp.c:1530
socket_udp * rtp_socket
Definition rtp.c:275

References rtp::rtp_socket, and udp_async_start().

Referenced by tx_send_base().

Here is the call graph for this function:

◆ rtp_async_wait()

void rtp_async_wait ( struct rtp * session)

Definition at line 4032 of file rtp.c.

4033{
4034 udp_async_wait(session->rtp_socket);
4035}
void udp_async_wait(socket_udp *s)
Definition net_udp.c:1557

References rtp::rtp_socket, and udp_async_wait().

Referenced by tx_send_base().

Here is the call graph for this function:

◆ rtp_compute_fract_lost()

int rtp_compute_fract_lost ( struct rtp * session,
uint32_t ssrc )

Definition at line 3974 of file rtp.c.

3975{
3976 int h;
3977 source *s;
3978
3979 for (h = 0; h < RTP_DB_SIZE; h++) {
3980 for (s = session->db[h]; s != NULL; s = s->next) {
3981 check_source(s);
3982 if (s->ssrc == ssrc) {
3983 /* Much of this is taken from A.3 of draft-ietf-avt-rtp-new-01.txt */
3984 int extended_max = s->cycles + s->max_seq;
3985 int expected = extended_max - s->base_seq + 1;
3986 //int lost = expected - s->received;
3987 int expected_interval =
3988 expected - s->expected_prior;
3989 int received_interval =
3990 s->received - s->received_prior;
3991 int lost_interval =
3992 expected_interval - received_interval;
3993 int fraction;
3994 //uint32_t lsr;
3995 //uint32_t dlsr;
3996
3997 //printf("lost_interval %d\n", lost_interval);
3998 s->expected_prior = expected;
3999 s->received_prior = s->received;
4000 if (expected_interval == 0
4001 || lost_interval <= 0) {
4002 fraction = 0;
4003 } else {
4004 fraction =
4005 (lost_interval << 8) /
4006 expected_interval;
4007 }
4008
4009 return fraction;
4010 }
4011 }
4012 }
4013 return 0;
4014}

References _source::base_seq, check_source(), _source::cycles, rtp::db, _source::expected_prior, _source::max_seq, _source::next, _source::received, _source::received_prior, RTP_DB_SIZE, and _source::ssrc.

Here is the call graph for this function:

◆ rtp_del_csrc()

bool rtp_del_csrc ( struct rtp * session,
uint32_t csrc )

rtp_del_csrc: @session: the session pointer (returned by rtp_init()) @csrc: Constributing SSRC identifier

Removes @csrc from list of contributing sources used in SDES items. Used by mixers and transcoders.

Return values
trueon success, false if @csrc is not a valid source.

Definition at line 2510 of file rtp.c.

2511{
2512 source *s;
2513
2514 check_database(session);
2515 s = get_source(session, csrc);
2516 if (s == NULL) {
2517 debug_msg("Invalid source 0x%08x\n", csrc);
2518 return false;
2519 }
2520 check_source(s);
2522 session->csrc_count--;
2523 if (session->last_advertised_csrc >= session->csrc_count) {
2524 session->last_advertised_csrc = 0;
2525 }
2526 return true;
2527}

References check_database(), check_source(), rtp::csrc_count, debug_msg, FALSE, get_source(), rtp::last_advertised_csrc, and _source::should_advertise_sdes.

Here is the call graph for this function:

◆ rtp_done()

void rtp_done ( struct rtp * session)

rtp_done: @session: the RTP session to finish

Free the state associated with the given RTP session. This function does not send any packets (e.g. an RTCP BYE) - an application which wishes to exit in a clean manner should call rtp_send_bye() first.

Definition at line 3676 of file rtp.c.

3677{
3678 int i;
3679 source *s, *n;
3680
3681 check_database(session);
3682 /* In delete_source, check database gets called and this assumes */
3683 /* first added and last removed is us. */
3684 for (i = 0; i < RTP_DB_SIZE; i++) {
3685 s = session->db[i];
3686 while (s != NULL) {
3687 n = s->next;
3688 if (s->ssrc != session->my_ssrc) {
3689 delete_source(session, session->db[i]->ssrc);
3690 }
3691 s = n;
3692 }
3693 }
3694
3695 delete_source(session, session->my_ssrc);
3696
3697 /*
3698 * Introduce a memory leak until we add algorithm-specific
3699 * cleanup functions.
3700 if (session->encryption_key != NULL) {
3701 free(session->encryption_key);
3702 }
3703 */
3704
3705 udp_exit(session->rtp_socket);
3706 udp_exit(session->rtcp_socket);
3707 free(session->opt);
3708 free(session);
3709}
void udp_exit(socket_udp *s)
Definition net_udp.c:974
static void delete_source(struct rtp *session, uint32_t ssrc)
Definition rtp.c:673

References check_database(), rtp::db, delete_source(), rtp::my_ssrc, _source::next, rtp::opt, rtp::rtcp_socket, RTP_DB_SIZE, rtp::rtp_socket, _source::ssrc, and udp_exit().

Referenced by am_participant::~am_participant(), audio_done(), audio_receiver_process_message(), audio_sender_process_message(), rtp_video_rxtx::destroy_rtp_device(), and vidcap_rtsp_done().

Here is the call graph for this function:

◆ rtp_flush_recv_buf()

void rtp_flush_recv_buf ( struct rtp * session)

rtp_flush_recv_buf: Flushes receiver buffer contents. @session: The RTP Session.

Definition at line 3964 of file rtp.c.

3965{
3967}
void udp_flush_recv_buf(socket_udp *s)
Definition net_udp.c:1500

References rtp::rtp_socket, and udp_flush_recv_buf().

Referenced by audio_receiver_thread().

Here is the call graph for this function:

◆ rtp_get_bytes_sent()

uint64_t rtp_get_bytes_sent ( struct rtp * session)

Definition at line 3969 of file rtp.c.

3970{
3971 return session->rtp_bytes_sent;
3972}
uint64_t rtp_bytes_sent
Definition rtp.c:309

References rtp::rtp_bytes_sent.

◆ rtp_get_option()

bool rtp_get_option ( struct rtp * session,
rtp_option optname,
int * optval )

rtp_get_option: @session: The RTP session. @optname: The option name, see rtp_option. @optval: The return value.

Retrieves the value of a session option. See rtp_option for documentation on the options and their legal values.

Returns
true and the value of the option in optval on success, else false.

Definition at line 1352 of file rtp.c.

1353{
1354 switch (optname) {
1356 *optval = session->opt->wait_for_rtcp;
1357 break;
1358 case RTP_OPT_PROMISC:
1359 *optval = session->opt->promiscuous_mode;
1360 break;
1362 *optval = session->opt->filter_my_packets;
1363 break;
1365 *optval = session->opt->reuse_bufs;
1366 break;
1367 default:
1368 *optval = 0;
1369 debug_msg
1370 ("Ignoring unknown option (%d) in call to rtp_get_option().\n",
1371 optname);
1372 return false;
1373 }
1374 return true;
1375}
int reuse_bufs
Definition rtp.c:257
int wait_for_rtcp
Definition rtp.c:255
int promiscuous_mode
Definition rtp.c:254

References debug_msg, options::filter_my_packets, rtp::opt, options::promiscuous_mode, options::reuse_bufs, RTP_OPT_FILTER_MY_PACKETS, RTP_OPT_PROMISC, RTP_OPT_REUSE_PACKET_BUFS, RTP_OPT_WEAK_VALIDATION, and options::wait_for_rtcp.

◆ rtp_get_recv_buf()

int rtp_get_recv_buf ( struct rtp * session)

Definition at line 3944 of file rtp.c.

3945{
3946 return udp_get_recv_buf(session->rtp_socket);
3947}
int udp_get_recv_buf(socket_udp *s)
Definition net_udp.c:1445

References rtp::rtp_socket, and udp_get_recv_buf().

Referenced by ultragrid_rtp_video_rxtx::receiver_loop().

Here is the call graph for this function:

◆ rtp_get_rr()

const rtcp_rr * rtp_get_rr ( struct rtp * session,
uint32_t reporter,
uint32_t reportee )

rtp_get_rr: @session: the session pointer (returned by rtp_init()) @reporter: participant originating receiver report @reportee: participant included in receiver report

Retrieve the latest receiver report on @reportee made by @reporter. Provides an indication of other receivers reception service.

Return value: A pointer to a rtcp_rr structure on success, NULL otherwise. The pointer must not be freed.

Definition at line 2707 of file rtp.c.

2709{
2710 check_database(session);
2711 return get_rr(session, reporter, reportee);
2712}
static const rtcp_rr * get_rr(struct rtp *session, uint32_t reporter_ssrc, uint32_t reportee_ssrc)
Definition rtp.c:512

References check_database(), and get_rr().

Referenced by process_rr().

Here is the call graph for this function:

◆ rtp_get_sdes()

const char * rtp_get_sdes ( struct rtp * session,
uint32_t ssrc,
rtcp_sdes_type type )

rtp_get_sdes: @session: the session pointer (returned by rtp_init()) @ssrc: the SSRC identifier of a participant @type: the SDES information to retrieve

Recovers session description (SDES) information on participant identified with @ssrc. The SDES information associated with a source is updated when receiver reports are received. There are several different types of SDES information, e.g. username, location, phone, email. These are enumerated by rtcp_sdes_type.

Return value: pointer to string containing SDES description if received, NULL otherwise.

Definition at line 2631 of file rtp.c.

2633{
2634 source *s;
2635
2636 check_database(session);
2637
2638 s = get_source(session, ssrc);
2639 if (s == NULL) {
2640 debug_msg("Invalid source 0x%08x\n", ssrc);
2641 return NULL;
2642 }
2643 check_source(s);
2644
2645 switch (type) {
2646 case RTCP_SDES_CNAME:
2647 return s->sdes_cname;
2648 case RTCP_SDES_NAME:
2649 return s->sdes_name;
2650 case RTCP_SDES_EMAIL:
2651 return s->sdes_email;
2652 case RTCP_SDES_PHONE:
2653 return s->sdes_phone;
2654 case RTCP_SDES_LOC:
2655 return s->sdes_loc;
2656 case RTCP_SDES_TOOL:
2657 return s->sdes_tool;
2658 case RTCP_SDES_NOTE:
2659 return s->sdes_note;
2660 case RTCP_SDES_PRIV:
2661 return s->sdes_priv;
2662 default:
2663 /* This includes RTCP_SDES_PRIV and RTCP_SDES_END */
2664 debug_msg("Unknown SDES item (type=%d)\n", type);
2665 }
2666 return NULL;
2667}

References check_database(), check_source(), debug_msg, get_source(), RTCP_SDES_CNAME, RTCP_SDES_EMAIL, RTCP_SDES_LOC, RTCP_SDES_NAME, RTCP_SDES_NOTE, RTCP_SDES_PHONE, RTCP_SDES_PRIV, RTCP_SDES_TOOL, _source::sdes_cname, _source::sdes_email, _source::sdes_loc, _source::sdes_name, _source::sdes_note, _source::sdes_phone, _source::sdes_priv, _source::sdes_tool, and type.

Referenced by format_rtcp_sdes().

Here is the call graph for this function:

◆ rtp_get_sr()

const rtcp_sr * rtp_get_sr ( struct rtp * session,
uint32_t ssrc )

rtp_get_sr: @session: the session pointer (returned by rtp_init()) @ssrc: identifier of source

Retrieve the latest sender report made by sender with @ssrc identifier.

Return value: A pointer to an rtcp_sr structure on success, NULL otherwise. The pointer must not be freed.

Definition at line 2679 of file rtp.c.

2680{
2681 /* Return the last SR received from this ssrc. The */
2682 /* caller MUST NOT free the memory returned to it. */
2683 source *s;
2684
2685 check_database(session);
2686
2687 s = get_source(session, ssrc);
2688 if (s == NULL) {
2689 return NULL;
2690 }
2691 check_source(s);
2692 return s->sr;
2693}

References check_database(), check_source(), get_source(), and _source::sr.

Here is the call graph for this function:

◆ rtp_get_udp_local_socket()

struct socket_udp_local * rtp_get_udp_local_socket ( struct rtp * session)

Definition at line 4037 of file rtp.c.

4038{
4039 return udp_get_local(session->rtp_socket);
4040}
struct socket_udp_local * udp_get_local(socket_udp *s)
Definition net_udp.c:1751

References rtp::rtp_socket, and udp_get_local().

Referenced by audio_play_mixer_ctl().

Here is the call graph for this function:

◆ rtp_get_udp_rx_port()

int rtp_get_udp_rx_port ( struct rtp * session)

Definition at line 4042 of file rtp.c.

4043{
4044 return udp_get_udp_rx_port(session->rtp_socket);
4045}
int udp_get_udp_rx_port(socket_udp *s)
Definition net_udp.c:1756

References rtp::rtp_socket, and udp_get_udp_rx_port().

Referenced by set_audio_spec_to_vrxtx(), and vidcap_rtsp_init().

Here is the call graph for this function:

◆ rtp_get_userdata()

uint8_t * rtp_get_userdata ( struct rtp * session)

rtp_get_userdata: @session: The RTP session.

This function returns the userdata pointer that was passed to the rtp_init() or rtp_init_if() function when creating this session.

Returns: pointer to userdata.

Definition at line 1386 of file rtp.c.

1387{
1388 check_database(session);
1389 return session->userdata;
1390}
uint8_t * userdata
Definition rtp.c:285

References check_database(), and rtp::userdata.

Referenced by rtp_recv_callback().

Here is the call graph for this function:

◆ rtp_has_receiver()

bool rtp_has_receiver ( struct rtp * session)

Definition at line 4016 of file rtp.c.

4017{
4018 return !session->opt->send_back ||
4020}
bool udp_is_server_mode_blackhole(socket_udp *s)
Definition net_udp.c:911
int send_back
Definition rtp.c:259

References rtp::opt, rtp::rtp_socket, options::send_back, and udp_is_server_mode_blackhole().

Referenced by audio_tx_send(), rtp_process_data(), and tx_send_base().

Here is the call graph for this function:

◆ rtp_init()

struct rtp * rtp_init ( const char * addr,
uint16_t rx_port,
uint16_t tx_port,
int ttl,
double rtcp_bw,
int tfrc_on,
rtp_callback callback,
uint8_t * userdata,
int force_ip_version,
bool multithreaded )

rtp_init: @addr: IP destination of this session (unicast or multicast), as an ASCII string. May be a host name, which will be looked up, or may be an IPv4 dotted quad or IPv6 literal adddress. @rx_port: The port to which to bind the UDP socket @tx_port: The port to which to send UDP packets @ttl: The TTL for both multicast and unicast (-1 for default) @rtcp_bw: The total bandwidth (in units of bytes per second) that is allocated to RTCP. @callback: See section on rtp_callback. @userdata: Opaque data associated with the session. See rtp_get_userdata().

Returns: An opaque session identifier to be used in future calls to the RTP library functions, or NULL on failure.

Definition at line 999 of file rtp.c.

1004{
1005 return rtp_init_if(addr, NULL, rx_port, tx_port, ttl, rtcp_bw, tfrc_on,
1006 callback, userdata, force_ip_version, multithreaded);
1007}
struct rtp * rtp_init_if(const char *addr, const char *iface, uint16_t rx_port, uint16_t tx_port, int ttl, double rtcp_bw, int tfrc_on, rtp_callback callback, uint8_t *userdata, int force_ip_version, bool multithreaded)
Definition rtp.c:1034
Option::Callback::fcn_type callback
Definition settings.cpp:251

References callback, rtp::rtcp_bw, rtp_init_if(), rtp::tfrc_on, and rtp::userdata.

Here is the call graph for this function:

◆ rtp_init_if()

struct rtp * rtp_init_if ( const char * addr,
const char * iface,
uint16_t rx_port,
uint16_t tx_port,
int ttl,
double rtcp_bw,
int tfrc_on,
rtp_callback callback,
uint8_t * userdata,
int force_ip_version,
bool multithreaded )

rtp_init_if: @addr: IP destination of this session (unicast or multicast), as an ASCII string. May be a host name, which will be looked up, or may be an IPv4 dotted quad or IPv6 literal adddress. @iface: If the destination of the session is multicast, the optional interface to bind to. May be NULL, in which case the default multicast interface as determined by the system will be used. @rx_port: The port to which to bind the UDP socket @tx_port: The port to which to send UDP packets @ttl: The TTL for both multicast and unicast (-1 for default) @rtcp_bw: The total bandwidth (in units of ___) that is allocated to RTCP. @callback: See section on rtp_callback. @userdata: Opaque data associated with the session. See rtp_get_userdata(). @force_ip_version if IPv4 or IPv4 is requested, pass 4 or 6 respectively, otherwise 0 @multithreaded if set to true uses separate thread to receive data (performance optimization)

Creates and initializes an RTP session.

Returns: An opaque session identifier to be used in future calls to the RTP library functions, or NULL on failure.

Definition at line 1034 of file rtp.c.

1039{
1040 struct rtp *session;
1041 int i, j;
1042 char *cname;
1043 char *hname;
1044
1045#ifdef _WIN32
1046 if (multithreaded) {
1047 log_msg(LOG_LEVEL_WARNING, "Multithreaded RTP is not recommended for MSW due to internal locking within Winsock implementation.\n");
1048 }
1049#endif
1050
1051 if (force_ip_version != 0 && force_ip_version != 4 && force_ip_version != 6) {
1052 log_msg(LOG_LEVEL_ERROR, "IP version must be either 4 or 6 (or 0)\n");
1053 return NULL;
1054 }
1055 if (ttl < -1 || ttl > 255) {
1056 log_msg(LOG_LEVEL_ERROR, "ttl must be in range [0..255] or -1, %d given\n", ttl);
1057 return NULL;
1058 }
1059 if (rx_port % 2) {
1060 log_msg(LOG_LEVEL_WARNING, "RTP: rx_port should be even, using %d.\n", rx_port);
1061 }
1062 if (tx_port % 2) {
1063 log_msg(LOG_LEVEL_WARNING, "RTP: tx_port should be even, using %d.\n", tx_port);
1064 }
1065
1066 session = (struct rtp *)malloc(sizeof(struct rtp));
1067 memset(session, 0, sizeof(struct rtp));
1068
1069 session->magic = 0xfeedface;
1070 session->opt = (options *) malloc(sizeof(options));
1071 session->userdata = userdata;
1072 session->mt_recv = multithreaded;
1073 session->send_rtcp_to_origin =
1074 (tx_port == 0 && is_host_loopback(addr)) ||
1075 strcmp(addr, IN6_BLACKHOLE_SERVER_MODE_STR) == 0;
1076
1077 if (rx_port == 0) {
1078 const unsigned random_off = (ug_rand() % (IPPORT_MAX - IPPORT_DYNAMIC + 1)) & ~1U;
1079 for (unsigned i = 0; i <= (IPPORT_MAX - IPPORT_DYNAMIC) - 1; i += 2) {
1080 int port = IPPORT_DYNAMIC + ((random_off + i) % (IPPORT_MAX - IPPORT_DYNAMIC + 1));
1081 // this stuff is not atomic. but... it cannot be done in this way, either
1082 int ret = udp_port_pair_is_free(force_ip_version, port);
1083 if (ret == 0) {
1084 rx_port = port;
1085 break;
1086 }
1087 }
1088 if (rx_port == 0) {
1089 log_msg(LOG_LEVEL_ERROR, "Unable to find empty RTP port pair!\n");
1090 } else {
1091 verbose_msg("Found empty UDP port pair %d/%d\n", rx_port, rx_port + 1);
1092 }
1093 } else {
1094 MSG(VERBOSE, "Bound to ports %d/%d\n", rx_port, rx_port + 1);
1095 }
1096 if (tx_port == 0) {
1097 tx_port = rx_port;
1098 }
1099 session->rtp_socket = udp_init_if(addr, iface, rx_port, tx_port, ttl, force_ip_version, multithreaded);
1100
1101 session->rtcp_socket =
1102 udp_init_if(addr, iface, (uint16_t) (rx_port + (rx_port ? 1 : 0)),
1103 (uint16_t) (tx_port + (tx_port ? 1 : 0)), ttl, force_ip_version, false);
1104
1105 init_opt(session);
1106
1107 if (session->rtp_socket == NULL || session->rtcp_socket == NULL) {
1108 printf("Unable to open network\n");
1109 free(session);
1110 return NULL;
1111 }
1112
1113 hname = udp_host_addr(session->rtp_socket);
1114 free(hname);
1115
1116 session->my_ssrc = ug_rand();
1117 session->callback = callback;
1118 session->invalid_rtp_count = 0;
1119 session->invalid_rtcp_count = 0;
1120 session->bye_count = 0;
1121 session->csrc_count = 0;
1122 session->ssrc_count = 0;
1123 session->ssrc_count_prev = 0;
1124 session->sender_count = 0;
1125 session->initial_rtcp = TRUE;
1126 session->sending_bye = FALSE;
1127 session->avg_rtcp_size = -1; /* Sentinal value: reception of first packet starts initial value... */
1128 session->we_sent = FALSE;
1129 session->rtcp_bw = rtcp_bw;
1130 session->sdes_count_pri = 0;
1131 session->sdes_count_sec = 0;
1132 session->sdes_count_ter = 0;
1133 session->rtp_seq = (uint16_t) ug_rand();
1134 session->rtp_pcount = 0;
1135 session->mhdr = NULL;
1136 session->tfrc_on = tfrc_on;
1137 session->rtp_bcount = 0;
1138 session->rtp_bytes_sent = 0;
1139 session->last_update =
1140 session->last_rtcp_send_time =
1142 session->encryption_enabled = 0;
1143 session->encryption_algorithm = NULL;
1144
1145 /* Calculate when we're supposed to send our first RTCP packet... */
1146 session->next_rtcp_send_time += rtcp_interval(session) * NS_IN_SEC;
1147
1148 /* Initialise the source database... */
1149 for (i = 0; i < RTP_DB_SIZE; i++) {
1150 session->db[i] = NULL;
1151 }
1152 session->last_advertised_csrc = 0;
1153
1154 /* Initialize sentinels in rr table */
1155 for (i = 0; i < RTP_DB_SIZE; i++) {
1156 for (j = 0; j < RTP_DB_SIZE; j++) {
1157 session->rr[i][j].next = &session->rr[i][j];
1158 session->rr[i][j].prev = &session->rr[i][j];
1159 }
1160 }
1161
1162 /* Create a database entry for ourselves... */
1163 create_source(session, session->my_ssrc, FALSE);
1164 cname = get_cname(session->rtp_socket);
1165 rtp_set_sdes(session, session->my_ssrc, RTCP_SDES_CNAME, cname,
1166 strlen(cname));
1167 free(cname); /* cname is copied by rtp_set_sdes()... */
1168
1169 log_msg(LOG_LEVEL_DEBUG, "Created new RTP session with SSRC 0x%08x.\n",
1170 session->my_ssrc);
1171
1172 return session;
1173}
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define MSG(l, fmt,...)
Definition debug.h:96
#define verbose_msg(...)
Definition debug.h:90
#define LOG_LEVEL_DEBUG
Definition kernels.cu:48
bool is_host_loopback(const char *hostname)
Definition net.c:174
#define IN6_BLACKHOLE_SERVER_MODE_STR
Definition net.h:52
int udp_port_pair_is_free(int force_ip_version, int even_port)
Definition net_udp.c:1608
socket_udp * udp_init_if(const char *addr, const char *iface, uint16_t rx_port, uint16_t tx_port, int ttl, int force_ip_version, bool multithreaded)
Definition net_udp.c:789
static double rtcp_interval(struct rtp *session)
Definition rtp.c:832
static char * get_cname(socket_udp *s)
Definition rtp.c:907
#define IPPORT_DYNAMIC
Definition rtp.c:102
#define IPPORT_MAX
Definition rtp.c:103
static void init_opt(struct rtp *session)
Definition rtp.c:966
Definition rtp.c:253
Definition rtp.c:274
bool mt_recv
Definition rtp.c:334
int invalid_rtp_count
Definition rtp.c:286
char * encryption_algorithm
Definition rtp.c:317
time_ns_t last_update
Definition rtp.c:298
int encryption_enabled
Definition rtp.c:318
uint16_t rtp_seq
Definition rtp.c:306
int invalid_rtcp_count
Definition rtp.c:287
struct msghdr * mhdr
Definition rtp.c:333
uint32_t ug_rand(void)
Definition random.c:88

References rtp::avg_rtcp_size, rtp::bye_count, callback, rtp::callback, create_source(), rtp::csrc_count, rtp::db, rtp::encryption_algorithm, rtp::encryption_enabled, FALSE, get_cname(), get_time_in_ns(), IN6_BLACKHOLE_SERVER_MODE_STR, init_opt(), rtp::initial_rtcp, rtp::invalid_rtcp_count, rtp::invalid_rtp_count, IPPORT_DYNAMIC, IPPORT_MAX, is_host_loopback(), rtp::last_advertised_csrc, rtp::last_rtcp_send_time, rtp::last_update, LOG_LEVEL_DEBUG, LOG_LEVEL_ERROR, LOG_LEVEL_WARNING, log_msg(), rtp::magic, rtp::mhdr, MSG, rtp::mt_recv, rtp::my_ssrc, _rtcp_rr_wrapper::next, rtp::next_rtcp_send_time, NS_IN_SEC, rtp::opt, _rtcp_rr_wrapper::prev, rtp::rr, rtp::rtcp_bw, rtcp_interval(), RTCP_SDES_CNAME, rtp::rtcp_socket, rtp::rtp_bcount, rtp::rtp_bytes_sent, RTP_DB_SIZE, rtp::rtp_pcount, rtp::rtp_seq, rtp_set_sdes(), rtp::rtp_socket, rtp::sdes_count_pri, rtp::sdes_count_sec, rtp::sdes_count_ter, rtp::send_rtcp_to_origin, rtp::sender_count, rtp::sending_bye, rtp::ssrc_count, rtp::ssrc_count_prev, rtp::tfrc_on, TRUE, udp_host_addr(), udp_init_if(), udp_port_pair_is_free(), ug_rand(), rtp::userdata, verbose_msg, and rtp::we_sent.

Referenced by initialize_audio_network(), rtp_video_rxtx::initialize_network(), rtp_init(), and vidcap_rtsp_init().

Here is the call graph for this function:

◆ rtp_init_with_udp_socket()

rtp_t rtp_init_with_udp_socket ( struct socket_udp_local * l,
struct sockaddr * sa,
socklen_t len,
rtp_callback callback )

Definition at line 1175 of file rtp.c.

1176{
1177 struct rtp *session;
1178 int i, j;
1179 char *cname;
1180 char *hname;
1181 int ttl = 127; /* FIXME */
1182 int tfrc_on = FALSE; /* FIXME */
1183
1184 session = (struct rtp *)malloc(sizeof(struct rtp));
1185 memset(session, 0, sizeof(struct rtp));
1186
1187 session->magic = 0xfeedface;
1188 session->opt = (options *) malloc(sizeof(options));
1189 // socket is not designated to receiving
1190 session->userdata = 0;
1191 session->mt_recv = false;
1192 session->send_rtcp_to_origin = true;
1193
1194 session->rtp_socket = udp_init_with_local(l, sa, len);
1195 session->rtcp_socket = udp_init_if("localhost", NULL, 0, 0, ttl, 6, false);
1196
1197 init_opt(session);
1198
1199 if (session->rtp_socket == NULL || session->rtcp_socket == NULL) {
1200 printf("Unable to open network\n");
1201 free(session);
1202 return NULL;
1203 }
1204
1205 hname = udp_host_addr(session->rtp_socket);
1206 free(hname);
1207
1208 session->my_ssrc = ug_rand();
1209 session->callback = callback;
1210 session->invalid_rtp_count = 0;
1211 session->invalid_rtcp_count = 0;
1212 session->bye_count = 0;
1213 session->csrc_count = 0;
1214 session->ssrc_count = 0;
1215 session->ssrc_count_prev = 0;
1216 session->sender_count = 0;
1217 session->initial_rtcp = TRUE;
1218 session->sending_bye = FALSE;
1219 session->avg_rtcp_size = -1; /* Sentinal value: reception of first packet starts initial value... */
1220 session->we_sent = FALSE;
1221 session->rtcp_bw = 5 * 1024 * 1024; /* FIXME */
1222 session->sdes_count_pri = 0;
1223 session->sdes_count_sec = 0;
1224 session->sdes_count_ter = 0;
1225 session->rtp_seq = (uint16_t) ug_rand();
1226 session->rtp_pcount = 0;
1227 session->mhdr = NULL;
1228 session->tfrc_on = tfrc_on;
1229 session->rtp_bcount = 0;
1230 session->rtp_bytes_sent = 0;
1231 session->last_update =
1232 session->last_rtcp_send_time =
1234 session->encryption_enabled = 0;
1235 session->encryption_algorithm = NULL;
1236
1237 /* Calculate when we're supposed to send our first RTCP packet... */
1238 session->next_rtcp_send_time += NS_IN_SEC * rtcp_interval(session);
1239
1240 /* Initialise the source database... */
1241 for (i = 0; i < RTP_DB_SIZE; i++) {
1242 session->db[i] = NULL;
1243 }
1244 session->last_advertised_csrc = 0;
1245
1246 /* Initialize sentinels in rr table */
1247 for (i = 0; i < RTP_DB_SIZE; i++) {
1248 for (j = 0; j < RTP_DB_SIZE; j++) {
1249 session->rr[i][j].next = &session->rr[i][j];
1250 session->rr[i][j].prev = &session->rr[i][j];
1251 }
1252 }
1253
1254 /* Create a database entry for ourselves... */
1255 create_source(session, session->my_ssrc, FALSE);
1256 cname = get_cname(session->rtp_socket);
1257 rtp_set_sdes(session, session->my_ssrc, RTCP_SDES_CNAME, cname,
1258 strlen(cname));
1259 free(cname); /* cname is copied by rtp_set_sdes()... */
1260
1261 log_msg(LOG_LEVEL_DEBUG, "Created new RTP session with SSRC 0x%08x.\n",
1262 session->my_ssrc);
1263
1264 return session;
1265}
socket_udp * udp_init_with_local(struct socket_udp_local *l, struct sockaddr *sa, socklen_t len)
Definition net_udp.c:927

References rtp::avg_rtcp_size, rtp::bye_count, callback, rtp::callback, create_source(), rtp::csrc_count, rtp::db, rtp::encryption_algorithm, rtp::encryption_enabled, FALSE, get_cname(), get_time_in_ns(), init_opt(), rtp::initial_rtcp, rtp::invalid_rtcp_count, rtp::invalid_rtp_count, rtp::last_advertised_csrc, rtp::last_rtcp_send_time, rtp::last_update, len, LOG_LEVEL_DEBUG, log_msg(), rtp::magic, rtp::mhdr, rtp::mt_recv, rtp::my_ssrc, _rtcp_rr_wrapper::next, rtp::next_rtcp_send_time, NS_IN_SEC, rtp::opt, _rtcp_rr_wrapper::prev, rtp::rr, rtp::rtcp_bw, rtcp_interval(), RTCP_SDES_CNAME, rtp::rtcp_socket, rtp::rtp_bcount, rtp::rtp_bytes_sent, RTP_DB_SIZE, rtp::rtp_pcount, rtp::rtp_seq, rtp_set_sdes(), rtp::rtp_socket, rtp::sdes_count_pri, rtp::sdes_count_sec, rtp::sdes_count_ter, rtp::send_rtcp_to_origin, rtp::sender_count, rtp::sending_bye, rtp::ssrc_count, rtp::ssrc_count_prev, rtp::tfrc_on, TRUE, udp_host_addr(), udp_init_if(), udp_init_with_local(), ug_rand(), rtp::userdata, and rtp::we_sent.

Referenced by am_participant::am_participant().

Here is the call graph for this function:

◆ rtp_is_ipv6()

bool rtp_is_ipv6 ( struct rtp * session)

Definition at line 4022 of file rtp.c.

4023{
4024 return udp_is_ipv6(session->rtp_socket);
4025}
bool udp_is_ipv6(socket_udp *s)
Definition net_udp.c:1598

References rtp::rtp_socket, and udp_is_ipv6().

Referenced by audio_tx_send_chan(), h264_sdp_video_rxtx::sdp_add_video(), set_audio_spec_to_vrxtx(), tx_send_base(), and tx_send_jpeg().

Here is the call graph for this function:

◆ rtp_my_ssrc()

uint32_t rtp_my_ssrc ( struct rtp * session)

rtp_my_ssrc: @session: The RTP Session.

Returns: The SSRC we are currently using in this session. Note that our SSRC can change at any time (due to collisions) so applications must not store the value returned, but rather should call this function each time they need it.

Definition at line 1401 of file rtp.c.

1402{
1403 check_database(session);
1404 return session->my_ssrc;
1405}

References check_database(), and rtp::my_ssrc.

Referenced by audio_sender_process_message(), filter_event(), format_rtcp_sr(), ultragrid_rtp_video_rxtx::get_ssrc(), initialize_audio_network(), rtp_video_rxtx::initialize_network(), process_rr(), rtp_video_rxtx::process_sender_message(), report_stats(), rtp_process_ctrl(), rtp_update(), send_rtcp(), and vidcap_rtsp_init().

Here is the call graph for this function:

◆ rtp_process_ctrl()

static void rtp_process_ctrl ( struct rtp * session,
uint8_t * buffer,
int buflen )
static

Definition at line 2127 of file rtp.c.

2128{
2129 /* This routine processes incoming RTCP packets */
2130 rtp_event event;
2131 rtcp_t *packet;
2132 uint8_t initVec[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
2133 int first;
2134 uint32_t packet_ssrc = rtp_my_ssrc(session);
2135
2136 if (buflen > 0) {
2137 if (session->encryption_enabled) {
2138 /* Decrypt the packet... */
2139 (session->decrypt_func) (session, buffer, buflen,
2140 initVec);
2141 buffer += 4; /* Skip the random prefix... */
2142 buflen -= 4;
2143 }
2144 if (validate_rtcp(buffer, buflen)) {
2145 first = TRUE;
2146 packet = (rtcp_t *)(void *) buffer;
2147 while (packet < (rtcp_t *)(void *) (buffer + buflen)) {
2148 switch (packet->common.pt) {
2149 case RTCP_SR:
2150 if (first
2151 && !filter_event(session,
2152 ntohl(packet->r.sr.
2153 sr.ssrc))) {
2154 event.ssrc =
2155 ntohl(packet->r.sr.sr.ssrc);
2156 event.type = RX_RTCP_START;
2157 event.data = &buflen;
2158 packet_ssrc = event.ssrc;
2159 session->callback(session,
2160 &event);
2161 }
2162 process_rtcp_sr(session, packet);
2163 break;
2164 case RTCP_RR:
2165 if (first
2166 && !filter_event(session,
2167 ntohl(packet->r.rr.
2168 ssrc))) {
2169 event.ssrc =
2170 ntohl(packet->r.rr.ssrc);
2171 event.type = RX_RTCP_START;
2172 event.data = &buflen;
2173 packet_ssrc = event.ssrc;
2174 session->callback(session,
2175 &event);
2176 }
2177 process_rtcp_rr(session, packet);
2178 break;
2179 case RTCP_RX:
2180 /* am not sending up a RX_RTCP_START... */
2181 process_rtcp_rx(session, packet);
2182 if (session->tfrc_on) {
2183 /* send up TFRC stuff ... */
2184 event.ssrc =
2185 ntohl(packet->r.rx.ssrc);
2186 event.type = RX_TFRC_RX;
2187 event.data = &buflen;
2188 packet_ssrc = event.ssrc;
2189 session->callback(session,
2190 &event);
2191 /* compute the rtt time */
2192 compute_rtt(session,
2193 packet->r.rx.rx);
2194 } else
2195 debug_msg
2196 ("RTCP_RX received without congestion control?");
2197 break;
2198 case RTCP_SDES:
2199 if (first
2200 && !filter_event(session,
2201 ntohl(packet->r.
2202 sdes.
2203 ssrc))) {
2204 event.ssrc =
2205 ntohl(packet->r.sdes.ssrc);
2206 event.type = RX_RTCP_START;
2207 event.data = &buflen;
2208 packet_ssrc = event.ssrc;
2209 session->callback(session,
2210 &event);
2211 }
2212 process_rtcp_sdes(session, packet);
2213 break;
2214 case RTCP_BYE:
2215 if (first
2216 && !filter_event(session,
2217 ntohl(packet->r.
2218 bye.
2219 ssrc[0]))) {
2220 event.ssrc =
2221 ntohl(packet->r.bye.
2222 ssrc[0]);
2223 event.type = RX_RTCP_START;
2224 event.data = &buflen;
2225 packet_ssrc = event.ssrc;
2226 session->callback(session,
2227 &event);
2228 }
2229 process_rtcp_bye(session, packet);
2230 break;
2231 case RTCP_APP:
2232 if (first
2233 && !filter_event(session,
2234 ntohl(packet->r.
2235 app.ssrc))) {
2236 event.ssrc =
2237 ntohl(packet->r.app.ssrc);
2238 event.type = RX_RTCP_START;
2239 event.data = &buflen;
2240 session->callback(session,
2241 &event);
2242 }
2243 process_rtcp_app(session, packet);
2244 break;
2245 default:
2246 debug_msg
2247 ("RTCP packet with unknown type (%d) ignored.\n",
2248 packet->common.pt);
2249 break;
2250 }
2251 packet =
2252 (rtcp_t *)(void *) ((char *)packet +
2253 (4 *
2254 (ntohs(packet->common.length) +
2255 1)));
2256 first = FALSE;
2257 }
2258 if (session->avg_rtcp_size < 0) {
2259 /* This is the first RTCP packet we've received, set our initial estimate */
2260 /* of the average packet size to be the size of this packet. */
2261 session->avg_rtcp_size =
2262 buflen + RTP_LOWER_LAYER_OVERHEAD;
2263 } else {
2264 /* Update our estimate of the average RTCP packet size. The constants are */
2265 /* 1/16 and 15/16 (section 6.3.3 of draft-ietf-avt-rtp-new-02.txt). */
2266 session->avg_rtcp_size =
2267 (0.0625 *
2268 (buflen + RTP_LOWER_LAYER_OVERHEAD)) +
2269 (0.9375 * session->avg_rtcp_size);
2270 }
2271 /* Signal that we've finished processing this packet */
2272 if (!filter_event(session, packet_ssrc)) {
2273 event.ssrc = packet_ssrc;
2274 event.type = RX_RTCP_FINISH;
2275 event.data = NULL;
2276 session->callback(session, &event);
2277 }
2278 } else {
2279 debug_msg("Invalid RTCP packet discarded\n");
2280 session->invalid_rtcp_count++;
2281 }
2282 }
2283}
static int validate_rtcp(uint8_t *packet, int len)
Definition rtp.c:1670
static void process_rtcp_app(struct rtp *session, rtcp_t *packet)
Definition rtp.c:2074
static void process_rtcp_sdes(struct rtp *session, rtcp_t *packet)
Definition rtp.c:1987
#define RTP_LOWER_LAYER_OVERHEAD
Definition rtp.c:136
static void process_rtcp_sr(struct rtp *session, rtcp_t *packet)
Definition rtp.c:1898
static void process_rtcp_bye(struct rtp *session, rtcp_t *packet)
Definition rtp.c:2045
#define RTCP_BYE
Definition rtp.c:141
#define RTCP_RX
Definition rtp.c:143
static uint32_t compute_rtt(struct rtp *session, rtcp_rx *rrx)
Definition rtp.c:2120
static void process_rtcp_rx(struct rtp *session, rtcp_t *packet)
Definition rtp.c:1967
static void process_rtcp_rr(struct rtp *session, rtcp_t *packet)
Definition rtp.c:1948
@ RX_RTCP_START
Definition rtp.h:190
@ RX_TFRC_RX
Definition rtp.h:184
@ RX_RTCP_FINISH
Definition rtp.h:191
codec_t first
Definition sdl2.c:423

References app, rtcp_t::app, rtp::avg_rtcp_size, rtcp_t::bye, rtp::callback, rtcp_t::common, compute_rtt(), debug_msg, rtp::decrypt_func, rtp::encryption_enabled, FALSE, filter_event(), first, rtp::invalid_rtcp_count, rtcp_common::length, process_rtcp_app(), process_rtcp_bye(), process_rtcp_rr(), process_rtcp_rx(), process_rtcp_sdes(), process_rtcp_sr(), rtcp_common::pt, rtcp_t::r, rtcp_t::rr, RTCP_APP, RTCP_BYE, RTCP_RR, RTCP_RX, RTCP_SDES, RTCP_SR, RTP_LOWER_LAYER_OVERHEAD, rtp_my_ssrc(), rtcp_t::rx, RX_RTCP_FINISH, RX_RTCP_START, RX_TFRC_RX, rtcp_t::sdes, rtcp_t::sr, rtcp_rr::ssrc, rtcp_sr::ssrc, rtcp_t::ssrc, rtp::tfrc_on, TRUE, and validate_rtcp().

Referenced by rtcp_recv_r(), rtp_recv(), rtp_recv_poll_r(), rtp_recv_r(), rtp_send_bye(), rtp_send_bye_now(), and send_rtcp().

Here is the call graph for this function:

◆ rtp_process_data()

static void rtp_process_data ( struct rtp * session,
uint32_t curr_rtp_ts,
uint8_t * buffer,
rtp_packet * packet,
int buflen )
static

Definition at line 1559 of file rtp.c.

1561{
1562 /* This routine preprocesses an incoming RTP packet, deciding whether to process it. */
1563
1564 if (buflen <= 0)
1565 return;
1566
1567 if (session->encryption_enabled) {
1568 uint8_t initVec[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
1569 (session->decrypt_func) (session, buffer, buflen,
1570 initVec);
1571 }
1572
1573 if (!rtp_has_receiver(session)) {
1574 session->opt->send_back = FALSE; // avoid multiple checks if already sending
1575 struct sockaddr *sa = (struct sockaddr *)(void *)((char *) packet + RTP_MAX_PACKET_LEN);
1576 log_msg(LOG_LEVEL_NOTICE, "[RTP] Redirecting stream to a client %s.\n", get_sockaddr_str(sa));
1577 udp_set_receiver(session->rtp_socket, sa, sa->sa_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6));
1578 }
1579
1580 /* figure out header lenght based on tfrc_on */
1581 /* might as well extract rtt and send_ts */
1582 int vlen = 12; /* vlen = 12 | 16 | 20 */
1583 if (session->tfrc_on) {
1584 vlen += 4;
1585 packet->send_ts = ntohl(packet->send_ts);
1586 /* rtt is present in RTP packet - XXX */
1587 if (packet->pt & 64) {
1588 /* rtt is present in RTP packet - XXX */
1589 vlen += 4;
1590 packet->rtt = ntohl(packet->rtt);
1591 //printf ("\n%8d %8d %8d", packet->send_ts, ntohl(packet->ts), packet->rtt );
1592 }
1593 }
1594 uint8_t *buffer_vlen = buffer + vlen;
1595
1596 /* Convert header fields to host byte order... */
1597 packet->seq = ntohs(packet->seq);
1598 packet->ts = ntohl(packet->ts);
1599 packet->ssrc = ntohl(packet->ssrc);
1600 /* Setup internal pointers, etc... */
1601 if (packet->cc) {
1602 int i;
1603 packet->csrc = (uint32_t *)(void *) (buffer_vlen);
1604 for (i = 0; i < packet->cc; i++) {
1605 packet->csrc[i] = ntohl(packet->csrc[i]);
1606 }
1607 } else {
1608 packet->csrc = NULL;
1609 }
1610 if (packet->x) {
1611 packet->extn = buffer_vlen + (packet->cc * 4);
1612 packet->extn_len =
1613 (packet->extn[2] << 8) | packet->extn[3];
1614 packet->extn_type =
1615 (packet->extn[0] << 8) | packet->extn[1];
1616 } else {
1617 packet->extn = NULL;
1618 packet->extn_len = 0;
1619 packet->extn_type = 0;
1620 }
1621 packet->data = (char *)(buffer_vlen + (packet->cc * 4));
1622 packet->data_len = buflen - (packet->cc * 4) - vlen;
1623 if (packet->extn != NULL) {
1624 packet->data += ((packet->extn_len + 1) * 4);
1625 packet->data_len -= ((packet->extn_len + 1) * 4);
1626 }
1627 if (validate_rtp(session, packet, buflen, vlen)) {
1628 source *s = NULL;
1629
1630 if (session->opt->wait_for_rtcp) {
1631 s = create_source(session, packet->ssrc, TRUE);
1632 } else {
1633 s = get_source(session, packet->ssrc);
1634 }
1635 if (session->opt->promiscuous_mode) {
1636 if (s == NULL) {
1637 create_source(session, packet->ssrc,
1638 FALSE);
1639 s = get_source(session, packet->ssrc);
1640 }
1641 update_seq(s, packet->seq);
1642 process_rtp(session, curr_rtp_ts, packet, s);
1643 return; /* We don't free "packet", that's done by the callback function... */
1644 }
1645 if (s != NULL) {
1646 if (s->probation == -1) {
1648 s->max_seq = packet->seq - 1;
1649 }
1650 if (update_seq(s, packet->seq)) {
1651 process_rtp(session, curr_rtp_ts,
1652 packet, s);
1653 return; /* we don't free "packet", that's done by the callback function... */
1654 }
1655 /* This source is still on probation... */
1656 debug_msg("RTP packet from probationary source ignored...\n");
1657 } else {
1658 /* debug_msg("RTP packet from unknown source ignored\n"); */
1659 }
1660 } else {
1661 session->invalid_rtp_count++;
1662 debug_msg("Invalid RTP packet discarded\n");
1663 }
1664
1665 if (!session->opt->reuse_bufs) {
1666 free(packet);
1667 }
1668}
#define LOG_LEVEL_NOTICE
information that may be interesting
Definition debug.h:61
const char * get_sockaddr_str(struct sockaddr *sa)
Definition net.c:450
void udp_set_receiver(socket_udp *s, struct sockaddr *sa, socklen_t len)
Definition net_udp.c:922
static void process_rtp(struct rtp *session, uint32_t curr_rtp_ts, rtp_packet *packet, source *s)
Definition rtp.c:1474
static int update_seq(source *s, uint16_t seq)
Definition rtp.c:778
#define MIN_SEQUENTIAL
Definition rtp.c:127
bool rtp_has_receiver(struct rtp *session)
Definition rtp.c:4016
static bool validate_rtp(struct rtp *session, rtp_packet *packet, int len, int vlen)
Definition rtp.c:1447

References create_source(), debug_msg, rtp::decrypt_func, rtp::encryption_enabled, FALSE, get_sockaddr_str(), get_source(), rtp::invalid_rtp_count, LOG_LEVEL_NOTICE, log_msg(), _source::max_seq, MIN_SEQUENTIAL, rtp::opt, _source::probation, process_rtp(), options::promiscuous_mode, options::reuse_bufs, rtp_has_receiver(), RTP_MAX_PACKET_LEN, rtp::rtp_socket, options::send_back, rtp::tfrc_on, TRUE, udp_set_receiver(), update_seq(), validate_rtp(), and options::wait_for_rtcp.

Referenced by rtp_recv_data().

Here is the call graph for this function:

◆ rtp_recv()

bool rtp_recv ( struct rtp * session,
struct timeval * timeout,
uint32_t curr_rtp_ts )

rtp_recv: @session: the session pointer (returned by rtp_init()) @timeout: the amount of time that rtcp_recv() is allowed to block @curr_rtp_ts: the current time expressed in units of the media timestamp.

Receive RTP packets and dispatch them.

Return values
trueif data received, false if the timeout occurred.
Deprecated
Use thread-safe rtp_recv_r() instead.

Definition at line 2297 of file rtp.c.

2298{
2299 check_database(session);
2300 udp_fd_zero();
2301 udp_fd_set(session->rtp_socket);
2302 udp_fd_set(session->rtcp_socket);
2303 if (udp_select(timeout) > 0) {
2304 if (udp_fd_isset(session->rtp_socket)) {
2305 rtp_recv_data(session, curr_rtp_ts);
2306 }
2307 if (udp_fd_isset(session->rtcp_socket)) {
2308 uint8_t buffer[RTP_MAX_PACKET_LEN];
2309 int buflen;
2310 buflen =
2311 udp_recv(session->rtcp_socket, (char *)buffer,
2313 rtp_process_ctrl(session, buffer, buflen);
2314 }
2315 check_database(session);
2316 return true;
2317 }
2318 check_database(session);
2319 return false;
2320}
int udp_recv(socket_udp *s, char *buffer, int buflen)
Definition net_udp.c:1236
void udp_fd_set(socket_udp *s)
Definition net_udp.c:1304
int udp_fd_isset(socket_udp *s)
Definition net_udp.c:1331
void udp_fd_zero(void)
Definition net_udp.c:955
int udp_select(struct timeval *timeout)
Definition net_udp.c:1350
static int rtp_recv_data(struct rtp *session, uint32_t curr_rtp_ts)
Definition rtp.c:1523

References check_database(), rtp::rtcp_socket, RTP_MAX_PACKET_LEN, rtp_process_ctrl(), rtp_recv_data(), rtp::rtp_socket, udp_fd_isset(), udp_fd_set(), udp_fd_zero(), udp_recv(), and udp_select().

Here is the call graph for this function:

◆ rtp_recv_data()

static int rtp_recv_data ( struct rtp * session,
uint32_t curr_rtp_ts )
static

Definition at line 1523 of file rtp.c.

1524{
1525 int buflen = 0;
1526 rtp_packet *packet = NULL;
1527 uint8_t *buffer = NULL;
1528
1529 if (session->mt_recv) {
1530 buflen = udp_recv_data(session->rtp_socket, (char **) &packet);
1531 buffer = ((uint8_t *) packet) + RTP_PACKET_HEADER_SIZE;
1532 } else {
1533 if (!session->opt->reuse_bufs || (packet == NULL)) {
1534 packet = (rtp_packet *) malloc(RTP_MAX_PACKET_LEN + (session->opt->record_source ? sizeof(struct sockaddr_storage) : 0));
1535 buffer = ((uint8_t *) packet) + RTP_PACKET_HEADER_SIZE;
1536 }
1537 struct sockaddr_storage *sin = NULL;
1538 socklen_t addrlen = 0;
1539 if (session->opt->record_source) {
1540 sin = (struct sockaddr_storage *)(void *) ((char *) packet + RTP_MAX_PACKET_LEN);
1541 addrlen = sizeof(struct sockaddr_storage);
1542 }
1543 buflen =
1544 udp_recvfrom(session->rtp_socket, (char *)buffer,
1546 (struct sockaddr *) sin, sin ? &addrlen : 0);
1547 if (buflen <= 0) {
1548 free(packet);
1549 }
1550 }
1551
1552 if (buflen > 0) {
1553 rtp_process_data(session, curr_rtp_ts, buffer, packet, buflen);
1554 }
1555
1556 return buflen;
1557}
int udp_recv_data(socket_udp *s, char **buffer)
Definition net_udp.c:1281
static void rtp_process_data(struct rtp *session, uint32_t curr_rtp_ts, uint8_t *buffer, rtp_packet *packet, int buflen)
Definition rtp.c:1559
rtp_packet
Definition rtp.h:126
#define RTP_PACKET_HEADER_SIZE
Definition rtp.h:128
int record_source
Definition rtp.c:258

References rtp::mt_recv, rtp::opt, options::record_source, options::reuse_bufs, RTP_MAX_PACKET_LEN, rtp_packet, RTP_PACKET_HEADER_SIZE, rtp_process_data(), rtp::rtp_socket, udp_recv_data(), and udp_recvfrom().

Referenced by rtp_recv(), rtp_recv_poll_r(), and rtp_recv_r().

Here is the call graph for this function:

◆ rtp_recv_poll_r()

int rtp_recv_poll_r ( struct rtp ** sessions,
struct timeval * timeout,
uint32_t curr_rtp_ts )

rtp_recv_poll_r: The meaning is as above with except that this function polls for first nonempty stream and returns data.

Parameters
sessionsnull-terminated list of rtp sessions.
timeouttimeout
cur_rtp_tslist null-terminated of timestamps for each session
Returns
received bytes

Definition at line 2434 of file rtp.c.

2435{
2436 struct rtp **current;
2437 struct udp_fd_r fd;
2438
2439 udp_fd_zero_r(&fd);
2440
2441 for(current = sessions; *current != NULL; ++current) {
2442 check_database(*current);
2443 udp_fd_set_r((*current)->rtp_socket, &fd);
2444 udp_fd_set_r((*current)->rtcp_socket, &fd);
2445 }
2446 if (udp_select_r(timeout, &fd) > 0) {
2447 int received_bytes = 0;
2448 for(current = sessions; *current != NULL; ++current) {
2449 if (udp_fd_isset_r((*current)->rtp_socket, &fd)) {
2450 received_bytes = rtp_recv_data(*current, curr_rtp_ts);
2451 }
2452 if (udp_fd_isset_r((*current)->rtcp_socket, &fd)) {
2453 uint8_t buffer[RTP_MAX_PACKET_LEN];
2454 int buflen;
2455 buflen =
2456 udp_recv((*current)->rtcp_socket, (char *)buffer,
2458 rtp_process_ctrl(*current, buffer, buflen);
2459 }
2460 check_database(*current);
2461 }
2462 return received_bytes;
2463 }
2464 //check_database(session);
2465 return 0;
2466}

References check_database(), RTP_MAX_PACKET_LEN, rtp_process_ctrl(), rtp_recv_data(), udp_fd_isset_r(), udp_fd_set_r(), udp_fd_zero_r(), udp_recv(), and udp_select_r().

Here is the call graph for this function:

◆ rtp_recv_r()

bool rtp_recv_r ( struct rtp * session,
struct timeval * timeout,
uint32_t curr_rtp_ts )

Receive RTP packets and dispatch them.

Reentrant variant of rtp_recv()

Currently, this function is the only one of rtp_recv family eligible for multithreaded receiving.

Parameters
sessionthe session pointer (returned by rtp_init())
timeoutthe amount of time that rtcp_recv() is allowed to block
curr_rtp_tsthe current time expressed in units of the media timestamp.
Return values
trueif data received
falseif the timeout occurred

Definition at line 2338 of file rtp.c.

2339{
2340 struct udp_fd_r fd;
2341
2342 check_database(session);
2343 if (session->mt_recv) {
2344 bool ret = false;
2345 if (udp_not_empty(session->rtp_socket, timeout)) {
2346 rtp_recv_data(session, curr_rtp_ts);
2347 ret = true;
2348 }
2349 udp_fd_zero_r(&fd);
2350 udp_fd_set_r(session->rtcp_socket, &fd);
2351 struct timeval no_wait_tv = { .tv_sec = 0, .tv_usec = 0 };
2352
2353 if (udp_select_r(&no_wait_tv, &fd) > 0) {
2354 uint8_t buffer[RTP_MAX_PACKET_LEN];
2355 int buflen;
2356 session->rtcp_dest_len = sizeof(session->rtcp_dest);
2357 buflen =
2358 udp_recvfrom(session->rtcp_socket, (char *)buffer,
2360 (struct sockaddr *) &session->rtcp_dest, &session->rtcp_dest_len);
2361 rtp_process_ctrl(session, buffer, buflen);
2362 ret = true;
2363 }
2364 return ret; // NOLINTNEXTLINE(readability-else-after-return)
2365 } else {
2366 udp_fd_zero_r(&fd);
2367 udp_fd_set_r(session->rtp_socket, &fd);
2368 udp_fd_set_r(session->rtcp_socket, &fd);
2369 if (udp_select_r(timeout, &fd) > 0) {
2370 if (udp_fd_isset_r(session->rtp_socket, &fd)) {
2371 rtp_recv_data(session, curr_rtp_ts);
2372 }
2373 if (udp_fd_isset_r(session->rtcp_socket, &fd)) {
2374 uint8_t buffer[RTP_MAX_PACKET_LEN];
2375 int buflen;
2376 session->rtcp_dest_len = sizeof(session->rtcp_dest);
2377 buflen =
2378 udp_recvfrom(session->rtcp_socket, (char *)buffer,
2380 (struct sockaddr *) &session->rtcp_dest, &session->rtcp_dest_len);
2381 rtp_process_ctrl(session, buffer, buflen);
2382 }
2383 check_database(session);
2384 return true;
2385 }
2386 }
2387 check_database(session);
2388 return false;
2389}
bool udp_not_empty(socket_udp *s, struct timeval *timeout)
Checks whether there are data ready to read in socket.
Definition net_udp.c:1197

References check_database(), rtp::mt_recv, rtp::rtcp_dest, rtp::rtcp_dest_len, rtp::rtcp_socket, RTP_MAX_PACKET_LEN, rtp_process_ctrl(), rtp_recv_data(), rtp::rtp_socket, udp_fd_isset_r(), udp_fd_set_r(), udp_fd_zero_r(), udp_not_empty(), udp_recvfrom(), and udp_select_r().

Referenced by audio_receiver_thread(), ultragrid_rtp_video_rxtx::receiver_loop(), h264_rtp_video_rxtx::send_frame(), h264_sdp_video_rxtx::send_frame(), and vidcap_rtsp_thread().

Here is the call graph for this function:

◆ rtp_send_bye()

void rtp_send_bye ( struct rtp * session)

rtp_send_bye: @session: The RTP session

Sends a BYE message on the RTP session, indicating that this participant is leaving the session. The process of sending a BYE may take some time, and this function will block until it is complete. During this time, RTCP events are reported to the application via the callback function (data packets are silently discarded).

Definition at line 3598 of file rtp.c.

3599{
3600 uint8_t buffer[RTP_MAX_PACKET_LEN];
3601 int buflen;
3602 double new_interval;
3603
3604 check_database(session);
3605
3606 /* "...a participant which never sent an RTP or RTCP packet MUST NOT send */
3607 /* a BYE packet when they leave the group." (section 6.3.7 of RTP spec) */
3608 if ((session->we_sent == FALSE) && (session->initial_rtcp == TRUE)) {
3609 debug_msg("Silent BYE\n");
3610 return;
3611 }
3612
3613 /* If the session is small, send an immediate BYE. Otherwise, we delay and */
3614 /* perform BYE reconsideration as needed. */
3615 if (session->ssrc_count < 50) {
3616 rtp_send_bye_now(session);
3617 } else {
3618 time_ns_t curr_time = get_time_in_ns();
3619 session->sending_bye = TRUE;
3620 session->last_rtcp_send_time =
3621 session->next_rtcp_send_time = curr_time;
3622 session->bye_count = 1;
3623 session->initial_rtcp = TRUE;
3624 session->we_sent = FALSE;
3625 session->sender_count = 0;
3626 session->avg_rtcp_size = 70.0 + RTP_LOWER_LAYER_OVERHEAD; /* FIXME */
3627 session->next_rtcp_send_time += (rtcp_interval(session) / (session->csrc_count + 1)) * NS_IN_SEC;
3628
3629 debug_msg("Preparing to send BYE...\n");
3630 while (1) {
3631 /* Schedule us to block in udp_select() until the time we are due to send our */
3632 /* BYE packet. If we receive an RTCP packet from another participant before */
3633 /* then, we are woken up to handle it... */
3634 long long us = (session->next_rtcp_send_time - curr_time) / NS_IN_US;
3635 lldiv_t d = lldiv(us, US_IN_SEC);
3636 struct timeval timeout = { .tv_sec = d.quot, .tv_usec = d.rem };
3637 udp_fd_zero();
3638 udp_fd_set(session->rtcp_socket);
3639 if ((udp_select(&timeout) > 0)
3640 && udp_fd_isset(session->rtcp_socket)) {
3641 /* We woke up because an RTCP packet was received; process it... */
3642 buflen =
3643 udp_recv(session->rtcp_socket,
3644 (char *)buffer,
3646 rtp_process_ctrl(session, buffer, buflen);
3647 }
3648 /* Is it time to send our BYE? */
3649 time_ns_t curr_time = get_time_in_ns();
3650 new_interval =
3651 rtcp_interval(session) / (session->csrc_count + 1);
3652 time_ns_t new_send_time = session->last_rtcp_send_time + new_interval * NS_IN_SEC;
3653 if (curr_time > new_send_time) {
3654 debug_msg("Sent BYE...\n");
3655 rtp_send_bye_now(session);
3656 break;
3657 }
3658 /* No, we reconsider... */
3659 session->next_rtcp_send_time = new_send_time;
3660 debug_msg("Reconsidered sending BYE... delay = %f\n",
3661 (session->next_rtcp_send_time - curr_time) / (double) NS_IN_SEC);
3662 /* ...and perform housekeeping in the usual manner */
3663 rtp_update(session, curr_time);
3664 }
3665 }
3666}
void rtp_update(struct rtp *session, time_ns_t curr_time)
Definition rtp.c:3456
static void rtp_send_bye_now(struct rtp *session)
Definition rtp.c:3525
#define US_IN_SEC
Definition tv.h:89
#define NS_IN_US
Definition tv.h:94

References rtp::avg_rtcp_size, rtp::bye_count, check_database(), rtp::csrc_count, debug_msg, FALSE, get_time_in_ns(), rtp::initial_rtcp, rtp::last_rtcp_send_time, rtp::next_rtcp_send_time, NS_IN_SEC, NS_IN_US, rtcp_interval(), rtp::rtcp_socket, RTP_LOWER_LAYER_OVERHEAD, RTP_MAX_PACKET_LEN, rtp_process_ctrl(), rtp_send_bye_now(), rtp_update(), rtp::sender_count, rtp::sending_bye, rtp::ssrc_count, TRUE, udp_fd_isset(), udp_fd_set(), udp_fd_zero(), udp_recv(), udp_select(), US_IN_SEC, and rtp::we_sent.

Here is the call graph for this function:

◆ rtp_send_bye_now()

static void rtp_send_bye_now ( struct rtp * session)
static

Definition at line 3525 of file rtp.c.

3526{
3527 /* Send a BYE packet immediately. This is an internal function, */
3528 /* hidden behind the rtp_send_bye() wrapper which implements BYE */
3529 /* reconsideration for the application. */
3530 uint8_t buffer[RTP_MAX_PACKET_LEN + MAX_ENCRYPTION_PAD]; /* + 8 to allow for padding when encrypting */
3531 uint8_t *ptr = buffer;
3532 rtcp_common *common;
3533 uint8_t initVec[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
3534
3535 check_database(session);
3536 /* If encryption is enabled, add a 32 bit random prefix to the packet */
3537 if (session->encryption_enabled) {
3538 *((uint32_t *)(void *) ptr) = ug_rand();
3539 ptr += 4;
3540 }
3541
3542 ptr = format_rtcp_rr(ptr, RTP_MAX_PACKET_LEN - (ptr - buffer), session);
3543 common = (rtcp_common *)(void *) ptr;
3544
3545 common->version = 2;
3546 common->p = 0;
3547 common->count = 1;
3548 common->pt = RTCP_BYE;
3549 common->length = htons(1);
3550 ptr += sizeof(rtcp_common);
3551
3552 *((uint32_t *)(void *) ptr) = htonl(session->my_ssrc);
3553 ptr += 4;
3554
3555 if (session->encryption_enabled) {
3556 if (((ptr - buffer) % session->encryption_pad_length) != 0) {
3557 /* Add padding to the last packet in the compound, if necessary. */
3558 /* We don't have to worry about overflowing the buffer, since we */
3559 /* intentionally allocated it 8 bytes longer to allow for this. */
3560 int padlen =
3561 session->encryption_pad_length -
3562 ((ptr - buffer) % session->encryption_pad_length);
3563 int i;
3564
3565 for (i = 0; i < padlen - 1; i++) {
3566 *(ptr++) = '\0';
3567 }
3568 *(ptr++) = (uint8_t) padlen;
3569
3570 common->p = TRUE;
3571 common->length =
3572 htons((int16_t)
3573 (((ptr - (uint8_t *) common) / 4) - 1));
3574 }
3575 assert(((ptr - buffer) % session->encryption_pad_length) == 0);
3576 (session->encrypt_func) (session, buffer, ptr - buffer,
3577 initVec);
3578 }
3579 rtcp_udp_send(session, ptr - buffer, (char *)buffer);
3580 /* Loop the data back to ourselves so local participant can */
3581 /* query own stats when using unicast or multicast with no */
3582 /* loopback. */
3583 rtp_process_ctrl(session, buffer, ptr - buffer);
3584 check_database(session);
3585}
static uint8_t * format_rtcp_rr(uint8_t *buffer, int buflen, struct rtp *session)
Definition rtp.c:3048
#define MAX_ENCRYPTION_PAD
Definition rtp.c:109
static void rtcp_udp_send(struct rtp *session, int len, char *buffer)
Definition rtp.c:3263

References check_database(), rtcp_common::count, rtp::encrypt_func, rtp::encryption_enabled, rtp::encryption_pad_length, format_rtcp_rr(), rtcp_common::length, MAX_ENCRYPTION_PAD, rtp::my_ssrc, rtcp_common::p, rtcp_common::pt, RTCP_BYE, rtcp_udp_send(), RTP_MAX_PACKET_LEN, rtp_process_ctrl(), TRUE, ug_rand(), and rtcp_common::version.

Referenced by rtp_send_bye().

Here is the call graph for this function:

◆ rtp_send_ctrl()

void rtp_send_ctrl ( struct rtp * session,
uint32_t rtp_ts,
rtcp_app_callback appcallback,
time_ns_t curr_time )

rtp_send_ctrl: @session: the session pointer (returned by rtp_init()) @rtp_ts: the current time expressed in units of the media timestamp. @appcallback: a callback to create an APP RTCP packet, if needed.

Checks RTCP timer and sends RTCP data when nececessary. The interval between RTCP packets is randomized over an interval that depends on the session bandwidth, the number of participants, and whether the local participant is a sender. This function should be called at least once per second, and can be safely called more frequently.

Definition at line 3409 of file rtp.c.

3411{
3412 /* Send an RTCP packet, if one is due... */
3413
3414 check_database(session);
3415 if (curr_time > session->next_rtcp_send_time) {
3416 /* The RTCP transmission timer has expired. The following */
3417 /* implements draft-ietf-avt-rtp-new-02.txt section 6.3.6 */
3418 int h;
3419 source *s;
3420 double new_interval =
3421 rtcp_interval(session) / (session->csrc_count + 1);
3422 time_ns_t new_send_time = session->last_rtcp_send_time + new_interval * NS_IN_SEC;
3423 if (curr_time > new_send_time) {
3424 send_rtcp(session, rtp_ts, appcallback);
3425 session->initial_rtcp = FALSE;
3426 session->last_rtcp_send_time = curr_time;
3427 session->next_rtcp_send_time = curr_time + (rtcp_interval(session) / (session->csrc_count +
3428 1)) * NS_IN_SEC;
3429 /* We're starting a new RTCP reporting interval, zero out */
3430 /* the per-interval statistics. */
3431 session->sender_count = 0;
3432 for (h = 0; h < RTP_DB_SIZE; h++) {
3433 for (s = session->db[h]; s != NULL; s = s->next) {
3434 check_source(s);
3435 s->sender = FALSE;
3436 }
3437 }
3438 } else {
3439 session->next_rtcp_send_time = new_send_time;
3440 }
3441 session->ssrc_count_prev = session->ssrc_count;
3442 }
3443 check_database(session);
3444}
static void send_rtcp(struct rtp *session, uint32_t rtp_ts, rtcp_app_callback appcallback)
Definition rtp.c:3284

References check_database(), check_source(), rtp::csrc_count, rtp::db, FALSE, rtp::initial_rtcp, rtp::last_rtcp_send_time, _source::next, rtp::next_rtcp_send_time, NS_IN_SEC, rtcp_interval(), RTP_DB_SIZE, send_rtcp(), _source::sender, rtp::sender_count, rtp::ssrc_count, and rtp::ssrc_count_prev.

Referenced by audio_receiver_thread(), audio_sender_thread(), audio_tx_send_standard(), ultragrid_rtp_video_rxtx::receiver_loop(), h264_rtp_video_rxtx::send_frame(), h264_sdp_video_rxtx::send_frame(), and ultragrid_rtp_video_rxtx::send_frame_async().

Here is the call graph for this function:

◆ rtp_send_data()

int rtp_send_data ( struct rtp * session,
uint32_t rtp_ts,
char pt,
int m,
int cc,
const uint32_t * csrc,
char * data,
int data_len,
char * extn,
uint16_t extn_len,
uint16_t extn_type )

rtp_send_data: @session: the session pointer (returned by rtp_init()) @rtp_ts: The timestamp reflects the sampling instant of the first octet of the RTP data to be sent. The timestamp is expressed in media units. @pt: The payload type identifying the format of the data. @m: Marker bit, interpretation defined by media profile of payload. @cc: Number of contributing sources (excluding local participant) @csrc: Array of SSRC identifiers for contributing sources. @data: The RTP data to be sent. @data_len: The size @data in bytes. @extn: Extension data (if present). @extn_len: size of @extn in bytes. @extn_type: extension type indicator.

Send an RTP packet. Most media applications will only set the @session, @rtp_ts, @pt, @m, @data, @data_len arguments.

Mixers and translators typically set additional contributing sources arguments (@cc, @csrc).

Extensions fields (@extn, @extn_len, @extn_type) are for including application specific information. When the widest amount of inter-operability is required these fields should be avoided as some applications discard packets with extensions they do not recognize.

Return value: Number of bytes transmitted.

Definition at line 2742 of file rtp.c.

2746{
2747 return rtp_send_data_hdr(session, rtp_ts, pt, m, cc, csrc, NULL, 0,
2748 data, data_len, extn, extn_len, extn_type);
2749}
int rtp_send_data_hdr(struct rtp *session, uint32_t rtp_ts, char pt, int m, int cc, const uint32_t *csrc, char *phdr, int phdr_len, char *data, int data_len, char *extn, uint16_t extn_len, uint16_t extn_type)
Definition rtp.c:2752

References rtp_send_data_hdr().

Referenced by audio_tx_send_standard(), and tx_send_h264().

Here is the call graph for this function:

◆ rtp_send_data_hdr()

int rtp_send_data_hdr ( struct rtp * session,
uint32_t rtp_ts,
char pt,
int m,
int cc,
const uint32_t * csrc,
char * phdr,
int phdr_len,
char * data,
int data_len,
char * extn,
uint16_t extn_len,
uint16_t extn_type )

Definition at line 2752 of file rtp.c.

2758{
2759 int vlen, buffer_len, i, rc, pad, pad_len __attribute__((unused));
2760 uint8_t *buffer = NULL;
2761 rtp_packet *packet = NULL;
2762 uint8_t initVec[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
2763#ifdef _WIN32
2764 WSABUF *send_vector = NULL;
2765#else
2766 struct iovec send_vector[3];
2767#endif
2768 int send_vector_len;
2769
2770 void *d; // to be freed after packet is sent
2771
2772 check_database(session);
2773
2774 assert((data == NULL && data_len == 0)
2775 || (data != NULL && data_len > 0));
2776
2777 vlen = 12;
2778 if (session->tfrc_on) {
2779 vlen += 4;
2780 if (session->new_rtt)
2781 vlen += 4;
2782 }
2783 buffer_len = vlen + (4 * cc);
2784
2785 if (extn != NULL) {
2786 buffer_len += (extn_len + 1) * 4;
2787 }
2788
2789 /* Do we need to pad this packet to a multiple of 64 bits? */
2790 /* This is only needed if encryption is enabled, since DES */
2791 /* only works on multiples of 64 bits. We just calculate */
2792 /* the amount of padding to add here, so we can reserve */
2793 /* space - the actual padding is added later. */
2794#ifdef NDEF
2795 /* FIXME: This is broken, due to scatter send [csp] *//* FIXME */
2796 if ((session->encryption_enabled) &&
2797 ((buffer_len % session->encryption_pad_length) != 0)) {
2798 pad = TRUE;
2799 pad_len =
2800 session->encryption_pad_length -
2801 (buffer_len % session->encryption_pad_length);
2802 buffer_len += pad_len;
2803 assert((buffer_len % session->encryption_pad_length) == 0);
2804 } else {
2805 pad = FALSE;
2806 pad_len = 0;
2807 }
2808#endif
2809 pad = FALSE; /* FIXME */
2810 pad_len = 0;
2811
2812 /* Allocate memory for the packet... */
2813 assert(buffer_len < RTP_MAX_PACKET_LEN);
2814 /* we dont always need 20 (12|16) but this seems to work. LG */
2815#ifdef _WIN32
2816 d = (uint8_t *) malloc(3 * sizeof(WSABUF) + 20 + RTP_PACKET_HEADER_SIZE);
2817 send_vector = d;
2818 buffer = (uint8_t *) d + 3 * sizeof(WSABUF);
2819#else
2820 d = buffer = (uint8_t *) malloc(20 + RTP_PACKET_HEADER_SIZE);
2821#endif
2822 packet = (rtp_packet *)(void *) buffer;
2823
2824#ifdef _WIN32
2825 send_vector[0].buf = (char *) (buffer + RTP_PACKET_HEADER_SIZE);
2826 send_vector[0].len = buffer_len;
2827#else
2828 send_vector[0].iov_base = buffer + RTP_PACKET_HEADER_SIZE;
2829 send_vector[0].iov_len = buffer_len;
2830#endif
2831 send_vector_len = 1;
2832
2833 /* These are internal pointers into the buffer... */
2834#ifdef NDEF
2835 packet->csrc = (uint32_t *) (buffer + RTP_PACKET_HEADER_SIZE + vlen);
2836 packet->extn =
2837 (uint8_t *) (buffer + RTP_PACKET_HEADER_SIZE + vlen + (4 * cc));
2838 packet->data =
2839 (uint8_t *) (buffer + RTP_PACKET_HEADER_SIZE + vlen + (4 * cc));
2840 if (extn != NULL) {
2841 packet->data += (extn_len + 1) * 4;
2842 }
2843#endif
2844 /* ...and the actual packet header... */
2845 packet->v = 2;
2846 packet->p = pad;
2847 packet->x = (extn != NULL);
2848 packet->cc = cc;
2849 packet->m = m;
2850 packet->pt = pt;
2851 packet->seq = htons(session->rtp_seq++);
2852 packet->ts = htonl(rtp_ts);
2853 packet->ssrc = htonl(session->my_ssrc);
2854
2855 /* ... do tfrc stuff... */
2856 if (session->tfrc_on) {
2857 packet->send_ts = htonl(get_local_mediatime());
2858 if (session->new_rtt) {
2859 packet->rtt = htonl(session->cmp_rtt);
2860 /* hopefully this will set the 7th bit */
2861 packet->pt = packet->pt | 64;
2862 } else
2863 packet->pt = packet->pt & 63; /* this should clear the 7th bit */
2864 }
2865
2866 /* ...now the CSRC list... */
2867 for (i = 0; i < cc; i++) {
2868 packet->csrc[i] = htonl(csrc[i]);
2869 }
2870 /* ...a header extension? */
2871 if (extn != NULL) {
2872 /* We don't use the packet->extn_type field here, that's for receive only... */
2873 uint16_t *base = (uint16_t *)(void *) packet->extn;
2874 base[0] = htons(extn_type);
2875 base[1] = htons(extn_len);
2876 memcpy(packet->extn + 4, extn, extn_len * 4);
2877 }
2878 /* ...the payload header... */
2879 if (phdr != NULL) {
2880#ifdef _WIN32
2881 send_vector[send_vector_len].buf = phdr;
2882 send_vector[send_vector_len].len = phdr_len;
2883#else
2884 send_vector[send_vector_len].iov_base = phdr;
2885 send_vector[send_vector_len].iov_len = phdr_len;
2886#endif
2887 send_vector_len++;
2888 }
2889 /* ...and the media data... */
2890 if (data_len > 0) {
2891#ifdef _WIN32
2892 send_vector[send_vector_len].buf = (void *) data;
2893 send_vector[send_vector_len].len = data_len;
2894#else
2895 send_vector[send_vector_len].iov_base = (void *) data;
2896 send_vector[send_vector_len].iov_len = data_len;
2897#endif
2898 send_vector_len++;
2899 }
2900#ifdef NDEF /* FIXME */
2901 /* ...and any padding... */
2902 if (pad) {
2903 for (i = 0; i < pad_len; i++) {
2904 buffer[buffer_len + RTP_PACKET_HEADER_SIZE - pad_len +
2905 i] = 0;
2906 }
2907 buffer[buffer_len + RTP_PACKET_HEADER_SIZE - 1] = (char)pad_len;
2908 }
2909#endif
2910
2911 /* Finally, encrypt if desired... */
2912 if (session->encryption_enabled) {
2913 assert((buffer_len % session->encryption_pad_length) == 0);
2914 (session->encrypt_func) (session,
2915 buffer + RTP_PACKET_HEADER_SIZE,
2916 buffer_len, initVec);
2917 }
2918
2919 rc = udp_sendv(session->rtp_socket, send_vector, send_vector_len, d);
2920 if (rc == -1) {
2921 log_msg(LOG_LEVEL_WARNING, "sending RTP packet: %s", ug_strerror(errno));
2922 }
2923
2924 /* Update the RTCP statistics... */
2925 session->we_sent = TRUE;
2926 session->rtp_pcount += 1;
2927 session->rtp_bcount += buffer_len;
2928 session->rtp_bytes_sent += buffer_len + data_len;
2930
2931 check_database(session);
2932 return rc;
2933}
int udp_sendv(socket_udp *s, struct iovec *vector, int count, void *d)
Definition net_udp.c:1067
struct __attribute__((packed))
Definition rtp.h:88
time_ns_t last_rtp_send_time
Definition rtp.c:299
uint16_t new_rtt
Definition rtp.c:313
uint32_t cmp_rtt
Definition rtp.c:312
uint32_t get_local_mediatime(void)
Definition tv.c:65

References __attribute__(), check_database(), rtp::cmp_rtt, rtp::encrypt_func, rtp::encryption_enabled, rtp::encryption_pad_length, FALSE, get_local_mediatime(), get_time_in_ns(), rtp::last_rtp_send_time, LOG_LEVEL_WARNING, log_msg(), rtp::my_ssrc, rtp::new_rtt, rtp::rtp_bcount, rtp::rtp_bytes_sent, RTP_MAX_PACKET_LEN, rtp_packet, RTP_PACKET_HEADER_SIZE, rtp::rtp_pcount, rtp::rtp_seq, rtp::rtp_socket, rtp::tfrc_on, TRUE, udp_sendv(), ug_strerror(), and rtp::we_sent.

Referenced by audio_tx_send_chan(), rtp_send_data(), tx_send_base(), tx_send_h264(), and tx_send_jpeg().

Here is the call graph for this function:

◆ rtp_send_raw_rtp_data()

int rtp_send_raw_rtp_data ( struct rtp * session,
char * buffer,
int buffer_len )

Definition at line 1518 of file rtp.c.

1519{
1520 return udp_send(session->rtp_socket, buffer, buffer_len);
1521}

References rtp::rtp_socket, and udp_send().

Here is the call graph for this function:

◆ rtp_set_encryption_key()

bool rtp_set_encryption_key ( struct rtp * session,
const char * passphrase )

rtp_set_encryption_key: @session: The RTP session. @passphrase: The user-provided "pass phrase" to map to an encryption key.

Converts the user supplied key into a form suitable for use with RTP and install it as the active key. Passing in NULL as the passphrase disables encryption. The passphrase is converted into a DES key as specified in RFC1890, that is:

  • convert to canonical form
  • derive an MD5 hash of the canonical form
  • take the first 56 bits of the MD5 hash
  • add parity bits to form a 64 bit key

Note that versions of rat prior to 4.1.2 do not convert the passphrase to canonical form before taking the MD5 hash, and so will not be compatible for keys which are non-invarient under this step.

Determine from the user's encryption key which encryption mechanism we're using. Per the RTP RFC, if the key is of the form

 string/key

then "string" is the name of the encryption algorithm, and "key" is the key to be used. If no / is present, then the algorithm is assumed to be (the appropriate variant of) DES.

Definition at line 3742 of file rtp.c.

3743{
3744 char *canonical_passphrase;
3745 u_char hash[16];
3746 MD5CTX context;
3747 char *slash;
3748
3749 check_database(session);
3750 if (session->encryption_algorithm != NULL) {
3751 free(session->encryption_algorithm);
3752 session->encryption_algorithm = NULL;
3753 }
3754
3755 if (passphrase == NULL) {
3756 /* A NULL passphrase means disable encryption... */
3757 session->encryption_enabled = 0;
3758 check_database(session);
3759 return true;
3760 }
3761
3762 debug_msg("Enabling RTP/RTCP encryption\n");
3763 session->encryption_enabled = 1;
3764
3765 /*
3766 * Determine which algorithm we're using.
3767 */
3768
3769 slash = strchr(passphrase, '/');
3770 if (slash == 0) {
3771 session->encryption_algorithm = strdup("DES");
3772 } else {
3773 int l = slash - passphrase;
3774 session->encryption_algorithm = malloc(l + 1);
3775 strncpy(session->encryption_algorithm, passphrase, l);
3776 session->encryption_algorithm[l] = '\0';
3777 passphrase = slash + 1;
3778 }
3779
3780 debug_msg("Initializing encryption, algorithm is '%s'\n",
3781 session->encryption_algorithm);
3782
3783 /* Step 1: convert to canonical form, comprising the following steps: */
3784 /* a) convert the input string to the ISO 10646 character set, using */
3785 /* the UTF-8 encoding as specified in Annex P to ISO/IEC */
3786 /* 10646-1:1993 (ASCII characters require no mapping, but ISO */
3787 /* 8859-1 characters do); */
3788 /* b) remove leading and trailing white space characters; */
3789 /* c) replace one or more contiguous white space characters by a */
3790 /* single space (ASCII or UTF-8 0x20); */
3791 /* d) convert all letters to lower case and replace sequences of */
3792 /* characters and non-spacing accents with a single character, */
3793 /* where possible. */
3794 canonical_passphrase = strdup(passphrase); /* FIXME */
3795
3796 /* Step 2: derive an MD5 hash */
3797 MD5Init(&context);
3798 MD5Update(&context, (u_char *) canonical_passphrase,
3799 strlen(canonical_passphrase));
3800 MD5Final((u_char *) hash, &context);
3801 free(canonical_passphrase);
3802
3803 /* Initialize the encryption algorithm we've received */
3804
3805 if (strcmp(session->encryption_algorithm, "DES") == 0) {
3806 return des_initialize(session, hash, sizeof(hash)); // NOLINTNEXTLINE(readability-else-after-return)
3807 } else if (strcmp(session->encryption_algorithm, "Rijndael") == 0) {
3808 return rijndael_initialize(session, hash, sizeof(hash)); // NOLINTNEXTLINE(readability-else-after-return)
3809 } else {
3810 debug_msg("Encryption algorithm \"%s\" not found\n",
3811 session->encryption_algorithm);
3812 return false;
3813 }
3814}
void MD5Update(MD5CTX *context, const unsigned char *input, unsigned int inputLen)
Definition md5.c:249
void MD5Final(unsigned char digest[16], MD5CTX *context)
Definition md5.c:295
void MD5Init(MD5CTX *context)
Definition md5.c:229
static bool des_initialize(struct rtp *session, const u_char *hash, int hash_len)
Definition rtp.c:3816
static bool rijndael_initialize(struct rtp *session, const u_char *hash, int hash_len)
Definition rtp.c:3871
Definition md5.h:34

References check_database(), debug_msg, des_initialize(), rtp::encryption_algorithm, rtp::encryption_enabled, MD5Final(), MD5Init(), MD5Update(), and rijndael_initialize().

Here is the call graph for this function:

◆ rtp_set_my_ssrc()

bool rtp_set_my_ssrc ( struct rtp * session,
uint32_t ssrc )

rtp_set_my_ssrc: @session: the RTP session @ssrc: the SSRC to be used by the RTP session

This function coerces the local SSRC identifer to be ssrc. For this function to succeed it must be called immediately after rtp_init or rtp_init_if. The intended purpose of this function is to co-ordinate SSRC's between layered sessions, it should not be used otherwise.

Definition at line 1278 of file rtp.c.

1279{
1280 source *s;
1281 uint32_t h;
1282
1283 if (session->ssrc_count != 1 && session->sender_count != 0) {
1284 return false;
1285 }
1286 /* Remove existing source */
1287 h = ssrc_hash(session->my_ssrc);
1288 s = session->db[h];
1289 session->db[h] = NULL;
1290 /* Fill in new ssrc */
1291 session->my_ssrc = ssrc;
1292 s->ssrc = ssrc;
1293 h = ssrc_hash(ssrc);
1294 /* Put source back */
1295 session->db[h] = s;
1296 return true;
1297}

References rtp::db, rtp::my_ssrc, rtp::sender_count, _source::ssrc, rtp::ssrc_count, and ssrc_hash().

Here is the call graph for this function:

◆ rtp_set_option()

bool rtp_set_option ( struct rtp * session,
rtp_option optname,
int optval )

rtp_set_option: @session: The RTP session. @optname: The option name, see rtp_option. @optval: The value to set.

Sets the value of a session option. See rtp_option for documentation on the options and their legal values.

Definition at line 1308 of file rtp.c.

1309{
1310 switch (optname) {
1312 session->opt->wait_for_rtcp = optval;
1313 break;
1314 case RTP_OPT_PROMISC:
1315 session->opt->promiscuous_mode = optval;
1316 break;
1318 session->opt->filter_my_packets = optval;
1319 break;
1321 session->opt->reuse_bufs = optval;
1322 break;
1324 session->opt->record_source = optval;
1325 break;
1326 case RTP_OPT_SEND_BACK:
1327 session->opt->send_back = optval;
1328 if (optval) {
1329 session->opt->record_source = TRUE;
1330 }
1331 break;
1332 default:
1333 debug_msg
1334 ("Ignoring unknown option (%d) in call to rtp_set_option().\n",
1335 optname);
1336 return false;
1337 }
1338 return true;
1339}

References debug_msg, options::filter_my_packets, rtp::opt, options::promiscuous_mode, options::record_source, options::reuse_bufs, RTP_OPT_FILTER_MY_PACKETS, RTP_OPT_PROMISC, RTP_OPT_RECORD_SOURCE, RTP_OPT_REUSE_PACKET_BUFS, RTP_OPT_SEND_BACK, RTP_OPT_WEAK_VALIDATION, options::send_back, TRUE, and options::wait_for_rtcp.

Referenced by init_opt(), initialize_audio_network(), rtp_video_rxtx::initialize_network(), and vidcap_rtsp_init().

◆ rtp_set_recv_buf()

bool rtp_set_recv_buf ( struct rtp * session,
int bufsize )

Sets receiver buffer size

Parameters
sessionthe RTP Session
bufsizerequested recv network buffer size

Definition at line 3938 of file rtp.c.

3939{
3940 return udp_set_recv_buf(session->rtp_socket, bufsize);
3941}
bool udp_set_recv_buf(socket_udp *s, int size)
Definition net_udp.c:1486

References rtp::rtp_socket, and udp_set_recv_buf().

Referenced by audio_update_recv_buf(), initialize_audio_network(), rtp_video_rxtx::initialize_network(), ultragrid_rtp_video_rxtx::receiver_loop(), and vidcap_rtsp_init().

Here is the call graph for this function:

◆ rtp_set_recv_iov()

void rtp_set_recv_iov ( struct rtp * session,
struct msghdr * m )

Definition at line 1513 of file rtp.c.

1514{
1515 session->mhdr = m;
1516}

References rtp::mhdr.

◆ rtp_set_sdes()

bool rtp_set_sdes ( struct rtp * session,
uint32_t ssrc,
rtcp_sdes_type type,
const char * value,
int length )

rtp_set_sdes: @session: the session pointer (returned by rtp_init()) @ssrc: the SSRC identifier of a participant @type: the SDES type represented by @value @value: the SDES description @length: the length of the description

Sets session description information associated with participant @ssrc. Under normal circumstances applications always use the @ssrc of the local participant, this SDES information is transmitted in receiver reports. Setting SDES information for other participants affects the local SDES entries, but are not transmitted onto the network.

Return values
returnstrue if participant exists, false otherwise.

Definition at line 2546 of file rtp.c.

2548{
2549 source *s;
2550 char *v;
2551
2552 check_database(session);
2553
2554 s = get_source(session, ssrc);
2555 if (s == NULL) {
2556 debug_msg("Invalid source 0x%08x\n", ssrc);
2557 return false;
2558 }
2559 check_source(s);
2560
2561 v = (char *)malloc(length + 1);
2562 memset(v, '\0', length + 1);
2563 memcpy(v, value, length);
2564
2565 switch (type) {
2566 case RTCP_SDES_CNAME:
2567 if (s->sdes_cname)
2568 free(s->sdes_cname);
2569 s->sdes_cname = v;
2570 break;
2571 case RTCP_SDES_NAME:
2572 if (s->sdes_name)
2573 free(s->sdes_name);
2574 s->sdes_name = v;
2575 break;
2576 case RTCP_SDES_EMAIL:
2577 if (s->sdes_email)
2578 free(s->sdes_email);
2579 s->sdes_email = v;
2580 break;
2581 case RTCP_SDES_PHONE:
2582 if (s->sdes_phone)
2583 free(s->sdes_phone);
2584 s->sdes_phone = v;
2585 break;
2586 case RTCP_SDES_LOC:
2587 if (s->sdes_loc)
2588 free(s->sdes_loc);
2589 s->sdes_loc = v;
2590 break;
2591 case RTCP_SDES_TOOL:
2592 if (s->sdes_tool)
2593 free(s->sdes_tool);
2594 s->sdes_tool = v;
2595 break;
2596 case RTCP_SDES_NOTE:
2597 if (s->sdes_note)
2598 free(s->sdes_note);
2599 s->sdes_note = v;
2600 break;
2601 case RTCP_SDES_PRIV:
2602 if (s->sdes_priv)
2603 free(s->sdes_priv);
2604 s->sdes_priv = v;
2605 break;
2606 default:
2607 debug_msg("Unknown SDES item (type=%d, value=%s)\n", type, v);
2608 free(v);
2609 check_database(session);
2610 return false;
2611 }
2612 check_database(session);
2613 return true;
2614}

References check_database(), check_source(), debug_msg, get_source(), RTCP_SDES_CNAME, RTCP_SDES_EMAIL, RTCP_SDES_LOC, RTCP_SDES_NAME, RTCP_SDES_NOTE, RTCP_SDES_PHONE, RTCP_SDES_PRIV, RTCP_SDES_TOOL, _source::sdes_cname, _source::sdes_email, _source::sdes_loc, _source::sdes_name, _source::sdes_note, _source::sdes_phone, _source::sdes_priv, _source::sdes_tool, and type.

Referenced by initialize_audio_network(), rtp_video_rxtx::initialize_network(), process_rtcp_sdes(), rtp_init_if(), rtp_init_with_udp_socket(), and vidcap_rtsp_init().

Here is the call graph for this function:

◆ rtp_set_send_buf()

bool rtp_set_send_buf ( struct rtp * session,
int bufsize )

Sets sender buffer size

Parameters
sessionthe RTP Session
bufsizerequested send network buffer size

Definition at line 3954 of file rtp.c.

3955{
3956 return udp_set_send_buf(session->rtp_socket, bufsize);
3957}
bool udp_set_send_buf(socket_udp *s, int size)
Definition net_udp.c:1492

References rtp::rtp_socket, and udp_set_send_buf().

Referenced by rtp_video_rxtx::initialize_network(), and vidcap_rtsp_init().

Here is the call graph for this function:

◆ rtp_update()

void rtp_update ( struct rtp * session,
time_ns_t curr_time )

rtp_update: @session: the session pointer (returned by rtp_init())

Trawls through the internal data structures and performs housekeeping. This function should be called at least once per second. It uses an internal timer to limit the number of passes through the data structures to once per second, it can be safely called more frequently.

Definition at line 3456 of file rtp.c.

3457{
3458 /* Perform housekeeping on the source database... */
3459 int h;
3460 source *s, *n;
3461
3462 if (curr_time - session->last_update < 1 * NS_IN_SEC) {
3463 /* We only perform housekeeping once per second... */
3464 return;
3465 }
3466 session->last_update = curr_time;
3467
3468 /* Update we_sent (section 6.3.8 of RTP spec) */
3469 time_ns_t delay = curr_time - session->last_rtp_send_time;
3470 if (delay >= 2 * NS_IN_SEC * rtcp_interval(session)) {
3471 session->we_sent = FALSE;
3472 }
3473
3474 check_database(session);
3475
3476 for (h = 0; h < RTP_DB_SIZE; h++) {
3477 for (s = session->db[h]; s != NULL; s = n) {
3478 check_source(s);
3479 n = s->next;
3480 /* Expire sources which haven't been heard from for a int time. */
3481 /* Section 6.2.1 of the RTP specification details the timers used. */
3482
3483 /* How int since we last heard from this source? */
3484 delay = curr_time - s->last_active;
3485
3486 /* Check if we've received a BYE packet from this source. */
3487 /* If we have, and it was received more than 2 seconds ago */
3488 /* then the source is deleted. The arbitrary 2 second delay */
3489 /* is to ensure that all delayed packets are received before */
3490 /* the source is timed out. */
3491 if (s->got_bye && (delay > 2 * NS_IN_SEC)) {
3492 debug_msg
3493 ("Deleting source 0x%08" PRIx32 " due to reception of BYE %f seconds ago...\n",
3494 s->ssrc, (double) delay / NS_IN_SEC);
3495 delete_source(session, s->ssrc);
3496 }
3497
3498 /* Sources are marked as inactive if they haven't been heard */
3499 /* from for more than 2 intervals (RTP section 6.3.5) */
3500 if ((s->ssrc != rtp_my_ssrc(session))
3501 && (delay > (session->rtcp_interval * 2 * NS_IN_SEC))) {
3502 if (s->sender) {
3503 s->sender = FALSE;
3504 session->sender_count--;
3505 }
3506 }
3507
3508 /* If a source hasn't been heard from for more than 5 RTCP */
3509 /* reporting intervals, we delete it from our database... */
3510 if ((s->ssrc != rtp_my_ssrc(session))
3511 && (delay > (session->rtcp_interval * 5 * NS_IN_SEC))) {
3512 debug_msg
3513 ("Deleting source 0x%08" PRIx32 " due to timeout...\n",
3514 s->ssrc);
3515 delete_source(session, s->ssrc);
3516 }
3517 }
3518 }
3519
3520 /* Timeout those reception reports which haven't been refreshed for a int time */
3521 timeout_rr(session, curr_time);
3522 check_database(session);
3523}
static void timeout_rr(struct rtp *session, time_ns_t curr_ts)
Definition rtp.c:474

References check_database(), check_source(), rtp::db, debug_msg, delete_source(), FALSE, _source::got_bye, _source::last_active, rtp::last_rtp_send_time, rtp::last_update, _source::next, NS_IN_SEC, rtcp_interval(), rtp::rtcp_interval, RTP_DB_SIZE, rtp_my_ssrc(), _source::sender, rtp::sender_count, _source::ssrc, timeout_rr(), and rtp::we_sent.

Referenced by audio_receiver_thread(), audio_sender_thread(), ultragrid_rtp_video_rxtx::receiver_loop(), rtp_send_bye(), h264_rtp_video_rxtx::send_frame(), h264_sdp_video_rxtx::send_frame(), ultragrid_rtp_video_rxtx::send_frame_async(), and vidcap_rtsp_thread().

Here is the call graph for this function:

◆ send_rtcp()

static void send_rtcp ( struct rtp * session,
uint32_t rtp_ts,
rtcp_app_callback appcallback )
static

Definition at line 3284 of file rtp.c.

3286{
3287 /* Construct and send an RTCP packet. The order in which packets are packed into a */
3288 /* compound packet is defined by section 6.1 of draft-ietf-avt-rtp-new-03.txt and */
3289 /* we follow the recommended order. */
3290 uint8_t buffer[RTP_MAX_PACKET_LEN + MAX_ENCRYPTION_PAD]; /* The +8 is to allow for padding when encrypting */
3291 uint8_t *ptr = buffer;
3292 uint8_t *old_ptr;
3293 uint8_t *lpt; /* the last packet in the compound */
3294 rtcp_app *app;
3295 uint8_t initVec[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
3296
3297 check_database(session);
3298 /* If encryption is enabled, add a 32 bit random prefix to the packet */
3299 if (session->encryption_enabled) {
3300 *((uint32_t *)(void *) ptr) = ug_rand();
3301 ptr += 4;
3302 }
3303
3304 /* The first RTCP packet in the compound packet MUST always be a report packet... */
3305 if (session->we_sent) {
3306 ptr =
3307 format_rtcp_sr(ptr, RTP_MAX_PACKET_LEN - (ptr - buffer),
3308 session, rtp_ts);
3309 } else {
3310 ptr =
3311 format_rtcp_rr(ptr, RTP_MAX_PACKET_LEN - (ptr - buffer),
3312 session);
3313 }
3314 /* Add the appropriate SDES items to the packet... This should really be after the */
3315 /* insertion of the additional report blocks, but if we do that there are problems */
3316 /* with us being unable to fit the SDES packet in when we run out of buffer space */
3317 /* adding RRs. The correct fix would be to calculate the length of the SDES items */
3318 /* in advance and subtract this from the buffer length but this is non-trivial and */
3319 /* probably not worth it. */
3320 lpt = ptr;
3321 ptr =
3322 format_rtcp_sdes(ptr, RTP_MAX_PACKET_LEN - (ptr - buffer),
3323 rtp_my_ssrc(session), session);
3324
3325 /* If we have any CSRCs, we include SDES items for each of them in turn... */
3326 if (session->csrc_count > 0) {
3327 ptr =
3328 format_rtcp_sdes(ptr, RTP_MAX_PACKET_LEN - (ptr - buffer),
3329 next_csrc(session), session);
3330 }
3331
3332 /* Following that, additional RR packets SHOULD follow if there are more than 31 */
3333 /* senders, such that the reports do not fit into the initial packet. We give up */
3334 /* if there is insufficient space in the buffer: this is bad, since we always drop */
3335 /* the reports from the same sources (those at the end of the hash table). */
3336 while ((session->sender_count > 0)
3337 && ((RTP_MAX_PACKET_LEN - (ptr - buffer)) >= 8)) {
3338 lpt = ptr;
3339 ptr =
3340 format_rtcp_rr(ptr, RTP_MAX_PACKET_LEN - (ptr - buffer),
3341 session);
3342 }
3343
3344 /* Finish with as many APP packets as the application will provide. */
3345 old_ptr = ptr;
3346 if (appcallback) {
3347 while ((app =
3348 (*appcallback) (session, rtp_ts,
3349 RTP_MAX_PACKET_LEN - (ptr - buffer)))) {
3350 lpt = ptr;
3351 ptr =
3352 format_rtcp_app(ptr,
3353 RTP_MAX_PACKET_LEN - (ptr - buffer),
3354 rtp_my_ssrc(session), app);
3355 assert(ptr > old_ptr);
3356 old_ptr = ptr;
3357 assert(RTP_MAX_PACKET_LEN - (ptr - buffer) >= 0);
3358 }
3359 }
3360
3361 /* And encrypt if desired... */
3362 if (session->encryption_enabled) {
3363 if (((ptr - buffer) % session->encryption_pad_length) != 0) {
3364 /* Add padding to the last packet in the compound, if necessary. */
3365 /* We don't have to worry about overflowing the buffer, since we */
3366 /* intentionally allocated it 8 bytes longer to allow for this. */
3367 int padlen =
3368 session->encryption_pad_length -
3369 ((ptr - buffer) % session->encryption_pad_length);
3370 int i;
3371
3372 for (i = 0; i < padlen - 1; i++) {
3373 *(ptr++) = '\0';
3374 }
3375 *(ptr++) = (uint8_t) padlen;
3376 assert(((ptr -
3377 buffer) % session->encryption_pad_length) ==
3378 0);
3379
3380 ((rtcp_t *)(void *) lpt)->common.p = TRUE;
3381 ((rtcp_t *)(void *) lpt)->common.length =
3382 htons((int16_t) (((ptr - lpt) / 4) - 1));
3383 }
3384 (session->encrypt_func) (session, buffer, ptr - buffer,
3385 initVec);
3386 }
3387
3388 rtcp_udp_send(session, ptr - buffer, (char *)buffer);
3389 /* Loop the data back to ourselves so local participant can */
3390 /* query own stats when using unicast or multicast with no */
3391 /* loopback. */
3392 rtp_process_ctrl(session, buffer, ptr - buffer);
3393 check_database(session);
3394}
static uint8_t * format_rtcp_sr(uint8_t *buffer, int buflen, struct rtp *session, uint32_t rtp_ts)
Definition rtp.c:3012
static uint32_t next_csrc(struct rtp *session)
Definition rtp.c:344
static uint8_t * format_rtcp_app(uint8_t *buffer, int buflen, uint32_t ssrc, rtcp_app *app)
Definition rtp.c:3234
static uint8_t * format_rtcp_sdes(uint8_t *buffer, int buflen, uint32_t ssrc, struct rtp *session)
Definition rtp.c:3094

References app, check_database(), rtp::csrc_count, rtp::encrypt_func, rtp::encryption_enabled, rtp::encryption_pad_length, format_rtcp_app(), format_rtcp_rr(), format_rtcp_sdes(), format_rtcp_sr(), MAX_ENCRYPTION_PAD, next_csrc(), rtcp_udp_send(), RTP_MAX_PACKET_LEN, rtp_my_ssrc(), rtp_process_ctrl(), rtp::sender_count, TRUE, ug_rand(), and rtp::we_sent.

Referenced by rtp_send_ctrl().

Here is the call graph for this function:

◆ ssrc_hash()

static int ssrc_hash ( uint32_t ssrc)
inlinestatic

Definition at line 371 of file rtp.c.

372{
373 /* Hash from an ssrc to a position in the source database. */
374 /* Assumes that ssrc values are uniformly distributed, which */
375 /* should be true but probably isn't (Rosenberg has reported */
376 /* that many implementations generate ssrc values which are */
377 /* not uniformly distributed over the space, and the H.323 */
378 /* spec requires that they are non-uniformly distributed). */
379 /* This routine is written as a function rather than inline */
380 /* code to allow it to be made smart in future: probably we */
381 /* should run MD5 on the ssrc and derive a hash value from */
382 /* that, to ensure it's more uniformly distributed? */
383 return ssrc % RTP_DB_SIZE;
384}

References RTP_DB_SIZE.

Referenced by check_database(), delete_source(), get_rr(), get_source(), insert_rr(), really_create_source(), remove_rr(), and rtp_set_my_ssrc().

◆ timeout_rr()

static void timeout_rr ( struct rtp * session,
time_ns_t curr_ts )
static

Definition at line 474 of file rtp.c.

475{
476 /* Timeout any reception reports which have been in the database for more than 3 */
477 /* times the RTCP reporting interval without refresh. */
478 rtcp_rr_wrapper *start, *cur, *tmp;
479 rtp_event event;
480 int i, j;
481
482 for (i = 0; i < RTP_DB_SIZE; i++) {
483 for (j = 0; j < RTP_DB_SIZE; j++) {
484 start = &session->rr[i][j];
485 cur = start->next;
486 while (cur != start) {
487 if (curr_ts - cur->ts >
488 session->rtcp_interval * 3 * NS_IN_SEC) {
489 /* Signal the application... */
490 if (!filter_event
491 (session, cur->reporter_ssrc)) {
492 event.ssrc = cur->reporter_ssrc;
493 event.type = RR_TIMEOUT;
494 event.data = cur->rr;
495 session->callback(session,
496 &event);
497 }
498 /* Delete this reception report... */
499 tmp = cur;
500 cur = cur->prev;
501 tmp->prev->next = tmp->next;
502 tmp->next->prev = tmp->prev;
503 free(tmp->rr);
504 free(tmp);
505 }
506 cur = cur->next;
507 }
508 }
509 }
510}
@ RR_TIMEOUT
Definition rtp.h:192

References rtp::callback, filter_event(), _rtcp_rr_wrapper::next, NS_IN_SEC, _rtcp_rr_wrapper::prev, _rtcp_rr_wrapper::reporter_ssrc, _rtcp_rr_wrapper::rr, rtp::rr, RR_TIMEOUT, rtp::rtcp_interval, RTP_DB_SIZE, start(), and _rtcp_rr_wrapper::ts.

Referenced by rtp_update().

Here is the call graph for this function:

◆ update_seq()

static int update_seq ( source * s,
uint16_t seq )
static

Definition at line 778 of file rtp.c.

779{
780 /* Taken from draft-ietf-avt-rtp-new-01.txt */
781 uint16_t udelta = seq - s->max_seq;
782
783 /*
784 * Source is not valid until MIN_SEQUENTIAL packets with
785 * sequential sequence numbers have been received.
786 */
787 check_source(s);
788 if (s->probation) {
789 /* packet is in sequence */
790 if (seq == s->max_seq + 1) {
791 s->probation--;
792 s->max_seq = seq;
793 if (s->probation == 0) {
794 init_seq(s, seq);
795 s->received++;
796 return 1;
797 }
798 } else {
799 s->probation = MIN_SEQUENTIAL - 1;
800 s->max_seq = seq;
801 }
802 return 0; // NOLINTNEXTLINE(readability-else-after-return)
803 } else if (udelta < MAX_DROPOUT) {
804 /* in order, with permissible gap */
805 if (seq < s->max_seq) {
806 /*
807 * Sequence number wrapped - count another 64K cycle.
808 */
809 s->cycles += RTP_SEQ_MOD;
810 }
811 s->max_seq = seq;
812 } else if (udelta <= RTP_SEQ_MOD - MAX_MISORDER) {
813 /* the sequence number made a very large jump */
814 if (seq == s->bad_seq) {
815 /*
816 * Two sequential packets -- assume that the other side
817 * restarted without telling us so just re-sync
818 * (i.e., pretend this was the first packet).
819 */
820 init_seq(s, seq);
821 } else {
822 s->bad_seq = (seq + 1) & (RTP_SEQ_MOD - 1);
823 return 0;
824 }
825 } else {
826 /* duplicate or reordered packet */
827 }
828 s->received++;
829 return 1;
830}
#define MAX_DROPOUT
Definition rtp.c:125
static void init_seq(source *s, uint16_t seq)
Definition rtp.c:765
#define MAX_MISORDER
Definition rtp.c:126

References _source::bad_seq, check_source(), _source::cycles, init_seq(), MAX_DROPOUT, MAX_MISORDER, _source::max_seq, MIN_SEQUENTIAL, _source::probation, _source::received, RTP_SEQ_MOD, and seq.

Referenced by rtp_process_data().

Here is the call graph for this function:

◆ validate_rtcp()

static int validate_rtcp ( uint8_t * packet,
int len )
static

Definition at line 1670 of file rtp.c.

1671{
1672 /* Validity check for a compound RTCP packet. This function returns */
1673 /* TRUE if the packet is okay, FALSE if the validity check fails. */
1674 /* */
1675 /* The following checks can be applied to RTCP packets [RFC1889]: */
1676 /* o RTP version field must equal 2. */
1677 /* o The payload type field of the first RTCP packet in a compound */
1678 /* packet must be equal to SR or RR. */
1679 /* o The padding bit (P) should be zero for the first packet of a */
1680 /* compound RTCP packet because only the last should possibly */
1681 /* need padding. */
1682 /* o The length fields of the individual RTCP packets must total to */
1683 /* the overall length of the compound RTCP packet as received. */
1684
1685 rtcp_t *pkt = (rtcp_t *)(void *) packet;
1686 rtcp_t *end = (rtcp_t *)(void *) (((char *)pkt) + len);
1687 rtcp_t *r = pkt;
1688 int l = 0;
1689 int pc = 1;
1690 int p = 0;
1691 int is_okay = TRUE;
1692
1693 /* All RTCP packets must be compound packets (RFC1889, section 6.1) */
1694 if (((ntohs(pkt->common.length) + 1) * 4) == len) {
1695 debug_msg("Bogus RTCP packet: not a compound packet\n");
1696 is_okay = FALSE;
1697 }
1698
1699 /* The RTCP packet must not be larger than the surrounding UDP packet */
1700 if (((ntohs(pkt->common.length) + 1) * 4) > len) {
1701 debug_msg
1702 ("Bogus RTCP packet: length exceeds length of container UDP packet\n");
1703 return FALSE;
1704 }
1705
1706 /* Check the RTCP version, payload type and padding of the first in */
1707 /* the compund RTCP packet... */
1708 if (pkt->common.version != 2) {
1709 debug_msg
1710 ("Bogus RTCP packet: version number != 2 in the first sub-packet\n");
1711 is_okay = FALSE;
1712 }
1713 if (pkt->common.p != 0) {
1714 debug_msg
1715 ("Bogus RTCP packet: padding bit is set on first packet in compound\n");
1716 is_okay = FALSE;
1717 }
1718 if ((pkt->common.pt != RTCP_SR) && (pkt->common.pt != RTCP_RR)) {
1719 if (pkt->common.pt == RTCP_SDES) {
1720 debug_msg
1721 ("Bogus RTCP packet: compound packet starts with SDES not SR or RR\n");
1722 } else if (pkt->common.pt == RTCP_APP) {
1723 debug_msg
1724 ("Bogus RTCP packet: compound packet starts with APP not SR or RR\n");
1725 } else if (pkt->common.pt == RTCP_BYE) {
1726 debug_msg
1727 ("Bogus RTCP packet: compound packet starts with BYE not SR or RR\n");
1728 } else {
1729 debug_msg
1730 ("Bogus RTCP packet: compound packet starts with packet type %d not SR or RR\n",
1731 pkt->common.pt);
1732 }
1733 is_okay = FALSE;
1734 }
1735
1736 /* Check all following parts of the compund RTCP packet. The RTP version */
1737 /* number must be 2, and the padding bit must be zero on all apart from */
1738 /* the last packet. Try to validate the format of each sub-packet. */
1739 do {
1740 if (p == 1) {
1741 debug_msg
1742 ("Bogus RTCP packet: padding bit set in sub-packet %d which is not final sub-packet\n",
1743 pc);
1744 is_okay = FALSE;
1745 }
1746 if (r->common.p) {
1747 p = 1;
1748 }
1749 if (r->common.version != 2) {
1750 debug_msg
1751 ("Bogus RTCP packet: version number != 2 in sub-packet %d\n",
1752 pc);
1753 is_okay = FALSE;
1754 }
1755
1756 if (pkt->common.pt == RTCP_SR) {
1757 if (((ntohs(pkt->common.length) + 1) * 4) <
1758 (28 + (pkt->common.count * 24))) {
1759 debug_msg
1760 ("Bogus RTCP packet: SR packet is too short (length=%d)\n",
1761 ntohs(pkt->common.length));
1762 is_okay = FALSE;
1763 }
1764 } else if (pkt->common.pt == RTCP_RR) {
1765 if (((ntohs(pkt->common.length) + 1) * 4) <
1766 (8 + (pkt->common.count * 24))) {
1767 debug_msg
1768 ("Bogus RTCP packet: RR packet is too short (length=%d)\n",
1769 ntohs(pkt->common.length));
1770 is_okay = FALSE;
1771 }
1772 } else if (pkt->common.pt == RTCP_SDES) {
1773 /* Parse and validate the SDES packet */
1774 int count = pkt->common.count;
1775 struct rtcp_sdes_t *sd = &pkt->r.sdes;
1776 rtcp_sdes_item *rsp;
1777 rtcp_sdes_item *rspn;
1778 rtcp_sdes_item *sdes_end =
1779 (rtcp_sdes_item *) ((uint32_t *) pkt +
1780 pkt->common.length + 1);
1781
1782 while (--count >= 0) {
1783 rsp = &sd->item[0];
1784 if ((char *)rsp > (char *)end) {
1785 debug_msg
1786 ("Bogus RTCP packet: SDES longer than UDP packet: no terminating null item?\n");
1787 is_okay = FALSE;
1788 break;
1789 }
1790 if (rsp >= sdes_end) {
1791 debug_msg
1792 ("Bogus RTCP packet: too many SDES items for packet length\n");
1793 is_okay = FALSE;
1794 break;
1795 }
1796 for (; rsp->type; rsp = rspn) {
1797 rspn =
1798 (rtcp_sdes_item *) ((char *)rsp +
1799 rsp->length +
1800 2);
1801 if (rspn == sdes_end) {
1802 break;
1803 }
1804 }
1805 sd = (struct rtcp_sdes_t *)((uint32_t *) sd +
1806 (((char *)rsp -
1807 (char *)sd) >> 2)
1808 + 1);
1809 }
1810 if (count >= 0) {
1811 debug_msg
1812 ("Bogus RTCP packet: malformed SDES packet\n");
1813 }
1814 } else if (pkt->common.pt == RTCP_APP) {
1815 /* No way to validate these? */
1816 } else if (pkt->common.pt == RTCP_BYE) {
1817 /* No way to validate these? */
1818 }
1819 l += (ntohs(r->common.length) + 1) * 4;
1820 r = (rtcp_t *) (((uint32_t *) r) + ntohs(r->common.length) + 1);
1821 pc++; /* count of sub-packets, for debugging... */
1822 } while (r < end);
1823
1824 /* Check that the length of the packets matches the length of the UDP */
1825 /* packet in which they were received... */
1826 if (l != len) {
1827 debug_msg
1828 ("Bogus RTCP packet: RTCP packet length does not match UDP packet length (%d != %d)\n",
1829 l, len);
1830 is_okay = FALSE;
1831 }
1832 if (r != end) {
1833 debug_msg
1834 ("Bogus RTCP packet: RTCP packet length does not match UDP packet length (%p != %p)\n",
1835 r, end);
1836 is_okay = FALSE;
1837 }
1838
1839 if (!is_okay) {
1840 debug_dump(packet, len);
1841 }
1842
1843 return is_okay;
1844}
void debug_dump(const void *lp, int len)
Definition debug.cpp:179

References rtcp_t::common, count, rtcp_common::count, debug_dump(), debug_msg, FALSE, len, rtcp_common::length, rtcp_sdes_item::length, rtcp_common::p, rtcp_common::pt, rtcp_t::r, RTCP_APP, RTCP_BYE, RTCP_RR, RTCP_SDES, RTCP_SR, rtcp_t::sdes, TRUE, rtcp_sdes_item::type, and rtcp_common::version.

Referenced by rtp_process_ctrl().

Here is the call graph for this function:

◆ validate_rtp()

static bool validate_rtp ( struct rtp * session,
rtp_packet * packet,
int len,
int vlen )
inlinestatic

Definition at line 1447 of file rtp.c.

1448{
1449 /* This function checks the header info to make sure that the packet */
1450 /* is valid. We return true if the packet is valid, false otherwise. */
1451 /* See Appendix A.1 of the RTP specification. */
1452
1453 /* We only accept RTPv2 packets... */
1454 if (packet->v != 2) {
1455 debug_msg("rtp_header_validation: v != 2\n");
1456 return FALSE;
1457 }
1458
1459 if (!session->opt->wait_for_rtcp) {
1460 /* We prefer speed over accuracy... */
1461 return true;
1462 }
1463 return validate_rtp2(packet, len, vlen);
1464}
static bool validate_rtp2(rtp_packet *packet, int len, int vlen)
Definition rtp.c:1407

References debug_msg, FALSE, len, rtp::opt, validate_rtp2(), and options::wait_for_rtcp.

Referenced by rtp_process_data().

Here is the call graph for this function:

◆ validate_rtp2()

static bool validate_rtp2 ( rtp_packet * packet,
int len,
int vlen )
static

Definition at line 1407 of file rtp.c.

1408{
1409 /* Check for valid payload types..... 72-76 are RTCP payload type numbers, with */
1410 /* the high bit missing so we report that someone is running on the wrong port. */
1411 if (packet->pt >= 72 && packet->pt <= 76) {
1412 debug_msg("rtp_header_validation: payload-type invalid");
1413 if (packet->m) {
1414 debug_msg(" (RTCP packet on RTP port?)");
1415 }
1416 debug_msg("\n");
1417 return false;
1418 }
1419 /* Check that the length of the packet is sensible... */
1420 if (len < (vlen + (4 * packet->cc))) {
1421 debug_msg
1422 ("rtp_header_validation: packet length is smaller than the header\n");
1423 return false;
1424 }
1425 /* Check that the amount of padding specified is sensible. */
1426 /* Note: have to include the size of any extension header! */
1427 if (packet->p) {
1428 int payload_len = len - vlen - (packet->cc * 4);
1429 if (packet->x) {
1430 /* extension header and data */
1431 payload_len -= 4 * (1 + packet->extn_len);
1432 }
1433 if (packet->data[packet->data_len - 1] > payload_len) {
1434 debug_msg
1435 ("rtp_header_validation: padding greater than payload length\n");
1436 return false;
1437 }
1438 if (packet->data[packet->data_len - 1] < 1) {
1439 debug_msg("rtp_header_validation: padding zero\n");
1440 return false;
1441 }
1442 }
1443 return true;
1444}

References debug_msg, and len.

Referenced by validate_rtp().