Wed Apr 6 11:30:09 2011

Asterisk developer's documentation


res_rtp_asterisk.c File Reference

Supports RTP and RTCP with Symmetric RTP support for NAT traversal. More...

#include "asterisk.h"
#include <sys/time.h>
#include <signal.h>
#include <fcntl.h>
#include "asterisk/stun.h"
#include "asterisk/pbx.h"
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/acl.h"
#include "asterisk/config.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
#include "asterisk/manager.h"
#include "asterisk/unaligned.h"
#include "asterisk/module.h"
#include "asterisk/rtp_engine.h"

Go to the source code of this file.

Data Structures

struct  ast_rtcp
 Structure defining an RTCP session. More...
struct  ast_rtp
 RTP session description. More...
struct  frame_list
struct  rtp_red

Defines

#define DEFAULT_DTMF_TIMEOUT   (150 * (8000 / 1000))
#define DEFAULT_RTP_END   31000
#define DEFAULT_RTP_START   5000
#define FLAG_3389_WARNING   (1 << 0)
#define FLAG_DTMF_COMPENSATE   (1 << 4)
#define FLAG_NAT_ACTIVE   (3 << 1)
#define FLAG_NAT_INACTIVE   (0 << 1)
#define FLAG_NAT_INACTIVE_NOWARN   (1 << 1)
#define FLAG_NEED_MARKER_BIT   (1 << 3)
#define MAX_TIMESTAMP_SKEW   640
#define MAXIMUM_RTP_PORT   65535
#define MINIMUM_RTP_PORT   1024
#define RTCP_DEFAULT_INTERVALMS   5000
#define RTCP_MAX_INTERVALMS   60000
#define RTCP_MIN_INTERVALMS   500
#define RTCP_PT_APP   204
#define RTCP_PT_BYE   203
#define RTCP_PT_FUR   192
#define RTCP_PT_RR   201
#define RTCP_PT_SDES   202
#define RTCP_PT_SR   200
#define RTP_MTU   1200
#define RTP_SEQ_MOD   (1<<16)
#define SQUARE(x)   ((x) * (x))
#define ZFONE_PROFILE_ID   0x505a

Enumerations

enum  strict_rtp_state { STRICT_RTP_OPEN = 0, STRICT_RTP_LEARN, STRICT_RTP_CLOSED }

Functions

static void __reg_module (void)
static int __rtp_recvfrom (struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int rtcp)
static int __rtp_sendto (struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int rtcp)
static void __unreg_module (void)
static unsigned int ast_rtcp_calc_interval (struct ast_rtp *rtp)
static struct ast_frameast_rtcp_read (struct ast_rtp_instance *instance)
static int ast_rtcp_write (const void *data)
 Write and RTCP packet to the far end.
static int ast_rtcp_write_rr (struct ast_rtp_instance *instance)
 Send RTCP recipient's report.
static int ast_rtcp_write_sr (struct ast_rtp_instance *instance)
 Send RTCP sender's report.
static void ast_rtp_alt_remote_address_set (struct ast_rtp_instance *instance, struct ast_sockaddr *addr)
static void ast_rtp_change_source (struct ast_rtp_instance *instance)
static int ast_rtp_destroy (struct ast_rtp_instance *instance)
static int ast_rtp_dtmf_begin (struct ast_rtp_instance *instance, char digit)
static int ast_rtp_dtmf_compatible (struct ast_channel *chan0, struct ast_rtp_instance *instance0, struct ast_channel *chan1, struct ast_rtp_instance *instance1)
static int ast_rtp_dtmf_continuation (struct ast_rtp_instance *instance)
static int ast_rtp_dtmf_end (struct ast_rtp_instance *instance, char digit)
static int ast_rtp_dtmf_end_with_duration (struct ast_rtp_instance *instance, char digit, unsigned int duration)
static int ast_rtp_fd (struct ast_rtp_instance *instance, int rtcp)
static int ast_rtp_get_stat (struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat)
static int ast_rtp_local_bridge (struct ast_rtp_instance *instance0, struct ast_rtp_instance *instance1)
static int ast_rtp_new (struct ast_rtp_instance *instance, struct sched_context *sched, struct ast_sockaddr *addr, void *data)
static void ast_rtp_prop_set (struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
static int ast_rtp_qos_set (struct ast_rtp_instance *instance, int tos, int cos, const char *desc)
static int ast_rtp_raw_write (struct ast_rtp_instance *instance, struct ast_frame *frame, int codec)
static struct ast_frameast_rtp_read (struct ast_rtp_instance *instance, int rtcp)
static void ast_rtp_remote_address_set (struct ast_rtp_instance *instance, struct ast_sockaddr *addr)
static void ast_rtp_stop (struct ast_rtp_instance *instance)
static void ast_rtp_stun_request (struct ast_rtp_instance *instance, struct ast_sockaddr *suggestion, const char *username)
static void ast_rtp_update_source (struct ast_rtp_instance *instance)
static int ast_rtp_write (struct ast_rtp_instance *instance, struct ast_frame *frame)
static int bridge_p2p_rtp_write (struct ast_rtp_instance *instance, unsigned int *rtpheader, int len, int hdrlen)
static void calc_rxstamp (struct timeval *tv, struct ast_rtp *rtp, unsigned int timestamp, int mark)
static unsigned int calc_txstamp (struct ast_rtp *rtp, struct timeval *delivery)
static struct ast_framecreate_dtmf_frame (struct ast_rtp_instance *instance, enum ast_frame_type type, int compensate)
static int create_new_socket (const char *type, int af)
static char * handle_cli_rtcp_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_rtcp_set_stats (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_rtp_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int load_module (void)
static double normdev_compute (double normdev, double sample, unsigned int sample_count)
 Calculate normal deviation.
static struct ast_frameprocess_cn_rfc3389 (struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct ast_sockaddr *addr, int payloadtype, int mark)
static struct ast_frameprocess_dtmf_cisco (struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct ast_sockaddr *addr, int payloadtype, int mark)
static void process_dtmf_rfc2833 (struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct ast_sockaddr *addr, int payloadtype, int mark, struct frame_list *frames)
static struct ast_framered_t140_to_red (struct rtp_red *red)
static int red_write (const void *data)
 Write t140 redundacy frame.
static int reload_module (void)
static int rtcp_debug_test_addr (struct ast_sockaddr *addr)
static char * rtcp_do_debug_ip (struct ast_cli_args *a)
static int rtcp_recvfrom (struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa)
static int rtcp_sendto (struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa)
static int rtp_debug_test_addr (struct ast_sockaddr *addr)
static char * rtp_do_debug_ip (struct ast_cli_args *a)
static int rtp_get_rate (format_t subclass)
static int rtp_recvfrom (struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa)
static int rtp_red_buffer (struct ast_rtp_instance *instance, struct ast_frame *frame)
static int rtp_red_init (struct ast_rtp_instance *instance, int buffer_time, int *payloads, int generations)
static int rtp_reload (int reload)
static int rtp_sendto (struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa)
static double stddev_compute (double stddev, double sample, double normdev, double normdev_curent, unsigned int sample_count)
static void timeval2ntp (struct timeval tv, unsigned int *msw, unsigned int *lsw)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Asterisk RTP Stack" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, }
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_rtp_engine asterisk_rtp_engine
static struct ast_cli_entry cli_rtp []
static int dtmftimeout = DEFAULT_DTMF_TIMEOUT
ast_srtp_resres_srtp
static int rtcpdebug
static struct ast_sockaddr rtcpdebugaddr
static int rtcpinterval = RTCP_DEFAULT_INTERVALMS
static int rtcpstats
static int rtpdebug
static struct ast_sockaddr rtpdebugaddr
static int rtpend = DEFAULT_RTP_END
static int rtpstart = DEFAULT_RTP_START
static int strictrtp


Detailed Description

Supports RTP and RTCP with Symmetric RTP support for NAT traversal.

Author:
Mark Spencer <markster@digium.com>
Note:
RTP is defined in RFC 3550.

Definition in file res_rtp_asterisk.c.


Define Documentation

#define DEFAULT_DTMF_TIMEOUT   (150 * (8000 / 1000))

samples

Definition at line 75 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

#define DEFAULT_RTP_END   31000

Default maximum port number to end allocating RTP ports at

Definition at line 61 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

#define DEFAULT_RTP_START   5000

Default port number to start allocating RTP ports from

Definition at line 60 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

#define FLAG_3389_WARNING   (1 << 0)

Definition at line 101 of file res_rtp_asterisk.c.

Referenced by process_cn_rfc3389().

#define FLAG_DTMF_COMPENSATE   (1 << 4)

Definition at line 106 of file res_rtp_asterisk.c.

#define FLAG_NAT_ACTIVE   (3 << 1)

Definition at line 102 of file res_rtp_asterisk.c.

Referenced by ast_rtp_raw_write(), ast_rtp_read(), and bridge_p2p_rtp_write().

#define FLAG_NAT_INACTIVE   (0 << 1)

Definition at line 103 of file res_rtp_asterisk.c.

Referenced by ast_rtp_raw_write(), and bridge_p2p_rtp_write().

#define FLAG_NAT_INACTIVE_NOWARN   (1 << 1)

Definition at line 104 of file res_rtp_asterisk.c.

Referenced by ast_rtp_raw_write(), and bridge_p2p_rtp_write().

#define FLAG_NEED_MARKER_BIT   (1 << 3)

Definition at line 105 of file res_rtp_asterisk.c.

Referenced by ast_rtp_change_source(), ast_rtp_local_bridge(), ast_rtp_raw_write(), ast_rtp_stop(), ast_rtp_update_source(), and bridge_p2p_rtp_write().

#define MAX_TIMESTAMP_SKEW   640

Definition at line 53 of file res_rtp_asterisk.c.

#define MAXIMUM_RTP_PORT   65535

Maximum port number to accept

Definition at line 64 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

#define MINIMUM_RTP_PORT   1024

Minimum port number to accept

Definition at line 63 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

#define RTCP_DEFAULT_INTERVALMS   5000

Default milli-seconds between RTCP reports we send

Definition at line 56 of file res_rtp_asterisk.c.

#define RTCP_MAX_INTERVALMS   60000

Max milli-seconds between RTCP reports we send

Definition at line 58 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

#define RTCP_MIN_INTERVALMS   500

Min milli-seconds between RTCP reports we send

Definition at line 57 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

#define RTCP_PT_APP   204

Definition at line 71 of file res_rtp_asterisk.c.

#define RTCP_PT_BYE   203

Definition at line 70 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_read().

#define RTCP_PT_FUR   192

Definition at line 66 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_read().

#define RTCP_PT_RR   201

Definition at line 68 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_rr().

#define RTCP_PT_SDES   202

Definition at line 69 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), and ast_rtcp_write_sr().

#define RTCP_PT_SR   200

Definition at line 67 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

#define RTP_MTU   1200

Definition at line 73 of file res_rtp_asterisk.c.

#define RTP_SEQ_MOD   (1<<16)

A sequence number can't be more than 16 bits

Definition at line 55 of file res_rtp_asterisk.c.

Referenced by ast_rtp_read().

#define SQUARE (  )     ((x) * (x))

Referenced by stddev_compute().

#define ZFONE_PROFILE_ID   0x505a

Definition at line 77 of file res_rtp_asterisk.c.


Enumeration Type Documentation

enum strict_rtp_state

Enumerator:
STRICT_RTP_OPEN 
STRICT_RTP_LEARN  No RTP packets should be dropped, all sources accepted
STRICT_RTP_CLOSED  Accept next packet as source

Definition at line 95 of file res_rtp_asterisk.c.

00095                       {
00096    STRICT_RTP_OPEN = 0, /*! No RTP packets should be dropped, all sources accepted */
00097    STRICT_RTP_LEARN,    /*! Accept next packet as source */
00098    STRICT_RTP_CLOSED,   /*! Drop all RTP packets not coming from source that was learned */
00099 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 2825 of file res_rtp_asterisk.c.

static int __rtp_recvfrom ( struct ast_rtp_instance instance,
void *  buf,
size_t  size,
int  flags,
struct ast_sockaddr sa,
int  rtcp 
) [static]

Definition at line 320 of file res_rtp_asterisk.c.

References ast_recvfrom(), ast_rtp_instance_get_data(), ast_rtp_instance_get_srtp(), len(), res_srtp, ast_srtp::rtp, and ast_srtp_res::unprotect.

Referenced by rtcp_recvfrom(), and rtp_recvfrom().

00321 {
00322    int len;
00323    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00324    struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance);
00325 
00326    if ((len = ast_recvfrom(rtcp ? rtp->rtcp->s : rtp->s, buf, size, flags, sa)) < 0) {
00327       return len;
00328    }
00329 
00330    if (res_srtp && srtp && res_srtp->unprotect(srtp, buf, &len, rtcp) < 0) {
00331       return -1;
00332    }
00333 
00334    return len;
00335 }

static int __rtp_sendto ( struct ast_rtp_instance instance,
void *  buf,
size_t  size,
int  flags,
struct ast_sockaddr sa,
int  rtcp 
) [static]

Definition at line 347 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data(), ast_rtp_instance_get_srtp(), ast_sendto(), len(), ast_srtp_res::protect, res_srtp, and ast_srtp::rtp.

Referenced by rtcp_sendto(), and rtp_sendto().

00348 {
00349    int len = size;
00350    void *temp = buf;
00351    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00352    struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance);
00353 
00354    if (res_srtp && srtp && res_srtp->protect(srtp, &temp, &len, rtcp) < 0) {
00355       return -1;
00356    }
00357 
00358    return ast_sendto(rtcp ? rtp->rtcp->s : rtp->s, temp, len, flags, sa);
00359 }

static void __unreg_module ( void   )  [static]

Definition at line 2825 of file res_rtp_asterisk.c.

static unsigned int ast_rtcp_calc_interval ( struct ast_rtp rtp  )  [static]

Definition at line 376 of file res_rtp_asterisk.c.

Referenced by ast_rtp_raw_write(), and ast_rtp_read().

00377 {
00378    unsigned int interval;
00379    /*! \todo XXX Do a more reasonable calculation on this one
00380     * Look in RFC 3550 Section A.7 for an example*/
00381    interval = rtcpinterval;
00382    return interval;
00383 }

static struct ast_frame* ast_rtcp_read ( struct ast_rtp_instance instance  )  [static]

Definition at line 1640 of file res_rtp_asterisk.c.

References ast_rtcp::accumulated_transit, ast_assert, AST_CONTROL_VIDUPDATE, ast_debug, AST_FRAME_CONTROL, AST_FRIENDLY_OFFSET, ast_log(), ast_null_frame, ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), AST_RTP_PROPERTY_NAT, ast_sockaddr_cmp(), ast_sockaddr_copy(), ast_sockaddr_stringify(), ast_verbose, ast_frame::datalen, errno, EVENT_FLAG_REPORTING, ast_rtp::f, f, ast_frame::frametype, ast_frame_subclass::integer, LOG_DEBUG, LOG_WARNING, ast_frame::mallocd, manager_event, ast_rtcp::maxrtt, ast_rtcp::minrtt, normdev_compute(), ast_rtcp::normdevrtt, option_debug, ast_rtcp::reported_jitter, ast_rtcp::reported_jitter_count, ast_rtcp::reported_lost, ast_rtcp::reported_maxjitter, ast_rtcp::reported_maxlost, ast_rtcp::reported_minjitter, ast_rtcp::reported_minlost, ast_rtcp::reported_normdev_jitter, ast_rtcp::reported_normdev_lost, ast_rtcp::reported_stdev_jitter, ast_rtcp::reported_stdev_lost, ast_rtp::rtcp, rtcp_debug_test_addr(), ast_rtcp::rtcp_info, RTCP_PT_BYE, RTCP_PT_FUR, RTCP_PT_RR, RTCP_PT_SDES, RTCP_PT_SR, rtcp_recvfrom(), rtpdebug, ast_rtcp::rtt, ast_rtcp::rtt_count, ast_rtcp::rxlsr, ast_frame::samples, ast_rtcp::soc, ast_rtcp::spc, ast_frame::src, stddev_compute(), ast_rtcp::stdevrtt, ast_frame::subclass, ast_rtcp::them, ast_rtcp::themrxlsr, and timeval2ntp().

Referenced by ast_rtp_read().

01641 {
01642    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
01643    struct ast_sockaddr addr;
01644    unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET];
01645    unsigned int *rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET);
01646    int res, packetwords, position = 0;
01647    struct ast_frame *f = &ast_null_frame;
01648 
01649    /* Read in RTCP data from the socket */
01650    if ((res = rtcp_recvfrom(instance, rtcpdata + AST_FRIENDLY_OFFSET,
01651             sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET,
01652             0, &addr)) < 0) {
01653       ast_assert(errno != EBADF);
01654       if (errno != EAGAIN) {
01655          ast_log(LOG_WARNING, "RTCP Read error: %s.  Hanging up.\n", strerror(errno));
01656          return NULL;
01657       }
01658       return &ast_null_frame;
01659    }
01660 
01661    packetwords = res / 4;
01662 
01663    if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT)) {
01664       /* Send to whoever sent to us */
01665       if (ast_sockaddr_cmp(&rtp->rtcp->them, &addr)) {
01666          ast_sockaddr_copy(&rtp->rtcp->them, &addr);
01667          if (option_debug || rtpdebug)
01668             ast_debug(0, "RTCP NAT: Got RTCP from other end. Now sending to address %s\n",
01669                  ast_sockaddr_stringify(&rtp->rtcp->them));
01670       }
01671    }
01672 
01673    ast_debug(1, "Got RTCP report of %d bytes\n", res);
01674 
01675    while (position < packetwords) {
01676       int i, pt, rc;
01677       unsigned int length, dlsr, lsr, msw, lsw, comp;
01678       struct timeval now;
01679       double rttsec, reported_jitter, reported_normdev_jitter_current, normdevrtt_current, reported_lost, reported_normdev_lost_current;
01680       uint64_t rtt = 0;
01681 
01682       i = position;
01683       length = ntohl(rtcpheader[i]);
01684       pt = (length & 0xff0000) >> 16;
01685       rc = (length & 0x1f000000) >> 24;
01686       length &= 0xffff;
01687 
01688       if ((i + length) > packetwords) {
01689          if (option_debug || rtpdebug)
01690             ast_log(LOG_DEBUG, "RTCP Read too short\n");
01691          return &ast_null_frame;
01692       }
01693 
01694       if (rtcp_debug_test_addr(&addr)) {
01695          ast_verbose("\n\nGot RTCP from %s\n",
01696                 ast_sockaddr_stringify(&addr));
01697          ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown");
01698          ast_verbose("Reception reports: %d\n", rc);
01699          ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]);
01700       }
01701 
01702       i += 2; /* Advance past header and ssrc */
01703       if (rc == 0 && pt == RTCP_PT_RR) {      /* We're receiving a receiver report with no reports, which is ok */
01704          position += (length + 1);
01705          continue;
01706       }
01707 
01708       switch (pt) {
01709       case RTCP_PT_SR:
01710          gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */
01711          rtp->rtcp->spc = ntohl(rtcpheader[i+3]);
01712          rtp->rtcp->soc = ntohl(rtcpheader[i + 4]);
01713          rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/
01714 
01715          if (rtcp_debug_test_addr(&addr)) {
01716             ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096);
01717             ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2]));
01718             ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4]));
01719          }
01720          i += 5;
01721          if (rc < 1)
01722             break;
01723          /* Intentional fall through */
01724       case RTCP_PT_RR:
01725          /* Don't handle multiple reception reports (rc > 1) yet */
01726          /* Calculate RTT per RFC */
01727          gettimeofday(&now, NULL);
01728          timeval2ntp(now, &msw, &lsw);
01729          if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */
01730             comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16);
01731             lsr = ntohl(rtcpheader[i + 4]);
01732             dlsr = ntohl(rtcpheader[i + 5]);
01733             rtt = comp - lsr - dlsr;
01734 
01735             /* Convert end to end delay to usec (keeping the calculation in 64bit space)
01736                sess->ee_delay = (eedelay * 1000) / 65536; */
01737             if (rtt < 4294) {
01738                rtt = (rtt * 1000000) >> 16;
01739             } else {
01740                rtt = (rtt * 1000) >> 16;
01741                rtt *= 1000;
01742             }
01743             rtt = rtt / 1000.;
01744             rttsec = rtt / 1000.;
01745             rtp->rtcp->rtt = rttsec;
01746 
01747             if (comp - dlsr >= lsr) {
01748                rtp->rtcp->accumulated_transit += rttsec;
01749 
01750                if (rtp->rtcp->rtt_count == 0)
01751                   rtp->rtcp->minrtt = rttsec;
01752 
01753                if (rtp->rtcp->maxrtt<rttsec)
01754                   rtp->rtcp->maxrtt = rttsec;
01755                if (rtp->rtcp->minrtt>rttsec)
01756                   rtp->rtcp->minrtt = rttsec;
01757 
01758                normdevrtt_current = normdev_compute(rtp->rtcp->normdevrtt, rttsec, rtp->rtcp->rtt_count);
01759 
01760                rtp->rtcp->stdevrtt = stddev_compute(rtp->rtcp->stdevrtt, rttsec, rtp->rtcp->normdevrtt, normdevrtt_current, rtp->rtcp->rtt_count);
01761 
01762                rtp->rtcp->normdevrtt = normdevrtt_current;
01763 
01764                rtp->rtcp->rtt_count++;
01765             } else if (rtcp_debug_test_addr(&addr)) {
01766                ast_verbose("Internal RTCP NTP clock skew detected: "
01767                         "lsr=%u, now=%u, dlsr=%u (%d:%03dms), "
01768                       "diff=%d\n",
01769                       lsr, comp, dlsr, dlsr / 65536,
01770                       (dlsr % 65536) * 1000 / 65536,
01771                       dlsr - (comp - lsr));
01772             }
01773          }
01774 
01775          rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]);
01776          reported_jitter = (double) rtp->rtcp->reported_jitter;
01777 
01778          if (rtp->rtcp->reported_jitter_count == 0)
01779             rtp->rtcp->reported_minjitter = reported_jitter;
01780 
01781          if (reported_jitter < rtp->rtcp->reported_minjitter)
01782             rtp->rtcp->reported_minjitter = reported_jitter;
01783 
01784          if (reported_jitter > rtp->rtcp->reported_maxjitter)
01785             rtp->rtcp->reported_maxjitter = reported_jitter;
01786 
01787          reported_normdev_jitter_current = normdev_compute(rtp->rtcp->reported_normdev_jitter, reported_jitter, rtp->rtcp->reported_jitter_count);
01788 
01789          rtp->rtcp->reported_stdev_jitter = stddev_compute(rtp->rtcp->reported_stdev_jitter, reported_jitter, rtp->rtcp->reported_normdev_jitter, reported_normdev_jitter_current, rtp->rtcp->reported_jitter_count);
01790 
01791          rtp->rtcp->reported_normdev_jitter = reported_normdev_jitter_current;
01792 
01793          rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff;
01794 
01795          reported_lost = (double) rtp->rtcp->reported_lost;
01796 
01797          /* using same counter as for jitter */
01798          if (rtp->rtcp->reported_jitter_count == 0)
01799             rtp->rtcp->reported_minlost = reported_lost;
01800 
01801          if (reported_lost < rtp->rtcp->reported_minlost)
01802             rtp->rtcp->reported_minlost = reported_lost;
01803 
01804          if (reported_lost > rtp->rtcp->reported_maxlost)
01805             rtp->rtcp->reported_maxlost = reported_lost;
01806          reported_normdev_lost_current = normdev_compute(rtp->rtcp->reported_normdev_lost, reported_lost, rtp->rtcp->reported_jitter_count);
01807 
01808          rtp->rtcp->reported_stdev_lost = stddev_compute(rtp->rtcp->reported_stdev_lost, reported_lost, rtp->rtcp->reported_normdev_lost, reported_normdev_lost_current, rtp->rtcp->reported_jitter_count);
01809 
01810          rtp->rtcp->reported_normdev_lost = reported_normdev_lost_current;
01811 
01812          rtp->rtcp->reported_jitter_count++;
01813 
01814          if (rtcp_debug_test_addr(&addr)) {
01815             ast_verbose("  Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24));
01816             ast_verbose("  Packets lost so far: %d\n", rtp->rtcp->reported_lost);
01817             ast_verbose("  Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff));
01818             ast_verbose("  Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16);
01819             ast_verbose("  Interarrival jitter: %u\n", rtp->rtcp->reported_jitter);
01820             ast_verbose("  Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096);
01821             ast_verbose("  DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0);
01822             if (rtt)
01823                ast_verbose("  RTT: %lu(sec)\n", (unsigned long) rtt);
01824          }
01825          if (rtt) {
01826             manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From %s\r\n"
01827                             "PT: %d(%s)\r\n"
01828                             "ReceptionReports: %d\r\n"
01829                             "SenderSSRC: %u\r\n"
01830                             "FractionLost: %ld\r\n"
01831                             "PacketsLost: %d\r\n"
01832                             "HighestSequence: %ld\r\n"
01833                             "SequenceNumberCycles: %ld\r\n"
01834                             "IAJitter: %u\r\n"
01835                             "LastSR: %lu.%010lu\r\n"
01836                             "DLSR: %4.4f(sec)\r\n"
01837                      "RTT: %llu(sec)\r\n",
01838                      ast_sockaddr_stringify(&addr),
01839                      pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
01840                      rc,
01841                      rtcpheader[i + 1],
01842                      (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24),
01843                      rtp->rtcp->reported_lost,
01844                      (long) (ntohl(rtcpheader[i + 2]) & 0xffff),
01845                      (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16,
01846                      rtp->rtcp->reported_jitter,
01847                      (unsigned long) ntohl(rtcpheader[i + 4]) >> 16, ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096,
01848                      ntohl(rtcpheader[i + 5])/65536.0,
01849                      (unsigned long long)rtt);
01850          } else {
01851             manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From %s\r\n"
01852                             "PT: %d(%s)\r\n"
01853                             "ReceptionReports: %d\r\n"
01854                             "SenderSSRC: %u\r\n"
01855                             "FractionLost: %ld\r\n"
01856                             "PacketsLost: %d\r\n"
01857                             "HighestSequence: %ld\r\n"
01858                             "SequenceNumberCycles: %ld\r\n"
01859                             "IAJitter: %u\r\n"
01860                             "LastSR: %lu.%010lu\r\n"
01861                      "DLSR: %4.4f(sec)\r\n",
01862                      ast_sockaddr_stringify(&addr),
01863                      pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
01864                      rc,
01865                      rtcpheader[i + 1],
01866                      (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24),
01867                      rtp->rtcp->reported_lost,
01868                      (long) (ntohl(rtcpheader[i + 2]) & 0xffff),
01869                      (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16,
01870                      rtp->rtcp->reported_jitter,
01871                      (unsigned long) ntohl(rtcpheader[i + 4]) >> 16,
01872                      ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096,
01873                      ntohl(rtcpheader[i + 5])/65536.0);
01874          }
01875          break;
01876       case RTCP_PT_FUR:
01877          if (rtcp_debug_test_addr(&addr))
01878             ast_verbose("Received an RTCP Fast Update Request\n");
01879          rtp->f.frametype = AST_FRAME_CONTROL;
01880          rtp->f.subclass.integer = AST_CONTROL_VIDUPDATE;
01881          rtp->f.datalen = 0;
01882          rtp->f.samples = 0;
01883          rtp->f.mallocd = 0;
01884          rtp->f.src = "RTP";
01885          f = &rtp->f;
01886          break;
01887       case RTCP_PT_SDES:
01888          if (rtcp_debug_test_addr(&addr))
01889             ast_verbose("Received an SDES from %s\n",
01890                    ast_sockaddr_stringify(&rtp->rtcp->them));
01891          break;
01892       case RTCP_PT_BYE:
01893          if (rtcp_debug_test_addr(&addr))
01894             ast_verbose("Received a BYE from %s\n",
01895                    ast_sockaddr_stringify(&rtp->rtcp->them));
01896          break;
01897       default:
01898          ast_debug(1, "Unknown RTCP packet (pt=%d) received from %s\n",
01899               pt, ast_sockaddr_stringify(&rtp->rtcp->them));
01900          break;
01901       }
01902       position += (length + 1);
01903    }
01904 
01905    rtp->rtcp->rtcp_info = 1;
01906 
01907    return f;
01908 }

static int ast_rtcp_write ( const void *  data  )  [static]

Write and RTCP packet to the far end.

Note:
Decide if we are going to send an SR (with Reception Block) or RR RR is sent if we have not sent any rtp packets in the previous interval

Definition at line 1017 of file res_rtp_asterisk.c.

References ast_rtcp_write_rr(), ast_rtcp_write_sr(), ast_rtp_instance_get_data(), ast_rtcp::lastsrtxcount, ast_rtp::rtcp, and ast_rtp::txcount.

Referenced by ast_rtp_raw_write(), and ast_rtp_read().

01018 {
01019    struct ast_rtp_instance *instance = (struct ast_rtp_instance *) data;
01020    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
01021    int res;
01022 
01023    if (!rtp || !rtp->rtcp)
01024       return 0;
01025 
01026    if (rtp->txcount > rtp->rtcp->lastsrtxcount)
01027       res = ast_rtcp_write_sr(instance);
01028    else
01029       res = ast_rtcp_write_rr(instance);
01030 
01031    return res;
01032 }

static int ast_rtcp_write_rr ( struct ast_rtp_instance instance  )  [static]

Send RTCP recipient's report.

Note:
Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos it can change mid call, and SDES can't)

Definition at line 786 of file res_rtp_asterisk.c.

References ast_log(), ast_rtp_instance_get_data(), AST_SCHED_DEL, ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_verbose, ast_rtp::cycles, errno, ast_rtcp::expected_prior, ast_rtp::lastrxseqno, len(), LOG_ERROR, ast_rtcp::maxrxlost, ast_rtcp::minrxlost, normdev_compute(), ast_rtcp::normdev_rxlost, ast_rtcp::received_prior, ast_rtcp::rr_count, ast_rtp::rtcp, rtcp_debug_test_addr(), RTCP_PT_RR, RTCP_PT_SDES, rtcp_sendto(), ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtcp::rxlost, ast_rtcp::rxlost_count, ast_rtcp::rxlsr, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, ast_rtp::ssrc, stddev_compute(), ast_rtcp::stdev_rxlost, ast_rtcp::them, ast_rtcp::themrxlsr, ast_rtp::themssrc, and timersub().

Referenced by ast_rtcp_write().

00787 {
00788    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00789    int res;
00790    int len = 32;
00791    unsigned int lost;
00792    unsigned int extended;
00793    unsigned int expected;
00794    unsigned int expected_interval;
00795    unsigned int received_interval;
00796    int lost_interval;
00797    struct timeval now;
00798    unsigned int *rtcpheader;
00799    char bdata[1024];
00800    struct timeval dlsr;
00801    int fraction;
00802 
00803    double rxlost_current;
00804 
00805    if (!rtp || !rtp->rtcp)
00806       return 0;
00807 
00808    if (ast_sockaddr_isnull(&rtp->rtcp->them)) {
00809       ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n");
00810       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
00811       return 0;
00812    }
00813 
00814    extended = rtp->cycles + rtp->lastrxseqno;
00815    expected = extended - rtp->seedrxseqno + 1;
00816    lost = expected - rtp->rxcount;
00817    expected_interval = expected - rtp->rtcp->expected_prior;
00818    rtp->rtcp->expected_prior = expected;
00819    received_interval = rtp->rxcount - rtp->rtcp->received_prior;
00820    rtp->rtcp->received_prior = rtp->rxcount;
00821    lost_interval = expected_interval - received_interval;
00822 
00823    if (lost_interval <= 0)
00824       rtp->rtcp->rxlost = 0;
00825    else rtp->rtcp->rxlost = rtp->rtcp->rxlost;
00826    if (rtp->rtcp->rxlost_count == 0)
00827       rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
00828    if (lost_interval < rtp->rtcp->minrxlost)
00829       rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
00830    if (lost_interval > rtp->rtcp->maxrxlost)
00831       rtp->rtcp->maxrxlost = rtp->rtcp->rxlost;
00832 
00833    rxlost_current = normdev_compute(rtp->rtcp->normdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->rxlost_count);
00834    rtp->rtcp->stdev_rxlost = stddev_compute(rtp->rtcp->stdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->normdev_rxlost, rxlost_current, rtp->rtcp->rxlost_count);
00835    rtp->rtcp->normdev_rxlost = rxlost_current;
00836    rtp->rtcp->rxlost_count++;
00837 
00838    if (expected_interval == 0 || lost_interval <= 0)
00839       fraction = 0;
00840    else
00841       fraction = (lost_interval << 8) / expected_interval;
00842    gettimeofday(&now, NULL);
00843    timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
00844    rtcpheader = (unsigned int *)bdata;
00845    rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1));
00846    rtcpheader[1] = htonl(rtp->ssrc);
00847    rtcpheader[2] = htonl(rtp->themssrc);
00848    rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
00849    rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
00850    rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.));
00851    rtcpheader[6] = htonl(rtp->rtcp->themrxlsr);
00852    rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
00853 
00854    /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos
00855      it can change mid call, and SDES can't) */
00856    rtcpheader[len/4]     = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
00857    rtcpheader[(len/4)+1] = htonl(rtp->ssrc);               /* Our SSRC */
00858    rtcpheader[(len/4)+2] = htonl(0x01 << 24);              /* Empty for the moment */
00859    len += 12;
00860 
00861    res = rtcp_sendto(instance, (unsigned int *)rtcpheader, len, 0, &rtp->rtcp->them);
00862 
00863    if (res < 0) {
00864       ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno));
00865       /* Remove the scheduler */
00866       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
00867       return 0;
00868    }
00869 
00870    rtp->rtcp->rr_count++;
00871    if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
00872       ast_verbose("\n* Sending RTCP RR to %s\n"
00873          "  Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n"
00874          "  IA jitter: %.4f\n"
00875          "  Their last SR: %u\n"
00876              "  DLSR: %4.4f (sec)\n\n",
00877              ast_sockaddr_stringify(&rtp->rtcp->them),
00878              rtp->ssrc, rtp->themssrc, fraction, lost,
00879              rtp->rxjitter,
00880              rtp->rtcp->themrxlsr,
00881              (double)(ntohl(rtcpheader[7])/65536.0));
00882    }
00883 
00884    return res;
00885 }

static int ast_rtcp_write_sr ( struct ast_rtp_instance instance  )  [static]

Send RTCP sender's report.

Definition at line 888 of file res_rtp_asterisk.c.

References ast_log(), ast_rtp_instance_get_data(), AST_SCHED_DEL, ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_verbose, ast_rtp::cycles, errno, EVENT_FLAG_REPORTING, ast_rtcp::expected_prior, ast_rtp::lastrxseqno, ast_rtcp::lastsrtxcount, ast_rtp::lastts, len(), LOG_ERROR, manager_event, ast_rtcp::received_prior, ast_rtp::rtcp, rtcp_debug_test_addr(), RTCP_PT_SDES, RTCP_PT_SR, rtcp_sendto(), ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtcp::rxlsr, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, ast_rtcp::sr_count, ast_rtp::ssrc, ast_rtcp::them, ast_rtcp::themrxlsr, ast_rtp::themssrc, timersub(), timeval2ntp(), ast_rtp::txcount, ast_rtcp::txlsr, and ast_rtp::txoctetcount.

Referenced by ast_rtcp_write().

00889 {
00890    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00891    int res;
00892    int len = 0;
00893    struct timeval now;
00894    unsigned int now_lsw;
00895    unsigned int now_msw;
00896    unsigned int *rtcpheader;
00897    unsigned int lost;
00898    unsigned int extended;
00899    unsigned int expected;
00900    unsigned int expected_interval;
00901    unsigned int received_interval;
00902    int lost_interval;
00903    int fraction;
00904    struct timeval dlsr;
00905    char bdata[512];
00906 
00907    if (!rtp || !rtp->rtcp)
00908       return 0;
00909 
00910    if (ast_sockaddr_isnull(&rtp->rtcp->them)) {  /* This'll stop rtcp for this rtp session */
00911       ast_verbose("RTCP SR transmission error, rtcp halted\n");
00912       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
00913       return 0;
00914    }
00915 
00916    gettimeofday(&now, NULL);
00917    timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/
00918    rtcpheader = (unsigned int *)bdata;
00919    rtcpheader[1] = htonl(rtp->ssrc);               /* Our SSRC */
00920    rtcpheader[2] = htonl(now_msw);                 /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/
00921    rtcpheader[3] = htonl(now_lsw);                 /* now, LSW */
00922    rtcpheader[4] = htonl(rtp->lastts);             /* FIXME shouldn't be that, it should be now */
00923    rtcpheader[5] = htonl(rtp->txcount);            /* No. packets sent */
00924    rtcpheader[6] = htonl(rtp->txoctetcount);       /* No. bytes sent */
00925    len += 28;
00926 
00927    extended = rtp->cycles + rtp->lastrxseqno;
00928    expected = extended - rtp->seedrxseqno + 1;
00929    if (rtp->rxcount > expected)
00930       expected += rtp->rxcount - expected;
00931    lost = expected - rtp->rxcount;
00932    expected_interval = expected - rtp->rtcp->expected_prior;
00933    rtp->rtcp->expected_prior = expected;
00934    received_interval = rtp->rxcount - rtp->rtcp->received_prior;
00935    rtp->rtcp->received_prior = rtp->rxcount;
00936    lost_interval = expected_interval - received_interval;
00937    if (expected_interval == 0 || lost_interval <= 0)
00938       fraction = 0;
00939    else
00940       fraction = (lost_interval << 8) / expected_interval;
00941    timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
00942    rtcpheader[7] = htonl(rtp->themssrc);
00943    rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
00944    rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
00945    rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.));
00946    rtcpheader[11] = htonl(rtp->rtcp->themrxlsr);
00947    rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
00948    len += 24;
00949 
00950    rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1));
00951 
00952    /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */
00953    /* it can change mid call, and SDES can't) */
00954    rtcpheader[len/4]     = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
00955    rtcpheader[(len/4)+1] = htonl(rtp->ssrc);               /* Our SSRC */
00956    rtcpheader[(len/4)+2] = htonl(0x01 << 24);                    /* Empty for the moment */
00957    len += 12;
00958 
00959    res = rtcp_sendto(instance, (unsigned int *)rtcpheader, len, 0, &rtp->rtcp->them);
00960    if (res < 0) {
00961       ast_log(LOG_ERROR, "RTCP SR transmission error to %s, rtcp halted %s\n",
00962          ast_sockaddr_stringify(&rtp->rtcp->them),
00963          strerror(errno));
00964       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
00965       return 0;
00966    }
00967 
00968    /* FIXME Don't need to get a new one */
00969    gettimeofday(&rtp->rtcp->txlsr, NULL);
00970    rtp->rtcp->sr_count++;
00971 
00972    rtp->rtcp->lastsrtxcount = rtp->txcount;
00973 
00974    if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
00975       ast_verbose("* Sent RTCP SR to %s\n", ast_sockaddr_stringify(&rtp->rtcp->them));
00976       ast_verbose("  Our SSRC: %u\n", rtp->ssrc);
00977       ast_verbose("  Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096);
00978       ast_verbose("  Sent(RTP): %u\n", rtp->lastts);
00979       ast_verbose("  Sent packets: %u\n", rtp->txcount);
00980       ast_verbose("  Sent octets: %u\n", rtp->txoctetcount);
00981       ast_verbose("  Report block:\n");
00982       ast_verbose("  Fraction lost: %u\n", fraction);
00983       ast_verbose("  Cumulative loss: %u\n", lost);
00984       ast_verbose("  IA jitter: %.4f\n", rtp->rxjitter);
00985       ast_verbose("  Their last SR: %u\n", rtp->rtcp->themrxlsr);
00986       ast_verbose("  DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0));
00987    }
00988    manager_event(EVENT_FLAG_REPORTING, "RTCPSent", "To %s\r\n"
00989                    "OurSSRC: %u\r\n"
00990                    "SentNTP: %u.%010u\r\n"
00991                    "SentRTP: %u\r\n"
00992                    "SentPackets: %u\r\n"
00993                    "SentOctets: %u\r\n"
00994                    "ReportBlock:\r\n"
00995                    "FractionLost: %u\r\n"
00996                    "CumulativeLoss: %u\r\n"
00997                    "IAJitter: %.4f\r\n"
00998                    "TheirLastSR: %u\r\n"
00999             "DLSR: %4.4f (sec)\r\n",
01000             ast_sockaddr_stringify(&rtp->rtcp->them),
01001             rtp->ssrc,
01002             (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096,
01003             rtp->lastts,
01004             rtp->txcount,
01005             rtp->txoctetcount,
01006             fraction,
01007             lost,
01008             rtp->rxjitter,
01009             rtp->rtcp->themrxlsr,
01010             (double)(ntohl(rtcpheader[12])/65536.0));
01011    return res;
01012 }

static void ast_rtp_alt_remote_address_set ( struct ast_rtp_instance instance,
struct ast_sockaddr addr 
) [static]

Definition at line 2408 of file res_rtp_asterisk.c.

References ast_rtp::alt_rtp_address, ast_rtp_instance_get_data(), and ast_sockaddr_copy().

02409 {
02410    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02411 
02412    /* No need to futz with rtp->rtcp here because ast_rtcp_read is already able to adjust if receiving
02413     * RTCP from an "unexpected" source
02414     */
02415    ast_sockaddr_copy(&rtp->alt_rtp_address, addr);
02416 
02417    return;
02418 }

static void ast_rtp_change_source ( struct ast_rtp_instance instance  )  [static]

Definition at line 730 of file res_rtp_asterisk.c.

References ast_debug, ast_random(), ast_rtp_instance_get_data(), ast_rtp_instance_get_srtp(), ast_set_flag, ast_srtp_res::change_source, FLAG_NEED_MARKER_BIT, res_srtp, and ast_srtp::rtp.

00731 {
00732    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00733    struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance);
00734    unsigned int ssrc = ast_random();
00735 
00736    if (!rtp->lastts) {
00737       ast_debug(3, "Not changing SSRC since we haven't sent any RTP yet\n");
00738       return;
00739    }
00740 
00741    /* We simply set this bit so that the next packet sent will have the marker bit turned on */
00742    ast_set_flag(rtp, FLAG_NEED_MARKER_BIT);
00743 
00744    ast_debug(3, "Changing ssrc from %u to %u due to a source change\n", rtp->ssrc, ssrc);
00745 
00746    if (srtp) {
00747       ast_debug(3, "Changing ssrc for SRTP from %u to %u\n", rtp->ssrc, ssrc);
00748       res_srtp->change_source(srtp, rtp->ssrc, ssrc);
00749    }
00750 
00751    rtp->ssrc = ssrc;
00752 
00753    return;
00754 }

static int ast_rtp_destroy ( struct ast_rtp_instance instance  )  [static]

Definition at line 498 of file res_rtp_asterisk.c.

References ast_free, ast_rtp_instance_get_data(), AST_SCHED_DEL, ast_smoother_free(), ast_rtp::red, ast_rtp::rtcp, ast_rtcp::s, ast_rtp::s, ast_rtp::sched, rtp_red::schedid, ast_rtcp::schedid, and ast_rtp::smoother.

00499 {
00500    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00501 
00502    /* Destroy the smoother that was smoothing out audio if present */
00503    if (rtp->smoother) {
00504       ast_smoother_free(rtp->smoother);
00505    }
00506 
00507    /* Close our own socket so we no longer get packets */
00508    if (rtp->s > -1) {
00509       close(rtp->s);
00510    }
00511 
00512    /* Destroy RTCP if it was being used */
00513    if (rtp->rtcp) {
00514       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
00515       close(rtp->rtcp->s);
00516       ast_free(rtp->rtcp);
00517    }
00518 
00519    /* Destroy RED if it was being used */
00520    if (rtp->red) {
00521       AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
00522       ast_free(rtp->red);
00523    }
00524 
00525    /* Finally destroy ourselves */
00526    ast_free(rtp);
00527 
00528    return 0;
00529 }

static int ast_rtp_dtmf_begin ( struct ast_rtp_instance instance,
char  digit 
) [static]

Definition at line 531 of file res_rtp_asterisk.c.

References ast_log(), ast_rtp_codecs_payload_code(), AST_RTP_DTMF, ast_rtp_instance_get_codecs(), ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address(), ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_tv(), ast_tvadd(), ast_tvnow(), ast_verbose, ast_rtp::dtmfmute, errno, ast_rtp::lastdigitts, ast_rtp::lastts, LOG_ERROR, LOG_WARNING, rtp_debug_test_addr(), rtp_sendto(), ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::sending_digit, ast_rtp::seqno, and ast_rtp::ssrc.

00532 {
00533    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00534    struct ast_sockaddr remote_address = { {0,} };
00535    int hdrlen = 12, res = 0, i = 0, payload = 101;
00536    char data[256];
00537    unsigned int *rtpheader = (unsigned int*)data;
00538 
00539    ast_rtp_instance_get_remote_address(instance, &remote_address);
00540 
00541    /* If we have no remote address information bail out now */
00542    if (ast_sockaddr_isnull(&remote_address)) {
00543       return -1;
00544    }
00545 
00546    /* Convert given digit into what we want to transmit */
00547    if ((digit <= '9') && (digit >= '0')) {
00548       digit -= '0';
00549    } else if (digit == '*') {
00550       digit = 10;
00551    } else if (digit == '#') {
00552       digit = 11;
00553    } else if ((digit >= 'A') && (digit <= 'D')) {
00554       digit = digit - 'A' + 12;
00555    } else if ((digit >= 'a') && (digit <= 'd')) {
00556       digit = digit - 'a' + 12;
00557    } else {
00558       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
00559       return -1;
00560    }
00561 
00562    /* Grab the payload that they expect the RFC2833 packet to be received in */
00563    payload = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 0, AST_RTP_DTMF);
00564 
00565    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
00566    rtp->send_duration = 160;
00567    rtp->lastdigitts = rtp->lastts + rtp->send_duration;
00568 
00569    /* Create the actual packet that we will be sending */
00570    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
00571    rtpheader[1] = htonl(rtp->lastdigitts);
00572    rtpheader[2] = htonl(rtp->ssrc);
00573 
00574    /* Actually send the packet */
00575    for (i = 0; i < 2; i++) {
00576       rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
00577       res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, &remote_address);
00578       if (res < 0) {
00579          ast_log(LOG_ERROR, "RTP Transmission error to %s: %s\n",
00580             ast_sockaddr_stringify(&remote_address),
00581             strerror(errno));
00582       }
00583       if (rtp_debug_test_addr(&remote_address)) {
00584          ast_verbose("Sent RTP DTMF packet to %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
00585                 ast_sockaddr_stringify(&remote_address),
00586                 payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
00587       }
00588       rtp->seqno++;
00589       rtp->send_duration += 160;
00590       rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
00591    }
00592 
00593    /* Record that we are in the process of sending a digit and information needed to continue doing so */
00594    rtp->sending_digit = 1;
00595    rtp->send_digit = digit;
00596    rtp->send_payload = payload;
00597 
00598    return 0;
00599 }

static int ast_rtp_dtmf_compatible ( struct ast_channel chan0,
struct ast_rtp_instance instance0,
struct ast_channel chan1,
struct ast_rtp_instance instance1 
) [static]

Definition at line 2539 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_prop(), AST_RTP_PROPERTY_DTMF, ast_channel_tech::send_digit_begin, and ast_channel::tech.

02540 {
02541    /* If both sides are not using the same method of DTMF transmission
02542     * (ie: one is RFC2833, other is INFO... then we can not do direct media.
02543     * --------------------------------------------------
02544     * | DTMF Mode |  HAS_DTMF  |  Accepts Begin Frames |
02545     * |-----------|------------|-----------------------|
02546     * | Inband    | False      | True                  |
02547     * | RFC2833   | True       | True                  |
02548     * | SIP INFO  | False      | False                 |
02549     * --------------------------------------------------
02550     */
02551    return (((ast_rtp_instance_get_prop(instance0, AST_RTP_PROPERTY_DTMF) != ast_rtp_instance_get_prop(instance1, AST_RTP_PROPERTY_DTMF)) ||
02552        (!chan0->tech->send_digit_begin != !chan1->tech->send_digit_begin)) ? 0 : 1);
02553 }

static int ast_rtp_dtmf_continuation ( struct ast_rtp_instance instance  )  [static]

Definition at line 601 of file res_rtp_asterisk.c.

References ast_log(), ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address(), ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_verbose, errno, ast_rtp::lastdigitts, LOG_ERROR, rtp_debug_test_addr(), rtp_sendto(), ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::seqno, and ast_rtp::ssrc.

Referenced by ast_rtp_read().

00602 {
00603    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00604    struct ast_sockaddr remote_address = { {0,} };
00605    int hdrlen = 12, res = 0;
00606    char data[256];
00607    unsigned int *rtpheader = (unsigned int*)data;
00608 
00609    ast_rtp_instance_get_remote_address(instance, &remote_address);
00610 
00611    /* Make sure we know where the other side is so we can send them the packet */
00612    if (ast_sockaddr_isnull(&remote_address)) {
00613       return -1;
00614    }
00615 
00616    /* Actually create the packet we will be sending */
00617    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
00618    rtpheader[1] = htonl(rtp->lastdigitts);
00619    rtpheader[2] = htonl(rtp->ssrc);
00620    rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration));
00621    rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
00622 
00623    /* Boom, send it on out */
00624    res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, &remote_address);
00625    if (res < 0) {
00626       ast_log(LOG_ERROR, "RTP Transmission error to %s: %s\n",
00627          ast_sockaddr_stringify(&remote_address),
00628          strerror(errno));
00629    }
00630 
00631    if (rtp_debug_test_addr(&remote_address)) {
00632       ast_verbose("Sent RTP DTMF packet to %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
00633              ast_sockaddr_stringify(&remote_address),
00634              rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
00635    }
00636 
00637    /* And now we increment some values for the next time we swing by */
00638    rtp->seqno++;
00639    rtp->send_duration += 160;
00640 
00641    return 0;
00642 }

static int ast_rtp_dtmf_end ( struct ast_rtp_instance instance,
char  digit 
) [static]

Definition at line 714 of file res_rtp_asterisk.c.

References ast_rtp_dtmf_end_with_duration().

00715 {
00716    return ast_rtp_dtmf_end_with_duration(instance, digit, 0);
00717 }

static int ast_rtp_dtmf_end_with_duration ( struct ast_rtp_instance instance,
char  digit,
unsigned int  duration 
) [static]

Definition at line 644 of file res_rtp_asterisk.c.

References ast_debug, ast_log(), ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address(), ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_tv(), ast_tvadd(), ast_tvnow(), ast_verbose, ast_frame_subclass::codec, ast_rtp::dtmfmute, errno, ast_rtp::f, ast_rtp::lastdigitts, ast_rtp::lastts, LOG_ERROR, LOG_WARNING, rtp_debug_test_addr(), rtp_get_rate(), rtp_sendto(), ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::sending_digit, ast_rtp::seqno, ast_rtp::ssrc, and ast_frame::subclass.

Referenced by ast_rtp_dtmf_end().

00645 {
00646    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00647    struct ast_sockaddr remote_address = { {0,} };
00648    int hdrlen = 12, res = 0, i = 0;
00649    char data[256];
00650    unsigned int *rtpheader = (unsigned int*)data;
00651    unsigned int measured_samples;
00652 
00653    ast_rtp_instance_get_remote_address(instance, &remote_address);
00654 
00655    /* Make sure we know where the remote side is so we can send them the packet we construct */
00656    if (ast_sockaddr_isnull(&remote_address)) {
00657       return -1;
00658    }
00659 
00660    /* Convert the given digit to the one we are going to send */
00661    if ((digit <= '9') && (digit >= '0')) {
00662       digit -= '0';
00663    } else if (digit == '*') {
00664       digit = 10;
00665    } else if (digit == '#') {
00666       digit = 11;
00667    } else if ((digit >= 'A') && (digit <= 'D')) {
00668       digit = digit - 'A' + 12;
00669    } else if ((digit >= 'a') && (digit <= 'd')) {
00670       digit = digit - 'a' + 12;
00671    } else {
00672       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
00673       return -1;
00674    }
00675 
00676    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
00677 
00678    if (duration > 0 && (measured_samples = duration * rtp_get_rate(rtp->f.subclass.codec) / 1000) > rtp->send_duration) {
00679       ast_debug(2, "Adjusting final end duration from %u to %u\n", rtp->send_duration, measured_samples);
00680       rtp->send_duration = measured_samples;
00681    }
00682 
00683    /* Construct the packet we are going to send */
00684    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
00685    rtpheader[1] = htonl(rtp->lastdigitts);
00686    rtpheader[2] = htonl(rtp->ssrc);
00687    rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
00688    rtpheader[3] |= htonl((1 << 23));
00689    rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
00690 
00691    /* Send it 3 times, that's the magical number */
00692    for (i = 0; i < 3; i++) {
00693       res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, &remote_address);
00694       if (res < 0) {
00695          ast_log(LOG_ERROR, "RTP Transmission error to %s: %s\n",
00696             ast_sockaddr_stringify(&remote_address),
00697             strerror(errno));
00698       }
00699       if (rtp_debug_test_addr(&remote_address)) {
00700          ast_verbose("Sent RTP DTMF packet to %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
00701                 ast_sockaddr_stringify(&remote_address),
00702                 rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
00703       }
00704    }
00705 
00706    /* Oh and we can't forget to turn off the stuff that says we are sending DTMF */
00707    rtp->lastts += rtp->send_duration;
00708    rtp->sending_digit = 0;
00709    rtp->send_digit = 0;
00710 
00711    return 0;
00712 }

static int ast_rtp_fd ( struct ast_rtp_instance instance,
int  rtcp 
) [static]

Definition at line 2379 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data(), ast_rtp::rtcp, ast_rtp::s, and ast_rtcp::s.

02380 {
02381    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02382 
02383    return rtcp ? (rtp->rtcp ? rtp->rtcp->s : -1) : rtp->s;
02384 }

static int ast_rtp_get_stat ( struct ast_rtp_instance instance,
struct ast_rtp_instance_stats stats,
enum ast_rtp_instance_stat  stat 
) [static]

Definition at line 2491 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data(), AST_RTP_INSTANCE_STAT_COMBINED_JITTER, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, AST_RTP_INSTANCE_STAT_COMBINED_RTT, AST_RTP_INSTANCE_STAT_LOCAL_MAXJITTER, AST_RTP_INSTANCE_STAT_LOCAL_MAXRXPLOSS, AST_RTP_INSTANCE_STAT_LOCAL_MINJITTER, AST_RTP_INSTANCE_STAT_LOCAL_MINRXPLOSS, AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVJITTER, AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVRXPLOSS, AST_RTP_INSTANCE_STAT_LOCAL_SSRC, AST_RTP_INSTANCE_STAT_LOCAL_STDEVJITTER, AST_RTP_INSTANCE_STAT_LOCAL_STDEVRXPLOSS, AST_RTP_INSTANCE_STAT_MAX_RTT, AST_RTP_INSTANCE_STAT_MIN_RTT, AST_RTP_INSTANCE_STAT_NORMDEVRTT, AST_RTP_INSTANCE_STAT_REMOTE_MAXJITTER, AST_RTP_INSTANCE_STAT_REMOTE_MAXRXPLOSS, AST_RTP_INSTANCE_STAT_REMOTE_MINJITTER, AST_RTP_INSTANCE_STAT_REMOTE_MINRXPLOSS, AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVJITTER, AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVRXPLOSS, AST_RTP_INSTANCE_STAT_REMOTE_SSRC, AST_RTP_INSTANCE_STAT_REMOTE_STDEVJITTER, AST_RTP_INSTANCE_STAT_REMOTE_STDEVRXPLOSS, AST_RTP_INSTANCE_STAT_RTT, AST_RTP_INSTANCE_STAT_RXCOUNT, AST_RTP_INSTANCE_STAT_RXJITTER, AST_RTP_INSTANCE_STAT_RXPLOSS, AST_RTP_INSTANCE_STAT_STDEVRTT, AST_RTP_INSTANCE_STAT_TXCOUNT, AST_RTP_INSTANCE_STAT_TXJITTER, AST_RTP_INSTANCE_STAT_TXPLOSS, AST_RTP_STAT_SET, AST_RTP_STAT_TERMINATOR, ast_rtcp::expected_prior, ast_rtp_instance_stats::local_maxjitter, ast_rtp_instance_stats::local_maxrxploss, ast_rtp_instance_stats::local_minjitter, ast_rtp_instance_stats::local_minrxploss, ast_rtp_instance_stats::local_normdevjitter, ast_rtp_instance_stats::local_normdevrxploss, ast_rtp_instance_stats::local_ssrc, ast_rtp_instance_stats::local_stdevjitter, ast_rtp_instance_stats::local_stdevrxploss, ast_rtcp::maxrtt, ast_rtp_instance_stats::maxrtt, ast_rtcp::maxrxjitter, ast_rtcp::maxrxlost, ast_rtcp::minrtt, ast_rtp_instance_stats::minrtt, ast_rtcp::minrxjitter, ast_rtcp::minrxlost, ast_rtcp::normdev_rxjitter, ast_rtcp::normdev_rxlost, ast_rtcp::normdevrtt, ast_rtp_instance_stats::normdevrtt, ast_rtcp::received_prior, ast_rtp_instance_stats::remote_maxjitter, ast_rtp_instance_stats::remote_maxrxploss, ast_rtp_instance_stats::remote_minjitter, ast_rtp_instance_stats::remote_minrxploss, ast_rtp_instance_stats::remote_normdevjitter, ast_rtp_instance_stats::remote_normdevrxploss, ast_rtp_instance_stats::remote_ssrc, ast_rtp_instance_stats::remote_stdevjitter, ast_rtp_instance_stats::remote_stdevrxploss, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtcp::reported_maxjitter, ast_rtcp::reported_maxlost, ast_rtcp::reported_minjitter, ast_rtcp::reported_minlost, ast_rtcp::reported_normdev_jitter, ast_rtcp::reported_normdev_lost, ast_rtcp::reported_stdev_jitter, ast_rtcp::reported_stdev_lost, ast_rtp::rtcp, ast_rtcp::rtt, ast_rtp_instance_stats::rtt, ast_rtp::rxcount, ast_rtp_instance_stats::rxcount, ast_rtp_instance_stats::rxjitter, ast_rtp::rxjitter, ast_rtp_instance_stats::rxploss, ast_rtp::ssrc, ast_rtcp::stdev_rxjitter, ast_rtcp::stdev_rxlost, ast_rtcp::stdevrtt, ast_rtp_instance_stats::stdevrtt, ast_rtp::themssrc, ast_rtp::txcount, ast_rtp_instance_stats::txcount, ast_rtp_instance_stats::txjitter, and ast_rtp_instance_stats::txploss.

02492 {
02493    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02494 
02495    if (!rtp->rtcp) {
02496       return -1;
02497    }
02498 
02499    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_TXCOUNT, -1, stats->txcount, rtp->txcount);
02500    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_RXCOUNT, -1, stats->rxcount, rtp->rxcount);
02501 
02502    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_TXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->txploss, rtp->rtcp->reported_lost);
02503    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_RXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->rxploss, rtp->rtcp->expected_prior - rtp->rtcp->received_prior);
02504    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MAXRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_maxrxploss, rtp->rtcp->reported_maxlost);
02505    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MINRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_minrxploss, rtp->rtcp->reported_minlost);
02506    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_normdevrxploss, rtp->rtcp->reported_normdev_lost);
02507    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_STDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_stdevrxploss, rtp->rtcp->reported_stdev_lost);
02508    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MAXRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_maxrxploss, rtp->rtcp->maxrxlost);
02509    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MINRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_minrxploss, rtp->rtcp->minrxlost);
02510    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_normdevrxploss, rtp->rtcp->normdev_rxlost);
02511    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_STDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_stdevrxploss, rtp->rtcp->stdev_rxlost);
02512    AST_RTP_STAT_TERMINATOR(AST_RTP_INSTANCE_STAT_COMBINED_LOSS);
02513 
02514    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_TXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->txjitter, rtp->rxjitter);
02515    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_RXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->rxjitter, rtp->rtcp->reported_jitter / (unsigned int) 65536.0);
02516    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MAXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_maxjitter, rtp->rtcp->reported_maxjitter);
02517    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MINJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_minjitter, rtp->rtcp->reported_minjitter);
02518    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_normdevjitter, rtp->rtcp->reported_normdev_jitter);
02519    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_STDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_stdevjitter, rtp->rtcp->reported_stdev_jitter);
02520    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MAXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_maxjitter, rtp->rtcp->maxrxjitter);
02521    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MINJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_minjitter, rtp->rtcp->minrxjitter);
02522    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_normdevjitter, rtp->rtcp->normdev_rxjitter);
02523    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_STDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_stdevjitter, rtp->rtcp->stdev_rxjitter);
02524    AST_RTP_STAT_TERMINATOR(AST_RTP_INSTANCE_STAT_COMBINED_JITTER);
02525 
02526    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_RTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->rtt, rtp->rtcp->rtt);
02527    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_MAX_RTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->maxrtt, rtp->rtcp->maxrtt);
02528    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_MIN_RTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->minrtt, rtp->rtcp->minrtt);
02529    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_NORMDEVRTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->normdevrtt, rtp->rtcp->normdevrtt);
02530    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_STDEVRTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->stdevrtt, rtp->rtcp->stdevrtt);
02531    AST_RTP_STAT_TERMINATOR(AST_RTP_INSTANCE_STAT_COMBINED_RTT);
02532 
02533    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_SSRC, -1, stats->local_ssrc, rtp->ssrc);
02534    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_SSRC, -1, stats->remote_ssrc, rtp->themssrc);
02535 
02536    return 0;
02537 }

static int ast_rtp_local_bridge ( struct ast_rtp_instance instance0,
struct ast_rtp_instance instance1 
) [static]

Definition at line 2482 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data(), ast_set_flag, and FLAG_NEED_MARKER_BIT.

02483 {
02484    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance0);
02485 
02486    ast_set_flag(rtp, FLAG_NEED_MARKER_BIT);
02487 
02488    return 0;
02489 }

static int ast_rtp_new ( struct ast_rtp_instance instance,
struct sched_context sched,
struct ast_sockaddr addr,
void *  data 
) [static]

Definition at line 436 of file res_rtp_asterisk.c.

References ast_bind(), ast_calloc, ast_debug, ast_free, ast_log(), ast_random(), ast_rtp_instance_set_local_address(), ast_sockaddr_is_ipv4(), ast_sockaddr_is_ipv6(), ast_sockaddr_set_port, create_new_socket(), errno, LOG_ERROR, STRICT_RTP_LEARN, and STRICT_RTP_OPEN.

00439 {
00440    struct ast_rtp *rtp = NULL;
00441    int x, startplace;
00442 
00443    /* Create a new RTP structure to hold all of our data */
00444    if (!(rtp = ast_calloc(1, sizeof(*rtp)))) {
00445       return -1;
00446    }
00447 
00448    /* Set default parameters on the newly created RTP structure */
00449    rtp->ssrc = ast_random();
00450    rtp->seqno = ast_random() & 0xffff;
00451    rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN);
00452 
00453    /* Create a new socket for us to listen on and use */
00454    if ((rtp->s =
00455         create_new_socket("RTP",
00456                 ast_sockaddr_is_ipv4(addr) ? AF_INET  :
00457                 ast_sockaddr_is_ipv6(addr) ? AF_INET6 : -1)) < 0) {
00458       ast_debug(1, "Failed to create a new socket for RTP instance '%p'\n", instance);
00459       ast_free(rtp);
00460       return -1;
00461    }
00462 
00463    /* Now actually find a free RTP port to use */
00464    x = (rtpend == rtpstart) ? rtpstart : (ast_random() % (rtpend - rtpstart)) + rtpstart;
00465    x = x & ~1;
00466    startplace = x;
00467 
00468    for (;;) {
00469       ast_sockaddr_set_port(addr, x);
00470       /* Try to bind, this will tell us whether the port is available or not */
00471       if (!ast_bind(rtp->s, addr)) {
00472          ast_debug(1, "Allocated port %d for RTP instance '%p'\n", x, instance);
00473          ast_rtp_instance_set_local_address(instance, addr);
00474          break;
00475       }
00476 
00477       x += 2;
00478       if (x > rtpend) {
00479          x = (rtpstart + 1) & ~1;
00480       }
00481 
00482       /* See if we ran out of ports or if the bind actually failed because of something other than the address being in use */
00483       if (x == startplace || errno != EADDRINUSE) {
00484          ast_log(LOG_ERROR, "Oh dear... we couldn't allocate a port for RTP instance '%p'\n", instance);
00485          return -1;
00486       }
00487    }
00488 
00489    /* Record any information we may need */
00490    rtp->sched = sched;
00491 
00492    /* Associate the RTP structure with the RTP instance and be done */
00493    ast_rtp_instance_set_data(instance, rtp);
00494 
00495    return 0;
00496 }

static void ast_rtp_prop_set ( struct ast_rtp_instance instance,
enum ast_rtp_property  property,
int  value 
) [static]

Definition at line 2331 of file res_rtp_asterisk.c.

References ast_bind(), ast_calloc, ast_debug, ast_free, ast_rtp_instance_get_data(), ast_rtp_instance_get_local_address(), AST_RTP_PROPERTY_RTCP, ast_sockaddr_is_ipv4(), ast_sockaddr_is_ipv6(), ast_sockaddr_port, ast_sockaddr_set_port, create_new_socket(), ast_rtp::rtcp, ast_rtcp::s, ast_rtcp::schedid, and ast_rtcp::us.

02332 {
02333    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02334 
02335    if (property == AST_RTP_PROPERTY_RTCP) {
02336       if (rtp->rtcp) {
02337          ast_debug(1, "Ignoring duplicate RTCP property on RTP instance '%p'\n", instance);
02338          return;
02339       }
02340       if (!(rtp->rtcp = ast_calloc(1, sizeof(*rtp->rtcp)))) {
02341          return;
02342       }
02343 
02344       /* Grab the IP address and port we are going to use */
02345       ast_rtp_instance_get_local_address(instance, &rtp->rtcp->us);
02346       ast_sockaddr_set_port(&rtp->rtcp->us,
02347                   ast_sockaddr_port(&rtp->rtcp->us) + 1);
02348 
02349       if ((rtp->rtcp->s =
02350            create_new_socket("RTCP",
02351                    ast_sockaddr_is_ipv4(&rtp->rtcp->us) ?
02352                    AF_INET :
02353                    ast_sockaddr_is_ipv6(&rtp->rtcp->us) ?
02354                    AF_INET6 : -1)) < 0) {
02355          ast_debug(1, "Failed to create a new socket for RTCP on instance '%p'\n", instance);
02356          ast_free(rtp->rtcp);
02357          rtp->rtcp = NULL;
02358          return;
02359       }
02360 
02361       /* Try to actually bind to the IP address and port we are going to use for RTCP, if this fails we have to bail out */
02362       if (ast_bind(rtp->rtcp->s, &rtp->rtcp->us)) {
02363          ast_debug(1, "Failed to setup RTCP on RTP instance '%p'\n", instance);
02364          close(rtp->rtcp->s);
02365          ast_free(rtp->rtcp);
02366          rtp->rtcp = NULL;
02367          return;
02368       }
02369 
02370       ast_debug(1, "Setup RTCP on RTP instance '%p'\n", instance);
02371       rtp->rtcp->schedid = -1;
02372 
02373       return;
02374    }
02375 
02376    return;
02377 }

static int ast_rtp_qos_set ( struct ast_rtp_instance instance,
int  tos,
int  cos,
const char *  desc 
) [static]

Definition at line 2587 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data(), ast_set_qos(), and ast_rtp::s.

02588 {
02589    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02590 
02591    return ast_set_qos(rtp->s, tos, cos, desc);
02592 }

static int ast_rtp_raw_write ( struct ast_rtp_instance instance,
struct ast_frame frame,
int  codec 
) [static]

Definition at line 1034 of file res_rtp_asterisk.c.

References ast_clear_flag, ast_debug, AST_FORMAT_G722, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, ast_rtcp_calc_interval(), ast_rtcp_write(), ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), ast_rtp_instance_get_remote_address(), AST_RTP_PROPERTY_NAT, ast_sched_add(), ast_set_flag, ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_test_flag, ast_tvzero(), ast_verbose, calc_txstamp(), ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, ast_frame::delivery, errno, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, FLAG_NEED_MARKER_BIT, ast_frame::frametype, ast_rtp::lastdigitts, ast_rtp::lastotexttimestamp, ast_rtp::lastovidtimestamp, ast_rtp::lastts, MAX_TIMESTAMP_SKEW, option_debug, ast_frame::ptr, put_unaligned_uint32(), ast_rtp::rtcp, rtp_debug_test_addr(), rtp_get_rate(), rtp_sendto(), rtpdebug, ast_frame::samples, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::sending_digit, ast_rtp::seqno, ast_rtp::ssrc, ast_frame::subclass, ast_frame::ts, ast_rtp::txcount, and ast_rtp::txoctetcount.

Referenced by ast_rtp_write().

01035 {
01036    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
01037    int pred, mark = 0;
01038    unsigned int ms = calc_txstamp(rtp, &frame->delivery);
01039    struct ast_sockaddr remote_address = { {0,} };
01040    int rate = rtp_get_rate(frame->subclass.codec) / 1000;
01041 
01042    if (frame->subclass.codec == AST_FORMAT_G722) {
01043       frame->samples /= 2;
01044    }
01045 
01046    if (rtp->sending_digit) {
01047       return 0;
01048    }
01049 
01050    if (frame->frametype == AST_FRAME_VOICE) {
01051       pred = rtp->lastts + frame->samples;
01052 
01053       /* Re-calculate last TS */
01054       rtp->lastts = rtp->lastts + ms * rate;
01055       if (ast_tvzero(frame->delivery)) {
01056          /* If this isn't an absolute delivery time, Check if it is close to our prediction,
01057             and if so, go with our prediction */
01058          if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW) {
01059             rtp->lastts = pred;
01060          } else {
01061             ast_debug(3, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms);
01062             mark = 1;
01063          }
01064       }
01065    } else if (frame->frametype == AST_FRAME_VIDEO) {
01066       mark = frame->subclass.codec & 0x1;
01067       pred = rtp->lastovidtimestamp + frame->samples;
01068       /* Re-calculate last TS */
01069       rtp->lastts = rtp->lastts + ms * 90;
01070       /* If it's close to our prediction, go for it */
01071       if (ast_tvzero(frame->delivery)) {
01072          if (abs(rtp->lastts - pred) < 7200) {
01073             rtp->lastts = pred;
01074             rtp->lastovidtimestamp += frame->samples;
01075          } else {
01076             ast_debug(3, "Difference is %d, ms is %d (%d), pred/ts/samples %d/%d/%d\n", abs(rtp->lastts - pred), ms, ms * 90, rtp->lastts, pred, frame->samples);
01077             rtp->lastovidtimestamp = rtp->lastts;
01078          }
01079       }
01080    } else {
01081       pred = rtp->lastotexttimestamp + frame->samples;
01082       /* Re-calculate last TS */
01083       rtp->lastts = rtp->lastts + ms;
01084       /* If it's close to our prediction, go for it */
01085       if (ast_tvzero(frame->delivery)) {
01086          if (abs(rtp->lastts - pred) < 7200) {
01087             rtp->lastts = pred;
01088             rtp->lastotexttimestamp += frame->samples;
01089          } else {
01090             ast_debug(3, "Difference is %d, ms is %d, pred/ts/samples %d/%d/%d\n", abs(rtp->lastts - pred), ms, rtp->lastts, pred, frame->samples);
01091             rtp->lastotexttimestamp = rtp->lastts;
01092          }
01093       }
01094    }
01095 
01096    /* If we have been explicitly told to set the marker bit then do so */
01097    if (ast_test_flag(rtp, FLAG_NEED_MARKER_BIT)) {
01098       mark = 1;
01099       ast_clear_flag(rtp, FLAG_NEED_MARKER_BIT);
01100    }
01101 
01102    /* If the timestamp for non-digt packets has moved beyond the timestamp for digits, update the digit timestamp */
01103    if (rtp->lastts > rtp->lastdigitts) {
01104       rtp->lastdigitts = rtp->lastts;
01105    }
01106 
01107    if (ast_test_flag(frame, AST_FRFLAG_HAS_TIMING_INFO)) {
01108       rtp->lastts = frame->ts * rate;
01109    }
01110 
01111    ast_rtp_instance_get_remote_address(instance, &remote_address);
01112 
01113    /* If we know the remote address construct a packet and send it out */
01114    if (!ast_sockaddr_isnull(&remote_address)) {
01115       int hdrlen = 12, res;
01116       unsigned char *rtpheader = (unsigned char *)(frame->data.ptr - hdrlen);
01117 
01118       put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23)));
01119       put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts));
01120       put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc));
01121 
01122       if ((res = rtp_sendto(instance, (void *)rtpheader, frame->datalen + hdrlen, 0, &remote_address)) < 0) {
01123          if (!ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT) || (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT) && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
01124             ast_debug(1, "RTP Transmission error of packet %d to %s: %s\n",
01125                  rtp->seqno,
01126                  ast_sockaddr_stringify(&remote_address),
01127                  strerror(errno));
01128          } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) {
01129             /* Only give this error message once if we are not RTP debugging */
01130             if (option_debug || rtpdebug)
01131                ast_debug(0, "RTP NAT: Can't write RTP to private address %s, waiting for other end to send audio...\n",
01132                     ast_sockaddr_stringify(&remote_address));
01133             ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN);
01134          }
01135       } else {
01136          rtp->txcount++;
01137          rtp->txoctetcount += (res - hdrlen);
01138 
01139          if (rtp->rtcp && rtp->rtcp->schedid < 1) {
01140             ast_debug(1, "Starting RTCP transmission on RTP instance '%p'\n", instance);
01141             rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, instance);
01142          }
01143       }
01144 
01145       if (rtp_debug_test_addr(&remote_address)) {
01146          ast_verbose("Sent RTP packet to      %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
01147                 ast_sockaddr_stringify(&remote_address),
01148                 codec, rtp->seqno, rtp->lastts, res - hdrlen);
01149       }
01150    }
01151 
01152    rtp->seqno++;
01153 
01154    return 0;
01155 }

static struct ast_frame * ast_rtp_read ( struct ast_rtp_instance instance,
int  rtcp 
) [static]

Definition at line 1980 of file res_rtp_asterisk.c.

References ast_rtp::alt_rtp_address, ast_assert, ast_codec_get_samples(), AST_CONTROL_SRCCHANGE, ast_debug, AST_FORMAT_AUDIO_MASK, AST_FORMAT_SLINEAR, AST_FORMAT_SLINEAR16, AST_FORMAT_T140, AST_FORMAT_T140RED, AST_FORMAT_VIDEO_MASK, ast_frame_byteswap_be, AST_FRAME_CONTROL, AST_FRAME_DTMF_END, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_frisolate(), AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_INSERT_TAIL, ast_log(), ast_null_frame, ast_rtcp_calc_interval(), ast_rtcp_read(), ast_rtcp_write(), AST_RTP_CISCO_DTMF, AST_RTP_CN, ast_rtp_codecs_payload_lookup(), AST_RTP_DTMF, ast_rtp_dtmf_continuation(), ast_rtp_instance_get_bridged(), ast_rtp_instance_get_codecs(), ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), ast_rtp_instance_get_remote_address(), ast_rtp_instance_set_remote_address(), AST_RTP_PROPERTY_NAT, ast_samp2tv(), ast_sched_add(), ast_set_flag, ast_sockaddr_cmp(), ast_sockaddr_copy(), ast_sockaddr_from_sin, ast_sockaddr_isnull(), ast_sockaddr_port, ast_sockaddr_set_port, ast_sockaddr_stringify(), ast_sockaddr_to_sin, ast_strdupa, AST_STUN_ACCEPT, ast_stun_handle_packet(), ast_tv(), ast_tvdiff_ms(), ast_verbose, ast_rtp_payload_type::asterisk_format, bridge_p2p_rtp_write(), ast_rtp_payload_type::code, ast_frame_subclass::codec, create_dtmf_frame(), ast_rtp::cycles, ast_frame::data, ast_frame::datalen, ast_rtp::dtmf_duration, ast_rtp::dtmf_timeout, errno, ext, ast_rtp::f, f, FLAG_NAT_ACTIVE, frames, ast_frame::frametype, ast_rtp::lastrxformat, ast_rtp::lastrxseqno, ast_rtp::lastrxts, len(), LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, ast_frame::offset, option_debug, process_cn_rfc3389(), process_dtmf_cisco(), process_dtmf_rfc2833(), ast_frame::ptr, ast_rtp::rawdata, ast_rtp::resp, ast_rtp::rtcp, rtp_debug_test_addr(), rtp_get_rate(), rtp_recvfrom(), RTP_SEQ_MOD, rtpdebug, ast_rtp::rxcount, ast_rtp::rxseqno, ast_rtp::rxssrc, ast_rtp::s, ast_frame::samples, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, ast_rtp::sending_digit, ast_frame::seqno, ast_frame::src, ast_rtp::strict_rtp_address, STRICT_RTP_CLOSED, STRICT_RTP_LEARN, ast_rtp::strict_rtp_state, ast_frame::subclass, ast_rtcp::them, ast_rtp::themssrc, and version.

01981 {
01982    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
01983    struct ast_sockaddr addr;
01984    int res, hdrlen = 12, version, payloadtype, padding, mark, ext, cc, prev_seqno;
01985    unsigned int *rtpheader = (unsigned int*)(rtp->rawdata + AST_FRIENDLY_OFFSET), seqno, ssrc, timestamp;
01986    struct ast_rtp_payload_type payload;
01987    struct ast_sockaddr remote_address = { {0,} };
01988    struct frame_list frames;
01989 
01990    /* If this is actually RTCP let's hop on over and handle it */
01991    if (rtcp) {
01992       if (rtp->rtcp) {
01993          return ast_rtcp_read(instance);
01994       }
01995       return &ast_null_frame;
01996    }
01997 
01998    /* If we are currently sending DTMF to the remote party send a continuation packet */
01999    if (rtp->sending_digit) {
02000       ast_rtp_dtmf_continuation(instance);
02001    }
02002 
02003    /* Actually read in the data from the socket */
02004    if ((res = rtp_recvfrom(instance, rtp->rawdata + AST_FRIENDLY_OFFSET,
02005             sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 0,
02006             &addr)) < 0) {
02007       ast_assert(errno != EBADF);
02008       if (errno != EAGAIN) {
02009          ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n", strerror(errno));
02010          return NULL;
02011       }
02012       return &ast_null_frame;
02013    }
02014 
02015    /* Make sure the data that was read in is actually enough to make up an RTP packet */
02016    if (res < hdrlen) {
02017       ast_log(LOG_WARNING, "RTP Read too short\n");
02018       return &ast_null_frame;
02019    }
02020 
02021    /* If strict RTP protection is enabled see if we need to learn the remote address or if we need to drop the packet */
02022    if (rtp->strict_rtp_state == STRICT_RTP_LEARN) {
02023       ast_sockaddr_copy(&rtp->strict_rtp_address, &addr);
02024       rtp->strict_rtp_state = STRICT_RTP_CLOSED;
02025    } else if (rtp->strict_rtp_state == STRICT_RTP_CLOSED) {
02026       if (ast_sockaddr_cmp(&rtp->strict_rtp_address, &addr)) {
02027          /* Hmm, not the strict addres. Perhaps we're getting audio from the alternate? */
02028          if (!ast_sockaddr_cmp(&rtp->alt_rtp_address, &addr)) {
02029             /* ooh, we did! You're now the new expected address, son! */
02030             ast_sockaddr_copy(&rtp->strict_rtp_address,
02031                     &addr);
02032          } else  {
02033             const char *real_addr = ast_strdupa(ast_sockaddr_stringify(&addr));
02034             const char *expected_addr = ast_strdupa(ast_sockaddr_stringify(&rtp->strict_rtp_address));
02035 
02036             ast_debug(1, "Received RTP packet from %s, dropping due to strict RTP protection. Expected it to be from %s\n",
02037                   real_addr, expected_addr);
02038 
02039             return &ast_null_frame;
02040          }
02041       }
02042    }
02043 
02044    /* Get fields and verify this is an RTP packet */
02045    seqno = ntohl(rtpheader[0]);
02046 
02047    ast_rtp_instance_get_remote_address(instance, &remote_address);
02048 
02049    if (!(version = (seqno & 0xC0000000) >> 30)) {
02050       struct sockaddr_in addr_tmp;
02051       ast_sockaddr_to_sin(&addr, &addr_tmp);
02052       if ((ast_stun_handle_packet(rtp->s, &addr_tmp, rtp->rawdata + AST_FRIENDLY_OFFSET, res, NULL, NULL) == AST_STUN_ACCEPT) &&
02053           ast_sockaddr_isnull(&remote_address)) {
02054          ast_sockaddr_from_sin(&addr, &addr_tmp);
02055          ast_rtp_instance_set_remote_address(instance, &addr);
02056       }
02057       return &ast_null_frame;
02058    }
02059 
02060    /* If symmetric RTP is enabled see if the remote side is not what we expected and change where we are sending audio */
02061    if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT)) {
02062       if (ast_sockaddr_cmp(&remote_address, &addr)) {
02063          ast_rtp_instance_set_remote_address(instance, &addr);
02064          ast_sockaddr_copy(&remote_address, &addr);
02065          if (rtp->rtcp) {
02066             ast_sockaddr_copy(&rtp->rtcp->them, &addr);
02067             ast_sockaddr_set_port(&rtp->rtcp->them, ast_sockaddr_port(&addr) + 1);
02068          }
02069          rtp->rxseqno = 0;
02070          ast_set_flag(rtp, FLAG_NAT_ACTIVE);
02071          if (option_debug || rtpdebug)
02072             ast_debug(0, "RTP NAT: Got audio from other end. Now sending to address %s\n",
02073                  ast_sockaddr_stringify(&remote_address));
02074       }
02075    }
02076 
02077    /* If we are directly bridged to another instance send the audio directly out */
02078    if (ast_rtp_instance_get_bridged(instance) && !bridge_p2p_rtp_write(instance, rtpheader, res, hdrlen)) {
02079       return &ast_null_frame;
02080    }
02081 
02082    /* If the version is not what we expected by this point then just drop the packet */
02083    if (version != 2) {
02084       return &ast_null_frame;
02085    }
02086 
02087    /* Pull out the various other fields we will need */
02088    payloadtype = (seqno & 0x7f0000) >> 16;
02089    padding = seqno & (1 << 29);
02090    mark = seqno & (1 << 23);
02091    ext = seqno & (1 << 28);
02092    cc = (seqno & 0xF000000) >> 24;
02093    seqno &= 0xffff;
02094    timestamp = ntohl(rtpheader[1]);
02095    ssrc = ntohl(rtpheader[2]);
02096 
02097    AST_LIST_HEAD_INIT_NOLOCK(&frames);
02098    /* Force a marker bit and change SSRC if the SSRC changes */
02099    if (rtp->rxssrc && rtp->rxssrc != ssrc) {
02100       struct ast_frame *f, srcupdate = {
02101          AST_FRAME_CONTROL,
02102          .subclass.integer = AST_CONTROL_SRCCHANGE,
02103       };
02104 
02105       if (!mark) {
02106          if (option_debug || rtpdebug) {
02107             ast_debug(1, "Forcing Marker bit, because SSRC has changed\n");
02108          }
02109          mark = 1;
02110       }
02111 
02112       f = ast_frisolate(&srcupdate);
02113       AST_LIST_INSERT_TAIL(&frames, f, frame_list);
02114    }
02115 
02116    rtp->rxssrc = ssrc;
02117 
02118    /* Remove any padding bytes that may be present */
02119    if (padding) {
02120       res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1];
02121    }
02122 
02123    /* Skip over any CSRC fields */
02124    if (cc) {
02125       hdrlen += cc * 4;
02126    }
02127 
02128    /* Look for any RTP extensions, currently we do not support any */
02129    if (ext) {
02130       hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2;
02131       hdrlen += 4;
02132       if (option_debug) {
02133          int profile;
02134          profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16;
02135          if (profile == 0x505a)
02136             ast_debug(1, "Found Zfone extension in RTP stream - zrtp - not supported.\n");
02137          else
02138             ast_debug(1, "Found unknown RTP Extensions %x\n", profile);
02139       }
02140    }
02141 
02142    /* Make sure after we potentially mucked with the header length that it is once again valid */
02143    if (res < hdrlen) {
02144       ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d\n", res, hdrlen);
02145       return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame;
02146    }
02147 
02148    rtp->rxcount++;
02149    if (rtp->rxcount == 1) {
02150       rtp->seedrxseqno = seqno;
02151    }
02152 
02153    /* Do not schedule RR if RTCP isn't run */
02154    if (rtp->rtcp && !ast_sockaddr_isnull(&rtp->rtcp->them) && rtp->rtcp->schedid < 1) {
02155       /* Schedule transmission of Receiver Report */
02156       rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, instance);
02157    }
02158    if ((int)rtp->lastrxseqno - (int)seqno  > 100) /* if so it would indicate that the sender cycled; allow for misordering */
02159       rtp->cycles += RTP_SEQ_MOD;
02160 
02161    prev_seqno = rtp->lastrxseqno;
02162    rtp->lastrxseqno = seqno;
02163 
02164    if (!rtp->themssrc) {
02165       rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */
02166    }
02167 
02168    if (rtp_debug_test_addr(&addr)) {
02169       ast_verbose("Got  RTP packet from    %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02170              ast_sockaddr_stringify(&addr),
02171              payloadtype, seqno, timestamp,res - hdrlen);
02172    }
02173 
02174    payload = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(instance), payloadtype);
02175 
02176    /* If the payload is not actually an Asterisk one but a special one pass it off to the respective handler */
02177    if (!payload.asterisk_format) {
02178       struct ast_frame *f = NULL;
02179       if (payload.code == AST_RTP_DTMF) {
02180          /* process_dtmf_rfc2833 may need to return multiple frames. We do this
02181           * by passing the pointer to the frame list to it so that the method
02182           * can append frames to the list as needed.
02183           */
02184          process_dtmf_rfc2833(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &addr, payloadtype, mark, &frames);
02185       } else if (payload.code == AST_RTP_CISCO_DTMF) {
02186          f = process_dtmf_cisco(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &addr, payloadtype, mark);
02187       } else if (payload.code == AST_RTP_CN) {
02188          f = process_cn_rfc3389(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &addr, payloadtype, mark);
02189       } else {
02190          ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n",
02191             payloadtype,
02192             ast_sockaddr_stringify(&remote_address));
02193       }
02194 
02195       if (f) {
02196          AST_LIST_INSERT_TAIL(&frames, f, frame_list);
02197       }
02198       /* Even if no frame was returned by one of the above methods,
02199        * we may have a frame to return in our frame list
02200        */
02201       if (!AST_LIST_EMPTY(&frames)) {
02202          return AST_LIST_FIRST(&frames);
02203       }
02204       return &ast_null_frame;
02205    }
02206 
02207    rtp->lastrxformat = rtp->f.subclass.codec = payload.code;
02208    rtp->f.frametype = (rtp->f.subclass.codec & AST_FORMAT_AUDIO_MASK) ? AST_FRAME_VOICE : (rtp->f.subclass.codec & AST_FORMAT_VIDEO_MASK) ? AST_FRAME_VIDEO : AST_FRAME_TEXT;
02209 
02210    rtp->rxseqno = seqno;
02211 
02212    if (rtp->dtmf_timeout && rtp->dtmf_timeout < timestamp) {
02213       rtp->dtmf_timeout = 0;
02214 
02215       if (rtp->resp) {
02216          struct ast_frame *f;
02217          f = create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0);
02218          f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass.codec)), ast_tv(0, 0));
02219          rtp->resp = 0;
02220          rtp->dtmf_timeout = rtp->dtmf_duration = 0;
02221          AST_LIST_INSERT_TAIL(&frames, f, frame_list);
02222          return AST_LIST_FIRST(&frames);
02223       }
02224    }
02225 
02226    rtp->lastrxts = timestamp;
02227 
02228    rtp->f.src = "RTP";
02229    rtp->f.mallocd = 0;
02230    rtp->f.datalen = res - hdrlen;
02231    rtp->f.data.ptr = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
02232    rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
02233    rtp->f.seqno = seqno;
02234 
02235    if (rtp->f.subclass.codec == AST_FORMAT_T140 && (int)seqno - (prev_seqno+1) > 0 && (int)seqno - (prev_seqno+1) < 10) {
02236       unsigned char *data = rtp->f.data.ptr;
02237 
02238       memmove(rtp->f.data.ptr+3, rtp->f.data.ptr, rtp->f.datalen);
02239       rtp->f.datalen +=3;
02240       *data++ = 0xEF;
02241       *data++ = 0xBF;
02242       *data = 0xBD;
02243    }
02244 
02245    if (rtp->f.subclass.codec == AST_FORMAT_T140RED) {
02246       unsigned char *data = rtp->f.data.ptr;
02247       unsigned char *header_end;
02248       int num_generations;
02249       int header_length;
02250       int len;
02251       int diff =(int)seqno - (prev_seqno+1); /* if diff = 0, no drop*/
02252       int x;
02253 
02254       rtp->f.subclass.codec = AST_FORMAT_T140;
02255       header_end = memchr(data, ((*data) & 0x7f), rtp->f.datalen);
02256       if (header_end == NULL) {
02257          return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame;
02258       }
02259       header_end++;
02260 
02261       header_length = header_end - data;
02262       num_generations = header_length / 4;
02263       len = header_length;
02264 
02265       if (!diff) {
02266          for (x = 0; x < num_generations; x++)
02267             len += data[x * 4 + 3];
02268 
02269          if (!(rtp->f.datalen - len))
02270             return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame;
02271 
02272          rtp->f.data.ptr += len;
02273          rtp->f.datalen -= len;
02274       } else if (diff > num_generations && diff < 10) {
02275          len -= 3;
02276          rtp->f.data.ptr += len;
02277          rtp->f.datalen -= len;
02278 
02279          data = rtp->f.data.ptr;
02280          *data++ = 0xEF;
02281          *data++ = 0xBF;
02282          *data = 0xBD;
02283       } else {
02284          for ( x = 0; x < num_generations - diff; x++)
02285             len += data[x * 4 + 3];
02286 
02287          rtp->f.data.ptr += len;
02288          rtp->f.datalen -= len;
02289       }
02290    }
02291 
02292    if (rtp->f.subclass.codec & AST_FORMAT_AUDIO_MASK) {
02293       rtp->f.samples = ast_codec_get_samples(&rtp->f);
02294       if ((rtp->f.subclass.codec == AST_FORMAT_SLINEAR) || (rtp->f.subclass.codec == AST_FORMAT_SLINEAR16)) {
02295          ast_frame_byteswap_be(&rtp->f);
02296       }
02297       calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
02298       /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */
02299       ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO);
02300       rtp->f.ts = timestamp / (rtp_get_rate(rtp->f.subclass.codec) / 1000);
02301       rtp->f.len = rtp->f.samples / ((ast_format_rate(rtp->f.subclass.codec) / 1000));
02302    } else if (rtp->f.subclass.codec & AST_FORMAT_VIDEO_MASK) {
02303       /* Video -- samples is # of samples vs. 90000 */
02304       if (!rtp->lastividtimestamp)
02305          rtp->lastividtimestamp = timestamp;
02306       rtp->f.samples = timestamp - rtp->lastividtimestamp;
02307       rtp->lastividtimestamp = timestamp;
02308       rtp->f.delivery.tv_sec = 0;
02309       rtp->f.delivery.tv_usec = 0;
02310       /* Pass the RTP marker bit as bit 0 in the subclass field.
02311        * This is ok because subclass is actually a bitmask, and
02312        * the low bits represent audio formats, that are not
02313        * involved here since we deal with video.
02314        */
02315       if (mark)
02316          rtp->f.subclass.codec |= 0x1;
02317    } else {
02318       /* TEXT -- samples is # of samples vs. 1000 */
02319       if (!rtp->lastitexttimestamp)
02320          rtp->lastitexttimestamp = timestamp;
02321       rtp->f.samples = timestamp - rtp->lastitexttimestamp;
02322       rtp->lastitexttimestamp = timestamp;
02323       rtp->f.delivery.tv_sec = 0;
02324       rtp->f.delivery.tv_usec = 0;
02325    }
02326 
02327    AST_LIST_INSERT_TAIL(&frames, &rtp->f, frame_list);
02328    return AST_LIST_FIRST(&frames);
02329 }

static void ast_rtp_remote_address_set ( struct ast_rtp_instance instance,
struct ast_sockaddr addr 
) [static]

Definition at line 2386 of file res_rtp_asterisk.c.

References ast_debug, ast_rtp_instance_get_data(), ast_sockaddr_copy(), ast_sockaddr_isnull(), ast_sockaddr_port, ast_sockaddr_set_port, ast_rtp::rtcp, ast_rtp::rxseqno, STRICT_RTP_LEARN, ast_rtp::strict_rtp_state, strictrtp, and ast_rtcp::them.

02387 {
02388    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02389 
02390    if (rtp->rtcp) {
02391       ast_debug(1, "Setting RTCP address on RTP instance '%p'\n", instance);
02392       ast_sockaddr_copy(&rtp->rtcp->them, addr);
02393       if (!ast_sockaddr_isnull(addr)) {
02394          ast_sockaddr_set_port(&rtp->rtcp->them,
02395                      ast_sockaddr_port(addr) + 1);
02396       }
02397    }
02398 
02399    rtp->rxseqno = 0;
02400 
02401    if (strictrtp) {
02402       rtp->strict_rtp_state = STRICT_RTP_LEARN;
02403    }
02404 
02405    return;
02406 }

static void ast_rtp_stop ( struct ast_rtp_instance instance  )  [static]

Definition at line 2565 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data(), ast_rtp_instance_set_remote_address(), AST_SCHED_DEL, ast_set_flag, ast_sockaddr_setnull(), FLAG_NEED_MARKER_BIT, free, ast_rtp::red, ast_rtp::rtcp, ast_rtp::sched, rtp_red::schedid, ast_rtcp::schedid, and ast_rtcp::them.

02566 {
02567    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02568    struct ast_sockaddr addr = { {0,} };
02569 
02570    if (rtp->rtcp) {
02571       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02572    }
02573    if (rtp->red) {
02574       AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
02575       free(rtp->red);
02576       rtp->red = NULL;
02577    }
02578 
02579    ast_rtp_instance_set_remote_address(instance, &addr);
02580    if (rtp->rtcp) {
02581       ast_sockaddr_setnull(&rtp->rtcp->them);
02582    }
02583 
02584    ast_set_flag(rtp, FLAG_NEED_MARKER_BIT);
02585 }

static void ast_rtp_stun_request ( struct ast_rtp_instance instance,
struct ast_sockaddr suggestion,
const char *  username 
) [static]

Definition at line 2555 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data(), ast_sockaddr_from_sin, ast_sockaddr_to_sin, ast_stun_request(), and ast_rtp::s.

02556 {
02557    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02558    struct sockaddr_in suggestion_tmp;
02559 
02560    ast_sockaddr_to_sin(suggestion, &suggestion_tmp);
02561    ast_stun_request(rtp->s, &suggestion_tmp, username, NULL);
02562    ast_sockaddr_from_sin(suggestion, &suggestion_tmp);
02563 }

static void ast_rtp_update_source ( struct ast_rtp_instance instance  )  [static]

Definition at line 719 of file res_rtp_asterisk.c.

References ast_debug, ast_rtp_instance_get_data(), ast_set_flag, and FLAG_NEED_MARKER_BIT.

00720 {
00721    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00722 
00723    /* We simply set this bit so that the next packet sent will have the marker bit turned on */
00724    ast_set_flag(rtp, FLAG_NEED_MARKER_BIT);
00725    ast_debug(3, "Setting the marker bit due to a source update\n");
00726 
00727    return;
00728 }

static int ast_rtp_write ( struct ast_rtp_instance instance,
struct ast_frame frame 
) [static]

Definition at line 1194 of file res_rtp_asterisk.c.

References ast_codec_pref_getsize(), ast_debug, AST_FORMAT_G719, AST_FORMAT_G723_1, AST_FORMAT_SIREN14, AST_FORMAT_SIREN7, AST_FORMAT_SPEEX, AST_FORMAT_SPEEX16, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup(), ast_frfree, ast_getformatname(), ast_log(), ast_rtp_codecs_payload_code(), ast_rtp_instance_get_codecs(), ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address(), ast_rtp_raw_write(), ast_smoother_feed, ast_smoother_feed_be, AST_SMOOTHER_FLAG_BE, ast_smoother_free(), ast_smoother_new(), ast_smoother_read(), ast_smoother_set_flags(), ast_smoother_test_flag(), ast_sockaddr_isnull(), ast_frame_subclass::codec, ast_format_list::cur_ms, ast_frame::datalen, f, ast_format_list::flags, ast_format_list::fr_len, ast_frame::frametype, ast_format_list::inc_ms, ast_rtp::lasttxformat, LOG_WARNING, ast_frame::offset, ast_rtp::red, red_t140_to_red(), ast_rtp::smoother, and ast_frame::subclass.

Referenced by red_write().

01195 {
01196    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
01197    struct ast_sockaddr remote_address = { {0,} };
01198    format_t codec, subclass;
01199 
01200    ast_rtp_instance_get_remote_address(instance, &remote_address);
01201 
01202    /* If we don't actually know the remote address don't even bother doing anything */
01203    if (ast_sockaddr_isnull(&remote_address)) {
01204       ast_debug(1, "No remote address on RTP instance '%p' so dropping frame\n", instance);
01205       return 0;
01206    }
01207 
01208    /* If there is no data length we can't very well send the packet */
01209    if (!frame->datalen) {
01210       ast_debug(1, "Received frame with no data for RTP instance '%p' so dropping frame\n", instance);
01211       return 0;
01212    }
01213 
01214    /* If the packet is not one our RTP stack supports bail out */
01215    if (frame->frametype != AST_FRAME_VOICE && frame->frametype != AST_FRAME_VIDEO && frame->frametype != AST_FRAME_TEXT) {
01216       ast_log(LOG_WARNING, "RTP can only send voice, video, and text\n");
01217       return -1;
01218    }
01219 
01220    if (rtp->red) {
01221       /* return 0; */
01222       /* no primary data or generations to send */
01223       if ((frame = red_t140_to_red(rtp->red)) == NULL)
01224          return 0;
01225    }
01226 
01227    /* Grab the subclass and look up the payload we are going to use */
01228    subclass = frame->subclass.codec;
01229    if (frame->frametype == AST_FRAME_VIDEO) {
01230       subclass &= ~0x1LL;
01231    }
01232    if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, subclass)) < 0) {
01233       ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(frame->subclass.codec));
01234       return -1;
01235    }
01236 
01237    /* Oh dear, if the format changed we will have to set up a new smoother */
01238    if (rtp->lasttxformat != subclass) {
01239       ast_debug(1, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
01240       rtp->lasttxformat = subclass;
01241       if (rtp->smoother) {
01242          ast_smoother_free(rtp->smoother);
01243          rtp->smoother = NULL;
01244       }
01245    }
01246 
01247    /* If no smoother is present see if we have to set one up */
01248    if (!rtp->smoother) {
01249       struct ast_format_list fmt = ast_codec_pref_getsize(&ast_rtp_instance_get_codecs(instance)->pref, subclass);
01250 
01251       switch (subclass) {
01252       case AST_FORMAT_SPEEX:
01253       case AST_FORMAT_SPEEX16:
01254       case AST_FORMAT_G723_1:
01255       case AST_FORMAT_SIREN7:
01256       case AST_FORMAT_SIREN14:
01257       case AST_FORMAT_G719:
01258          /* these are all frame-based codecs and cannot be safely run through
01259             a smoother */
01260          break;
01261       default:
01262          if (fmt.inc_ms) {
01263             if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
01264                ast_log(LOG_WARNING, "Unable to create smoother: format %s ms: %d len: %d\n", ast_getformatname(subclass), fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
01265                return -1;
01266             }
01267             if (fmt.flags) {
01268                ast_smoother_set_flags(rtp->smoother, fmt.flags);
01269             }
01270             ast_debug(1, "Created smoother: format: %s ms: %d len: %d\n", ast_getformatname(subclass), fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
01271          }
01272       }
01273    }
01274 
01275    /* Feed audio frames into the actual function that will create a frame and send it */
01276    if (rtp->smoother) {
01277       struct ast_frame *f;
01278 
01279       if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) {
01280          ast_smoother_feed_be(rtp->smoother, frame);
01281       } else {
01282          ast_smoother_feed(rtp->smoother, frame);
01283       }
01284 
01285       while ((f = ast_smoother_read(rtp->smoother)) && (f->data.ptr)) {
01286             ast_rtp_raw_write(instance, f, codec);
01287       }
01288    } else {
01289       int hdrlen = 12;
01290       struct ast_frame *f = NULL;
01291 
01292       if (frame->offset < hdrlen) {
01293          f = ast_frdup(frame);
01294       } else {
01295          f = frame;
01296       }
01297       if (f->data.ptr) {
01298          ast_rtp_raw_write(instance, f, codec);
01299       }
01300       if (f != frame) {
01301          ast_frfree(f);
01302       }
01303 
01304    }
01305 
01306    return 0;
01307 }

static int bridge_p2p_rtp_write ( struct ast_rtp_instance instance,
unsigned int *  rtpheader,
int  len,
int  hdrlen 
) [static]

Definition at line 1910 of file res_rtp_asterisk.c.

References ast_clear_flag, ast_debug, ast_log(), ast_rtp_codecs_payload_code(), ast_rtp_codecs_payload_lookup(), ast_rtp_instance_get_bridged(), ast_rtp_instance_get_codecs(), ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), ast_rtp_instance_get_remote_address(), AST_RTP_PROPERTY_NAT, ast_set_flag, ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_test_flag, ast_verbose, ast_rtp_payload_type::asterisk_format, ast_rtp::bridged, ast_rtp_payload_type::code, errno, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, FLAG_NEED_MARKER_BIT, LOG_WARNING, option_debug, reconstruct(), rtp_debug_test_addr(), rtp_sendto(), and rtpdebug.

Referenced by ast_rtp_read().

01911 {
01912    struct ast_rtp_instance *instance1 = ast_rtp_instance_get_bridged(instance);
01913    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance), *bridged = ast_rtp_instance_get_data(instance1);
01914    int res = 0, payload = 0, bridged_payload = 0, mark;
01915    struct ast_rtp_payload_type payload_type;
01916    int reconstruct = ntohl(rtpheader[0]);
01917    struct ast_sockaddr remote_address = { {0,} };
01918 
01919    /* Get fields from packet */
01920    payload = (reconstruct & 0x7f0000) >> 16;
01921    mark = (((reconstruct & 0x800000) >> 23) != 0);
01922 
01923    /* Check what the payload value should be */
01924    payload_type = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(instance), payload);
01925 
01926    /* Otherwise adjust bridged payload to match */
01927    bridged_payload = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance1), payload_type.asterisk_format, payload_type.code);
01928 
01929    /* If the payload coming in is not one of the negotiated ones then send it to the core, this will cause formats to change and the bridge to break */
01930    if (!(ast_rtp_instance_get_codecs(instance1)->payloads[bridged_payload].code)) {
01931       return -1;
01932    }
01933 
01934    /* If the marker bit has been explicitly set turn it on */
01935    if (ast_test_flag(rtp, FLAG_NEED_MARKER_BIT)) {
01936       mark = 1;
01937       ast_clear_flag(rtp, FLAG_NEED_MARKER_BIT);
01938    }
01939 
01940    /* Reconstruct part of the packet */
01941    reconstruct &= 0xFF80FFFF;
01942    reconstruct |= (bridged_payload << 16);
01943    reconstruct |= (mark << 23);
01944    rtpheader[0] = htonl(reconstruct);
01945 
01946    ast_rtp_instance_get_remote_address(instance1, &remote_address);
01947 
01948    if (ast_sockaddr_isnull(&remote_address)) {
01949       ast_debug(1, "Remote address is null, most likely RTP has been stopped\n");
01950       return 0;
01951    }
01952 
01953    /* Send the packet back out */
01954    res = rtp_sendto(instance1, (void *)rtpheader, len, 0, &remote_address);
01955    if (res < 0) {
01956       if (!ast_rtp_instance_get_prop(instance1, AST_RTP_PROPERTY_NAT) || (ast_rtp_instance_get_prop(instance1, AST_RTP_PROPERTY_NAT) && (ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
01957          ast_log(LOG_WARNING,
01958             "RTP Transmission error of packet to %s: %s\n",
01959             ast_sockaddr_stringify(&remote_address),
01960             strerror(errno));
01961       } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) {
01962          if (option_debug || rtpdebug)
01963             ast_log(LOG_WARNING,
01964                "RTP NAT: Can't write RTP to private "
01965                "address %s, waiting for other end to "
01966                "send audio...\n",
01967                ast_sockaddr_stringify(&remote_address));
01968          ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN);
01969       }
01970       return 0;
01971    } else if (rtp_debug_test_addr(&remote_address)) {
01972       ast_verbose("Sent RTP P2P packet to %s (type %-2.2d, len %-6.6u)\n",
01973              ast_sockaddr_stringify(&remote_address),
01974              bridged_payload, len - hdrlen);
01975    }
01976 
01977    return 0;
01978 }

static void calc_rxstamp ( struct timeval *  tv,
struct ast_rtp rtp,
unsigned int  timestamp,
int  mark 
) [static]

Definition at line 1309 of file res_rtp_asterisk.c.

References ast_samp2tv(), ast_tvadd(), ast_tvsub(), ast_frame_subclass::codec, ast_rtp::drxcore, ast_rtp::f, ast_rtcp::maxrxjitter, ast_rtcp::minrxjitter, normdev_compute(), ast_rtcp::normdev_rxjitter, ast_rtp::rtcp, rtp_get_rate(), ast_rtp::rxcore, ast_rtp::rxjitter, ast_rtcp::rxjitter_count, ast_rtp::rxtransit, ast_rtp::seedrxts, stddev_compute(), ast_rtcp::stdev_rxjitter, and ast_frame::subclass.

01310 {
01311    struct timeval now;
01312    struct timeval tmp;
01313    double transit;
01314    double current_time;
01315    double d;
01316    double dtv;
01317    double prog;
01318    int rate = rtp_get_rate(rtp->f.subclass.codec);
01319 
01320    double normdev_rxjitter_current;
01321    if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) {
01322       gettimeofday(&rtp->rxcore, NULL);
01323       rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000;
01324       /* map timestamp to a real time */
01325       rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */
01326       tmp = ast_samp2tv(timestamp, rate);
01327       rtp->rxcore = ast_tvsub(rtp->rxcore, tmp);
01328       /* Round to 0.1ms for nice, pretty timestamps */
01329       rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100;
01330    }
01331 
01332    gettimeofday(&now,NULL);
01333    /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */
01334    tmp = ast_samp2tv(timestamp, rate);
01335    *tv = ast_tvadd(rtp->rxcore, tmp);
01336 
01337    prog = (double)((timestamp-rtp->seedrxts)/(float)(rate));
01338    dtv = (double)rtp->drxcore + (double)(prog);
01339    current_time = (double)now.tv_sec + (double)now.tv_usec/1000000;
01340    transit = current_time - dtv;
01341    d = transit - rtp->rxtransit;
01342    rtp->rxtransit = transit;
01343    if (d<0)
01344       d=-d;
01345    rtp->rxjitter += (1./16.) * (d - rtp->rxjitter);
01346 
01347    if (rtp->rtcp) {
01348       if (rtp->rxjitter > rtp->rtcp->maxrxjitter)
01349          rtp->rtcp->maxrxjitter = rtp->rxjitter;
01350       if (rtp->rtcp->rxjitter_count == 1)
01351          rtp->rtcp->minrxjitter = rtp->rxjitter;
01352       if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter)
01353          rtp->rtcp->minrxjitter = rtp->rxjitter;
01354 
01355       normdev_rxjitter_current = normdev_compute(rtp->rtcp->normdev_rxjitter,rtp->rxjitter,rtp->rtcp->rxjitter_count);
01356       rtp->rtcp->stdev_rxjitter = stddev_compute(rtp->rtcp->stdev_rxjitter,rtp->rxjitter,rtp->rtcp->normdev_rxjitter,normdev_rxjitter_current,rtp->rtcp->rxjitter_count);
01357 
01358       rtp->rtcp->normdev_rxjitter = normdev_rxjitter_current;
01359       rtp->rtcp->rxjitter_count++;
01360    }
01361 }

static unsigned int calc_txstamp ( struct ast_rtp rtp,
struct timeval *  delivery 
) [static]

Definition at line 756 of file res_rtp_asterisk.c.

References ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), and ast_rtp::txcore.

Referenced by ast_rtp_raw_write().

00757 {
00758    struct timeval t;
00759    long ms;
00760 
00761    if (ast_tvzero(rtp->txcore)) {
00762       rtp->txcore = ast_tvnow();
00763       rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
00764    }
00765 
00766    t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
00767    if ((ms = ast_tvdiff_ms(t, rtp->txcore)) < 0) {
00768       ms = 0;
00769    }
00770    rtp->txcore = t;
00771 
00772    return (unsigned int) ms;
00773 }

static struct ast_frame* create_dtmf_frame ( struct ast_rtp_instance instance,
enum ast_frame_type  type,
int  compensate 
) [static]

Definition at line 1363 of file res_rtp_asterisk.c.

References AST_CONTROL_FLASH, ast_debug, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_LIST_NEXT, ast_null_frame, ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address(), ast_sockaddr_stringify(), ast_tvcmp(), ast_tvnow(), ast_frame::datalen, ast_rtp::dtmfmute, ast_rtp::dtmfsamples, ast_rtp::f, ast_frame::frametype, ast_frame_subclass::integer, ast_frame::mallocd, ast_rtp::resp, ast_frame::samples, ast_frame::src, and ast_frame::subclass.

Referenced by ast_rtp_read(), process_dtmf_cisco(), and process_dtmf_rfc2833().

01364 {
01365    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
01366    struct ast_sockaddr remote_address = { {0,} };
01367 
01368    ast_rtp_instance_get_remote_address(instance, &remote_address);
01369 
01370    if (((compensate && type == AST_FRAME_DTMF_END) || (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) {
01371       ast_debug(1, "Ignore potential DTMF echo from '%s'\n",
01372            ast_sockaddr_stringify(&remote_address));
01373       rtp->resp = 0;
01374       rtp->dtmfsamples = 0;
01375       return &ast_null_frame;
01376    }
01377    ast_debug(1, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp,
01378         ast_sockaddr_stringify(&remote_address));
01379    if (rtp->resp == 'X') {
01380       rtp->f.frametype = AST_FRAME_CONTROL;
01381       rtp->f.subclass.integer = AST_CONTROL_FLASH;
01382    } else {
01383       rtp->f.frametype = type;
01384       rtp->f.subclass.integer = rtp->resp;
01385    }
01386    rtp->f.datalen = 0;
01387    rtp->f.samples = 0;
01388    rtp->f.mallocd = 0;
01389    rtp->f.src = "RTP";
01390    AST_LIST_NEXT(&rtp->f, frame_list) = NULL;
01391 
01392    return &rtp->f;
01393 }

static int create_new_socket ( const char *  type,
int  af 
) [static]

Definition at line 414 of file res_rtp_asterisk.c.

References ast_log(), errno, and LOG_WARNING.

Referenced by ast_rtp_new(), and ast_rtp_prop_set().

00415 {
00416    int sock = socket(af, SOCK_DGRAM, 0);
00417 
00418    if (sock < 0) {
00419       if (!type) {
00420          type = "RTP/RTCP";
00421       }
00422       ast_log(LOG_WARNING, "Unable to allocate %s socket: %s\n", type, strerror(errno));
00423    } else {
00424       long flags = fcntl(sock, F_GETFL);
00425       fcntl(sock, F_SETFL, flags | O_NONBLOCK);
00426 #ifdef SO_NO_CHECK
00427       if (nochecksums) {
00428          setsockopt(sock, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
00429       }
00430 #endif
00431    }
00432 
00433    return sock;
00434 }

static char* handle_cli_rtcp_set_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2655 of file res_rtp_asterisk.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, rtcp_do_debug_ip(), rtcpdebug, rtcpdebugaddr, and ast_cli_entry::usage.

02656 {
02657    switch (cmd) {
02658    case CLI_INIT:
02659       e->command = "rtcp set debug {on|off|ip}";
02660       e->usage =
02661          "Usage: rtcp set debug {on|off|ip host[:port]}\n"
02662          "       Enable/Disable dumping of all RTCP packets. If 'ip' is\n"
02663          "       specified, limit the dumped packets to those to and from\n"
02664          "       the specified 'host' with optional port.\n";
02665       return NULL;
02666    case CLI_GENERATE:
02667       return NULL;
02668    }
02669 
02670    if (a->argc == e->args) { /* set on or off */
02671       if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
02672          rtcpdebug = 1;
02673          memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr));
02674          ast_cli(a->fd, "RTCP Debugging Enabled\n");
02675          return CLI_SUCCESS;
02676       } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
02677          rtcpdebug = 0;
02678          ast_cli(a->fd, "RTCP Debugging Disabled\n");
02679          return CLI_SUCCESS;
02680       }
02681    } else if (a->argc == e->args +1) { /* ip */
02682       return rtcp_do_debug_ip(a);
02683    }
02684 
02685    return CLI_SHOWUSAGE;   /* default, failure */
02686 }

static char* handle_cli_rtcp_set_stats ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2688 of file res_rtp_asterisk.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, rtcpstats, and ast_cli_entry::usage.

02689 {
02690    switch (cmd) {
02691    case CLI_INIT:
02692       e->command = "rtcp set stats {on|off}";
02693       e->usage =
02694          "Usage: rtcp set stats {on|off}\n"
02695          "       Enable/Disable dumping of RTCP stats.\n";
02696       return NULL;
02697    case CLI_GENERATE:
02698       return NULL;
02699    }
02700 
02701    if (a->argc != e->args)
02702       return CLI_SHOWUSAGE;
02703 
02704    if (!strncasecmp(a->argv[e->args-1], "on", 2))
02705       rtcpstats = 1;
02706    else if (!strncasecmp(a->argv[e->args-1], "off", 3))
02707       rtcpstats = 0;
02708    else
02709       return CLI_SHOWUSAGE;
02710 
02711    ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled");
02712    return CLI_SUCCESS;
02713 }

static char* handle_cli_rtp_set_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2622 of file res_rtp_asterisk.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, rtp_do_debug_ip(), rtpdebug, rtpdebugaddr, and ast_cli_entry::usage.

02623 {
02624    switch (cmd) {
02625    case CLI_INIT:
02626       e->command = "rtp set debug {on|off|ip}";
02627       e->usage =
02628          "Usage: rtp set debug {on|off|ip host[:port]}\n"
02629          "       Enable/Disable dumping of all RTP packets. If 'ip' is\n"
02630          "       specified, limit the dumped packets to those to and from\n"
02631          "       the specified 'host' with optional port.\n";
02632       return NULL;
02633    case CLI_GENERATE:
02634       return NULL;
02635    }
02636 
02637    if (a->argc == e->args) { /* set on or off */
02638       if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
02639          rtpdebug = 1;
02640          memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr));
02641          ast_cli(a->fd, "RTP Debugging Enabled\n");
02642          return CLI_SUCCESS;
02643       } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
02644          rtpdebug = 0;
02645          ast_cli(a->fd, "RTP Debugging Disabled\n");
02646          return CLI_SUCCESS;
02647       }
02648    } else if (a->argc == e->args +1) { /* ip */
02649       return rtp_do_debug_ip(a);
02650    }
02651 
02652    return CLI_SHOWUSAGE;   /* default, failure */
02653 }

static int load_module ( void   )  [static]

Definition at line 2796 of file res_rtp_asterisk.c.

References ARRAY_LEN, ast_cli_register_multiple(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_rtp_engine_register, ast_rtp_engine_unregister(), asterisk_rtp_engine, cli_rtp, and rtp_reload().

02797 {
02798    if (ast_rtp_engine_register(&asterisk_rtp_engine)) {
02799       return AST_MODULE_LOAD_DECLINE;
02800    }
02801 
02802    if (ast_cli_register_multiple(cli_rtp, ARRAY_LEN(cli_rtp))) {
02803       ast_rtp_engine_unregister(&asterisk_rtp_engine);
02804       return AST_MODULE_LOAD_DECLINE;
02805    }
02806 
02807    rtp_reload(0);
02808 
02809    return AST_MODULE_LOAD_SUCCESS;
02810 }

static double normdev_compute ( double  normdev,
double  sample,
unsigned int  sample_count 
) [static]

Calculate normal deviation.

Definition at line 386 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), and calc_rxstamp().

00387 {
00388    normdev = normdev * sample_count + sample;
00389    sample_count++;
00390 
00391    return normdev / sample_count;
00392 }

static struct ast_frame* process_cn_rfc3389 ( struct ast_rtp_instance instance,
unsigned char *  data,
int  len,
unsigned int  seqno,
unsigned int  timestamp,
struct ast_sockaddr addr,
int  payloadtype,
int  mark 
) [static]

Definition at line 1599 of file res_rtp_asterisk.c.

References ast_debug, AST_FRAME_CNG, AST_FRIENDLY_OFFSET, ast_log(), ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address(), ast_set_flag, ast_sockaddr_stringify(), ast_test_flag, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp::f, FLAG_3389_WARNING, ast_frame::frametype, ast_frame_subclass::integer, ast_rtp::lastrxformat, LOG_NOTICE, ast_frame::offset, ast_frame::ptr, ast_rtp::rawdata, rtpdebug, ast_frame::samples, and ast_frame::subclass.

Referenced by ast_rtp_read().

01600 {
01601    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
01602 
01603    /* Convert comfort noise into audio with various codecs.  Unfortunately this doesn't
01604       totally help us out becuase we don't have an engine to keep it going and we are not
01605       guaranteed to have it every 20ms or anything */
01606    if (rtpdebug)
01607       ast_debug(0, "- RTP 3389 Comfort noise event: Level %" PRId64 " (len = %d)\n", rtp->lastrxformat, len);
01608 
01609    if (ast_test_flag(rtp, FLAG_3389_WARNING)) {
01610       struct ast_sockaddr remote_address = { {0,} };
01611 
01612       ast_rtp_instance_get_remote_address(instance, &remote_address);
01613 
01614       ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client address: %s\n",
01615          ast_sockaddr_stringify(&remote_address));
01616       ast_set_flag(rtp, FLAG_3389_WARNING);
01617    }
01618 
01619    /* Must have at least one byte */
01620    if (!len)
01621       return NULL;
01622    if (len < 24) {
01623       rtp->f.data.ptr = rtp->rawdata + AST_FRIENDLY_OFFSET;
01624       rtp->f.datalen = len - 1;
01625       rtp->f.offset = AST_FRIENDLY_OFFSET;
01626       memcpy(rtp->f.data.ptr, data + 1, len - 1);
01627    } else {
01628       rtp->f.data.ptr = NULL;
01629       rtp->f.offset = 0;
01630       rtp->f.datalen = 0;
01631    }
01632    rtp->f.frametype = AST_FRAME_CNG;
01633    rtp->f.subclass.integer = data[0] & 0x7f;
01634    rtp->f.samples = 0;
01635    rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0;
01636 
01637    return &rtp->f;
01638 }

static struct ast_frame* process_dtmf_cisco ( struct ast_rtp_instance instance,
unsigned char *  data,
int  len,
unsigned int  seqno,
unsigned int  timestamp,
struct ast_sockaddr addr,
int  payloadtype,
int  mark 
) [static]

Definition at line 1520 of file res_rtp_asterisk.c.

References ast_debug, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), AST_RTP_PROPERTY_DTMF_COMPENSATE, create_dtmf_frame(), ast_rtp::dtmf_timeout, ast_rtp::dtmfsamples, f, ast_rtp::flags, ast_rtp::lastrxformat, option_debug, ast_rtp::resp, rtp_get_rate(), rtpdebug, and seq.

Referenced by ast_rtp_read().

01521 {
01522    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
01523    unsigned int event, flags, power;
01524    char resp = 0;
01525    unsigned char seq;
01526    struct ast_frame *f = NULL;
01527 
01528    if (len < 4) {
01529       return NULL;
01530    }
01531 
01532    /*      The format of Cisco RTP DTMF packet looks like next:
01533       +0                              - sequence number of DTMF RTP packet (begins from 1,
01534                     wrapped to 0)
01535       +1                              - set of flags
01536       +1 (bit 0)              - flaps by different DTMF digits delimited by audio
01537                     or repeated digit without audio???
01538       +2 (+4,+6,...)  - power level? (rises from 0 to 32 at begin of tone
01539                     then falls to 0 at its end)
01540       +3 (+5,+7,...)  - detected DTMF digit (0..9,*,#,A-D,...)
01541       Repeated DTMF information (bytes 4/5, 6/7) is history shifted right
01542       by each new packet and thus provides some redudancy.
01543 
01544       Sample of Cisco RTP DTMF packet is (all data in hex):
01545          19 07 00 02 12 02 20 02
01546       showing end of DTMF digit '2'.
01547 
01548       The packets
01549          27 07 00 02 0A 02 20 02
01550          28 06 20 02 00 02 0A 02
01551       shows begin of new digit '2' with very short pause (20 ms) after
01552       previous digit '2'. Bit +1.0 flips at begin of new digit.
01553 
01554       Cisco RTP DTMF packets comes as replacement of audio RTP packets
01555       so its uses the same sequencing and timestamping rules as replaced
01556       audio packets. Repeat interval of DTMF packets is 20 ms and not rely
01557       on audio framing parameters. Marker bit isn't used within stream of
01558       DTMFs nor audio stream coming immediately after DTMF stream. Timestamps
01559       are not sequential at borders between DTMF and audio streams,
01560    */
01561 
01562    seq = data[0];
01563    flags = data[1];
01564    power = data[2];
01565    event = data[3] & 0x1f;
01566 
01567    if (option_debug > 2 || rtpdebug)
01568       ast_debug(0, "Cisco DTMF Digit: %02x (len=%d, seq=%d, flags=%02x, power=%d, history count=%d)\n", event, len, seq, flags, power, (len - 4) / 2);
01569    if (event < 10) {
01570       resp = '0' + event;
01571    } else if (event < 11) {
01572       resp = '*';
01573    } else if (event < 12) {
01574       resp = '#';
01575    } else if (event < 16) {
01576       resp = 'A' + (event - 12);
01577    } else if (event < 17) {
01578       resp = 'X';
01579    }
01580    if ((!rtp->resp && power) || (rtp->resp && (rtp->resp != resp))) {
01581       rtp->resp = resp;
01582       /* Why we should care on DTMF compensation at reception? */
01583       if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE)) {
01584          f = create_dtmf_frame(instance, AST_FRAME_DTMF_BEGIN, 0);
01585          rtp->dtmfsamples = 0;
01586       }
01587    } else if ((rtp->resp == resp) && !power) {
01588       f = create_dtmf_frame(instance, AST_FRAME_DTMF_END, ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE));
01589       f->samples = rtp->dtmfsamples * (rtp->lastrxformat ? (rtp_get_rate(rtp->lastrxformat) / 1000) : 8);
01590       rtp->resp = 0;
01591    } else if (rtp->resp == resp)
01592       rtp->dtmfsamples += 20 * (rtp->lastrxformat ? (rtp_get_rate(rtp->lastrxformat) / 1000) : 8);
01593 
01594    rtp->dtmf_timeout = 0;
01595 
01596    return f;
01597 }

static void process_dtmf_rfc2833 ( struct ast_rtp_instance instance,
unsigned char *  data,
int  len,
unsigned int  seqno,
unsigned int  timestamp,
struct ast_sockaddr addr,
int  payloadtype,
int  mark,
struct frame_list frames 
) [static]

Definition at line 1395 of file res_rtp_asterisk.c.

References ast_debug, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_frdup(), AST_LIST_INSERT_TAIL, ast_log(), ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), ast_rtp_instance_get_remote_address(), AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_samp2tv(), ast_sockaddr_stringify(), ast_tv(), ast_tvdiff_ms(), ast_verbose, create_dtmf_frame(), ast_rtp::dtmf_duration, ast_rtp::dtmf_timeout, ast_rtp::dtmfsamples, dtmftimeout, f, frames, ast_rtp::lastevent, LOG_DEBUG, option_debug, ast_rtp::resp, rtp_debug_test_addr(), rtp_get_rate(), and rtpdebug.

Referenced by ast_rtp_read().

01396 {
01397    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
01398    struct ast_sockaddr remote_address = { {0,} };
01399    unsigned int event, event_end, samples;
01400    char resp = 0;
01401    struct ast_frame *f = NULL;
01402 
01403    ast_rtp_instance_get_remote_address(instance, &remote_address);
01404 
01405    /* Figure out event, event end, and samples */
01406    event = ntohl(*((unsigned int *)(data)));
01407    event >>= 24;
01408    event_end = ntohl(*((unsigned int *)(data)));
01409    event_end <<= 8;
01410    event_end >>= 24;
01411    samples = ntohl(*((unsigned int *)(data)));
01412    samples &= 0xFFFF;
01413 
01414    if (rtp_debug_test_addr(&remote_address)) {
01415       ast_verbose("Got  RTP RFC2833 from   %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u, mark %d, event %08x, end %d, duration %-5.5d) \n",
01416              ast_sockaddr_stringify(&remote_address),
01417              payloadtype, seqno, timestamp, len, (mark?1:0), event, ((event_end & 0x80)?1:0), samples);
01418    }
01419 
01420    /* Print out debug if turned on */
01421    if (rtpdebug || option_debug > 2)
01422       ast_debug(0, "- RTP 2833 Event: %08x (len = %d)\n", event, len);
01423 
01424    /* Figure out what digit was pressed */
01425    if (event < 10) {
01426       resp = '0' + event;
01427    } else if (event < 11) {
01428       resp = '*';
01429    } else if (event < 12) {
01430       resp = '#';
01431    } else if (event < 16) {
01432       resp = 'A' + (event - 12);
01433    } else if (event < 17) {        /* Event 16: Hook flash */
01434       resp = 'X';
01435    } else {
01436       /* Not a supported event */
01437       ast_log(LOG_DEBUG, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event);
01438       return;
01439    }
01440 
01441    if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE)) {
01442       if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) {
01443          rtp->resp = resp;
01444          rtp->dtmf_timeout = 0;
01445          f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE)));
01446          f->len = 0;
01447          rtp->lastevent = timestamp;
01448          AST_LIST_INSERT_TAIL(frames, f, frame_list);
01449       }
01450    } else {
01451       /*  The duration parameter measures the complete
01452           duration of the event (from the beginning) - RFC2833.
01453           Account for the fact that duration is only 16 bits long
01454           (about 8 seconds at 8000 Hz) and can wrap is digit
01455           is hold for too long. */
01456       unsigned int new_duration = rtp->dtmf_duration;
01457       unsigned int last_duration = new_duration & 0xFFFF;
01458 
01459       if (last_duration > 64000 && samples < last_duration) {
01460          new_duration += 0xFFFF + 1;
01461       }
01462       new_duration = (new_duration & ~0xFFFF) | samples;
01463 
01464       /* The second portion of this check is to not mistakenly
01465        * stop accepting DTMF if the seqno rolls over beyond
01466        * 65535.
01467        */
01468       if (rtp->lastevent > seqno && rtp->lastevent - seqno < 50) {
01469          /* Out of order frame. Processing this can cause us to
01470           * improperly duplicate incoming DTMF, so just drop
01471           * this.
01472           */
01473          return;
01474       }
01475 
01476       if (event_end & 0x80) {
01477          /* End event */
01478          if ((rtp->lastevent != seqno) && rtp->resp) {
01479             rtp->dtmf_duration = new_duration;
01480             f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0));
01481             f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass.codec)), ast_tv(0, 0));
01482             rtp->resp = 0;
01483             rtp->dtmf_duration = rtp->dtmf_timeout = 0;
01484             AST_LIST_INSERT_TAIL(frames, f, frame_list);
01485          }
01486       } else {
01487          /* Begin/continuation */
01488 
01489          if (rtp->resp && rtp->resp != resp) {
01490             /* Another digit already began. End it */
01491             f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0));
01492             f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass.codec)), ast_tv(0, 0));
01493             rtp->resp = 0;
01494             rtp->dtmf_duration = rtp->dtmf_timeout = 0;
01495             AST_LIST_INSERT_TAIL(frames, f, frame_list);
01496          }
01497 
01498          if (rtp->resp) {
01499             /* Digit continues */
01500             rtp->dtmf_duration = new_duration;
01501          } else {
01502             /* New digit began */
01503             rtp->resp = resp;
01504             f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_BEGIN, 0));
01505             rtp->dtmf_duration = samples;
01506             AST_LIST_INSERT_TAIL(frames, f, frame_list);
01507          }
01508 
01509          rtp->dtmf_timeout = timestamp + rtp->dtmf_duration + dtmftimeout;
01510       }
01511 
01512       rtp->lastevent = seqno;
01513    }
01514 
01515    rtp->dtmfsamples = samples;
01516 
01517    return;
01518 }

static struct ast_frame* red_t140_to_red ( struct rtp_red red  )  [static]

Definition at line 1157 of file res_rtp_asterisk.c.

References ast_frame::data, ast_frame::datalen, rtp_red::hdrlen, rtp_red::len, len(), rtp_red::num_gen, ast_frame::ptr, rtp_red::t140, and rtp_red::t140red.

Referenced by ast_rtp_write().

01157                                                               {
01158    unsigned char *data = red->t140red.data.ptr;
01159    int len = 0;
01160    int i;
01161 
01162    /* replace most aged generation */
01163    if (red->len[0]) {
01164       for (i = 1; i < red->num_gen+1; i++)
01165          len += red->len[i];
01166 
01167       memmove(&data[red->hdrlen], &data[red->hdrlen+red->len[0]], len);
01168    }
01169 
01170    /* Store length of each generation and primary data length*/
01171    for (i = 0; i < red->num_gen; i++)
01172       red->len[i] = red->len[i+1];
01173    red->len[i] = red->t140.datalen;
01174 
01175    /* write each generation length in red header */
01176    len = red->hdrlen;
01177    for (i = 0; i < red->num_gen; i++)
01178       len += data[i*4+3] = red->len[i];
01179 
01180    /* add primary data to buffer */
01181    memcpy(&data[len], red->t140.data.ptr, red->t140.datalen);
01182    red->t140red.datalen = len + red->t140.datalen;
01183 
01184    /* no primary data and no generations to send */
01185    if (len == red->hdrlen && !red->t140.datalen)
01186       return NULL;
01187 
01188    /* reset t.140 buffer */
01189    red->t140.datalen = 0;
01190 
01191    return &red->t140red;
01192 }

static int red_write ( const void *  data  )  [static]

Write t140 redundacy frame.

Parameters:
data primary data to be buffered

Definition at line 2423 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data(), ast_rtp_write(), ast_rtp::red, and rtp_red::t140.

Referenced by rtp_red_init().

02424 {
02425    struct ast_rtp_instance *instance = (struct ast_rtp_instance*) data;
02426    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02427 
02428    ast_rtp_write(instance, &rtp->red->t140);
02429 
02430    return 1;
02431 }

static int reload_module ( void   )  [static]

Definition at line 2790 of file res_rtp_asterisk.c.

References rtp_reload().

02791 {
02792    rtp_reload(1);
02793    return 0;
02794 }

static int rtcp_debug_test_addr ( struct ast_sockaddr addr  )  [inline, static]

Definition at line 311 of file res_rtp_asterisk.c.

References ast_sockaddr_cmp(), ast_sockaddr_isnull(), and rtcpdebugaddr.

Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), and ast_rtcp_write_sr().

00312 {
00313    if (!rtcpdebug) {
00314       return 0;
00315    }
00316 
00317    return ast_sockaddr_isnull(&rtcpdebugaddr) ? 1 : ast_sockaddr_cmp(&rtcpdebugaddr, addr) == 0;
00318 }

static char* rtcp_do_debug_ip ( struct ast_cli_args a  )  [static]

Definition at line 2608 of file res_rtp_asterisk.c.

References ast_cli_args::argv, ast_cli(), ast_sockaddr_parse(), ast_sockaddr_stringify(), ast_strdupa, CLI_FAILURE, CLI_SUCCESS, ast_cli_args::fd, rtcpdebug, and rtcpdebugaddr.

Referenced by handle_cli_rtcp_set_debug().

02609 {
02610    char *arg = ast_strdupa(a->argv[4]);
02611 
02612    if (!ast_sockaddr_parse(&rtcpdebugaddr, arg, 0)) {
02613       ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
02614       return CLI_FAILURE;
02615    }
02616    ast_cli(a->fd, "RTCP Debugging Enabled for address: %s\n",
02617       ast_sockaddr_stringify(&rtcpdebugaddr));
02618    rtcpdebug = 1;
02619    return CLI_SUCCESS;
02620 }

static int rtcp_recvfrom ( struct ast_rtp_instance instance,
void *  buf,
size_t  size,
int  flags,
struct ast_sockaddr sa 
) [static]

Definition at line 337 of file res_rtp_asterisk.c.

References __rtp_recvfrom().

Referenced by ast_rtcp_read().

00338 {
00339    return __rtp_recvfrom(instance, buf, size, flags, sa, 1);
00340 }

static int rtcp_sendto ( struct ast_rtp_instance instance,
void *  buf,
size_t  size,
int  flags,
struct ast_sockaddr sa 
) [static]

Definition at line 361 of file res_rtp_asterisk.c.

References __rtp_sendto().

Referenced by ast_rtcp_write_rr(), and ast_rtcp_write_sr().

00362 {
00363    return __rtp_sendto(instance, buf, size, flags, sa, 1);
00364 }

static int rtp_debug_test_addr ( struct ast_sockaddr addr  )  [inline, static]

Definition at line 302 of file res_rtp_asterisk.c.

References ast_sockaddr_cmp(), ast_sockaddr_isnull(), and rtpdebugaddr.

Referenced by ast_rtp_dtmf_begin(), ast_rtp_dtmf_continuation(), ast_rtp_dtmf_end_with_duration(), ast_rtp_raw_write(), ast_rtp_read(), bridge_p2p_rtp_write(), and process_dtmf_rfc2833().

00303 {
00304    if (!rtpdebug) {
00305       return 0;
00306    }
00307 
00308    return ast_sockaddr_isnull(&rtpdebugaddr) ? 1 : ast_sockaddr_cmp(&rtpdebugaddr, addr) == 0;
00309 }

static char* rtp_do_debug_ip ( struct ast_cli_args a  )  [static]

Definition at line 2594 of file res_rtp_asterisk.c.

References ast_cli_args::argv, ast_cli(), ast_sockaddr_parse(), ast_sockaddr_stringify(), ast_strdupa, CLI_FAILURE, CLI_SUCCESS, ast_cli_args::fd, rtpdebug, and rtpdebugaddr.

Referenced by handle_cli_rtp_set_debug().

02595 {
02596    char *arg = ast_strdupa(a->argv[4]);
02597 
02598    if (!ast_sockaddr_parse(&rtpdebugaddr, arg, 0)) {
02599       ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
02600       return CLI_FAILURE;
02601    }
02602    ast_cli(a->fd, "RTP Debugging Enabled for address: %s\n",
02603       ast_sockaddr_stringify(&rtpdebugaddr));
02604    rtpdebug = 1;
02605    return CLI_SUCCESS;
02606 }

static int rtp_get_rate ( format_t  subclass  )  [static]

Definition at line 371 of file res_rtp_asterisk.c.

References AST_FORMAT_G722, and ast_format_rate().

Referenced by ast_rtp_dtmf_end_with_duration(), ast_rtp_raw_write(), ast_rtp_read(), calc_rxstamp(), process_dtmf_cisco(), and process_dtmf_rfc2833().

00372 {
00373    return (subclass == AST_FORMAT_G722) ? 8000 : ast_format_rate(subclass);
00374 }

static int rtp_recvfrom ( struct ast_rtp_instance instance,
void *  buf,
size_t  size,
int  flags,
struct ast_sockaddr sa 
) [static]

Definition at line 342 of file res_rtp_asterisk.c.

References __rtp_recvfrom().

Referenced by ast_rtp_read().

00343 {
00344    return __rtp_recvfrom(instance, buf, size, flags, sa, 0);
00345 }

static int rtp_red_buffer ( struct ast_rtp_instance instance,
struct ast_frame frame 
) [static]

Definition at line 2468 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data(), rtp_red::buf_data, ast_frame::data, ast_frame::datalen, ast_frame::ptr, ast_rtp::red, rtp_red::t140, and ast_frame::ts.

02469 {
02470    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02471 
02472    if (frame->datalen > -1) {
02473       struct rtp_red *red = rtp->red;
02474       memcpy(&red->buf_data[red->t140.datalen], frame->data.ptr, frame->datalen);
02475       red->t140.datalen += frame->datalen;
02476       red->t140.ts = frame->ts;
02477    }
02478 
02479    return 0;
02480 }

static int rtp_red_init ( struct ast_rtp_instance instance,
int  buffer_time,
int *  payloads,
int  generations 
) [static]

Definition at line 2433 of file res_rtp_asterisk.c.

References ast_calloc, AST_FORMAT_T140RED, AST_FRAME_TEXT, ast_rtp_instance_get_data(), ast_sched_add(), rtp_red::buf_data, ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, ast_frame::frametype, rtp_red::hdrlen, rtp_red::num_gen, rtp_red::prev_ts, rtp_red::pt, ast_frame::ptr, ast_rtp::red, red_write(), ast_rtp::sched, rtp_red::schedid, ast_frame::subclass, rtp_red::t140, rtp_red::t140red, rtp_red::t140red_data, rtp_red::ti, and ast_frame::ts.

02434 {
02435    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02436    int x;
02437 
02438    if (!(rtp->red = ast_calloc(1, sizeof(*rtp->red)))) {
02439       return -1;
02440    }
02441 
02442    rtp->red->t140.frametype = AST_FRAME_TEXT;
02443    rtp->red->t140.subclass.codec = AST_FORMAT_T140RED;
02444    rtp->red->t140.data.ptr = &rtp->red->buf_data;
02445 
02446    rtp->red->t140.ts = 0;
02447    rtp->red->t140red = rtp->red->t140;
02448    rtp->red->t140red.data.ptr = &rtp->red->t140red_data;
02449    rtp->red->t140red.datalen = 0;
02450    rtp->red->ti = buffer_time;
02451    rtp->red->num_gen = generations;
02452    rtp->red->hdrlen = generations * 4 + 1;
02453    rtp->red->prev_ts = 0;
02454 
02455    for (x = 0; x < generations; x++) {
02456       rtp->red->pt[x] = payloads[x];
02457       rtp->red->pt[x] |= 1 << 7; /* mark redundant generations pt */
02458       rtp->red->t140red_data[x*4] = rtp->red->pt[x];
02459    }
02460    rtp->red->t140red_data[x*4] = rtp->red->pt[x] = payloads[x]; /* primary pt */
02461    rtp->red->schedid = ast_sched_add(rtp->sched, generations, red_write, instance);
02462 
02463    rtp->red->t140.datalen = 0;
02464 
02465    return 0;
02466 }

static int rtp_reload ( int  reload  )  [static]

Definition at line 2721 of file res_rtp_asterisk.c.

References ast_config_destroy(), ast_config_load2(), ast_false(), ast_log(), ast_true(), ast_variable_retrieve(), ast_verb, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_DTMF_TIMEOUT, DEFAULT_RTP_END, DEFAULT_RTP_START, dtmftimeout, LOG_WARNING, MAXIMUM_RTP_PORT, MINIMUM_RTP_PORT, RTCP_MAX_INTERVALMS, RTCP_MIN_INTERVALMS, rtcpinterval, rtpend, rtpstart, STRICT_RTP_OPEN, and strictrtp.

Referenced by load_module(), and reload_module().

02722 {
02723    struct ast_config *cfg;
02724    const char *s;
02725    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
02726 
02727    cfg = ast_config_load2("rtp.conf", "rtp", config_flags);
02728    if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
02729       return 0;
02730    }
02731 
02732    rtpstart = DEFAULT_RTP_START;
02733    rtpend = DEFAULT_RTP_END;
02734    dtmftimeout = DEFAULT_DTMF_TIMEOUT;
02735    strictrtp = STRICT_RTP_OPEN;
02736    if (cfg) {
02737       if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
02738          rtpstart = atoi(s);
02739          if (rtpstart < MINIMUM_RTP_PORT)
02740             rtpstart = MINIMUM_RTP_PORT;
02741          if (rtpstart > MAXIMUM_RTP_PORT)
02742             rtpstart = MAXIMUM_RTP_PORT;
02743       }
02744       if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
02745          rtpend = atoi(s);
02746          if (rtpend < MINIMUM_RTP_PORT)
02747             rtpend = MINIMUM_RTP_PORT;
02748          if (rtpend > MAXIMUM_RTP_PORT)
02749             rtpend = MAXIMUM_RTP_PORT;
02750       }
02751       if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
02752          rtcpinterval = atoi(s);
02753          if (rtcpinterval == 0)
02754             rtcpinterval = 0; /* Just so we're clear... it's zero */
02755          if (rtcpinterval < RTCP_MIN_INTERVALMS)
02756             rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
02757          if (rtcpinterval > RTCP_MAX_INTERVALMS)
02758             rtcpinterval = RTCP_MAX_INTERVALMS;
02759       }
02760       if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
02761 #ifdef SO_NO_CHECK
02762          nochecksums = ast_false(s) ? 1 : 0;
02763 #else
02764          if (ast_false(s))
02765             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
02766 #endif
02767       }
02768       if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
02769          dtmftimeout = atoi(s);
02770          if ((dtmftimeout < 0) || (dtmftimeout > 64000)) {
02771             ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
02772                dtmftimeout, DEFAULT_DTMF_TIMEOUT);
02773             dtmftimeout = DEFAULT_DTMF_TIMEOUT;
02774          };
02775       }
02776       if ((s = ast_variable_retrieve(cfg, "general", "strictrtp"))) {
02777          strictrtp = ast_true(s);
02778       }
02779       ast_config_destroy(cfg);
02780    }
02781    if (rtpstart >= rtpend) {
02782       ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
02783       rtpstart = DEFAULT_RTP_START;
02784       rtpend = DEFAULT_RTP_END;
02785    }
02786    ast_verb(2, "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
02787    return 0;
02788 }

static int rtp_sendto ( struct ast_rtp_instance instance,
void *  buf,
size_t  size,
int  flags,
struct ast_sockaddr sa 
) [static]

Definition at line 366 of file res_rtp_asterisk.c.

References __rtp_sendto().

Referenced by ast_rtp_dtmf_begin(), ast_rtp_dtmf_continuation(), ast_rtp_dtmf_end_with_duration(), ast_rtp_raw_write(), and bridge_p2p_rtp_write().

00367 {
00368    return __rtp_sendto(instance, buf, size, flags, sa, 0);
00369 }

static double stddev_compute ( double  stddev,
double  sample,
double  normdev,
double  normdev_curent,
unsigned int  sample_count 
) [static]

Definition at line 394 of file res_rtp_asterisk.c.

References SQUARE.

Referenced by ast_rtcp_read(), ast_rtcp_write_rr(), and calc_rxstamp().

00395 {
00396 /*
00397       for the formula check http://www.cs.umd.edu/~austinjp/constSD.pdf
00398       return sqrt( (sample_count*pow(stddev,2) + sample_count*pow((sample-normdev)/(sample_count+1),2) + pow(sample-normdev_curent,2)) / (sample_count+1));
00399       we can compute the sigma^2 and that way we would have to do the sqrt only 1 time at the end and would save another pow 2 compute
00400       optimized formula
00401 */
00402 #define SQUARE(x) ((x) * (x))
00403 
00404    stddev = sample_count * stddev;
00405    sample_count++;
00406 
00407    return stddev +
00408       ( sample_count * SQUARE( (sample - normdev) / sample_count ) ) +
00409       ( SQUARE(sample - normdev_curent) / sample_count );
00410 
00411 #undef SQUARE
00412 }

static void timeval2ntp ( struct timeval  tv,
unsigned int *  msw,
unsigned int *  lsw 
) [static]

Definition at line 775 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

00776 {
00777    unsigned int sec, usec, frac;
00778    sec = tv.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */
00779    usec = tv.tv_usec;
00780    frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6);
00781    *msw = sec;
00782    *lsw = frac;
00783 }

static int unload_module ( void   )  [static]

Definition at line 2812 of file res_rtp_asterisk.c.

References ARRAY_LEN, ast_cli_unregister_multiple(), ast_rtp_engine_unregister(), asterisk_rtp_engine, and cli_rtp.

02813 {
02814    ast_rtp_engine_unregister(&asterisk_rtp_engine);
02815    ast_cli_unregister_multiple(cli_rtp, ARRAY_LEN(cli_rtp));
02816 
02817    return 0;
02818 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Asterisk RTP Stack" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } [static]

Definition at line 2825 of file res_rtp_asterisk.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 2825 of file res_rtp_asterisk.c.

struct ast_rtp_engine asterisk_rtp_engine [static]

Definition at line 277 of file res_rtp_asterisk.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_rtp[] [static]

Initial value:

 {
   { .handler =  handle_cli_rtp_set_debug , .summary =  "Enable/Disable RTP debugging" ,__VA_ARGS__ },
   { .handler =  handle_cli_rtcp_set_debug , .summary =  "Enable/Disable RTCP debugging" ,__VA_ARGS__ },
   { .handler =  handle_cli_rtcp_set_stats , .summary =  "Enable/Disable RTCP stats" ,__VA_ARGS__ },
}

Definition at line 2715 of file res_rtp_asterisk.c.

Referenced by load_module(), and unload_module().

int dtmftimeout = DEFAULT_DTMF_TIMEOUT [static]

Definition at line 80 of file res_rtp_asterisk.c.

Referenced by process_dtmf_rfc2833(), and rtp_reload().

struct ast_srtp_res* res_srtp

Definition at line 43 of file rtp_engine.c.

Referenced by __rtp_recvfrom(), __rtp_sendto(), ast_rtp_change_source(), ast_rtp_engine_register_srtp(), ast_rtp_engine_srtp_is_registered(), ast_rtp_engine_unregister_srtp(), ast_rtp_instance_add_srtp_policy(), and instance_destructor().

int rtcpdebug [static]

Are we debugging RTCP?

Definition at line 85 of file res_rtp_asterisk.c.

Referenced by handle_cli_rtcp_set_debug(), and rtcp_do_debug_ip().

struct ast_sockaddr rtcpdebugaddr [static]

Debug RTCP packets to/from this host

Definition at line 89 of file res_rtp_asterisk.c.

Referenced by handle_cli_rtcp_set_debug(), rtcp_debug_test_addr(), and rtcp_do_debug_ip().

int rtcpinterval = RTCP_DEFAULT_INTERVALMS [static]

Time between rtcp reports in millisecs

Definition at line 87 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

int rtcpstats [static]

Are we debugging RTCP?

Definition at line 86 of file res_rtp_asterisk.c.

Referenced by handle_cli_rtcp_set_stats().

int rtpdebug [static]

Are we debugging?

Definition at line 84 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_read(), ast_rtp_raw_write(), ast_rtp_read(), bridge_p2p_rtp_write(), handle_cli_rtp_set_debug(), process_cn_rfc3389(), process_dtmf_cisco(), process_dtmf_rfc2833(), and rtp_do_debug_ip().

struct ast_sockaddr rtpdebugaddr [static]

Debug packets to/from this host

Definition at line 88 of file res_rtp_asterisk.c.

Referenced by handle_cli_rtp_set_debug(), rtp_debug_test_addr(), and rtp_do_debug_ip().

int rtpend = DEFAULT_RTP_END [static]

Last port for RTP sessions (set in rtp.conf)

Definition at line 83 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

int rtpstart = DEFAULT_RTP_START [static]

First port for RTP sessions (set in rtp.conf)

Definition at line 82 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

int strictrtp [static]

Definition at line 93 of file res_rtp_asterisk.c.

Referenced by ast_rtp_remote_address_set(), and rtp_reload().


Generated on Wed Apr 6 11:30:09 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7