Wed Oct 28 13:33:32 2009

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 <math.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/netsock.h"
#include "asterisk/cli.h"
#include "asterisk/manager.h"
#include "asterisk/unaligned.h"
#include "asterisk/module.h"
#include "asterisk/rtp_engine.h"

Include dependency graph for res_rtp_asterisk.c:

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  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 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 (const void *data)
 Send RTCP recipient's report.
static int ast_rtcp_write_sr (const void *data)
 Send RTCP sender's report.
static void ast_rtp_alt_remote_address_set (struct ast_rtp_instance *instance, struct sockaddr_in *sin)
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_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 sockaddr_in *sin, void *data)
static void ast_rtp_new_source (struct ast_rtp_instance *instance)
static void ast_rtp_prop_set (struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
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 sockaddr_in *sin)
static void ast_rtp_stop (struct ast_rtp_instance *instance)
static void ast_rtp_stun_request (struct ast_rtp_instance *instance, struct sockaddr_in *suggestion, const char *username)
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 int create_new_socket (const char *type)
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 sockaddr_in *sin, 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 sockaddr_in *sin, int payloadtype, int mark)
static struct ast_frameprocess_dtmf_rfc2833 (struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, struct sockaddr_in *sin, int payloadtype, int mark)
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 sockaddr_in *addr)
static char * rtcp_do_debug_ip (struct ast_cli_args *a)
static int rtp_debug_test_addr (struct sockaddr_in *addr)
static char * rtp_do_debug_ip (struct ast_cli_args *a)
static int rtp_get_rate (int subclass)
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 void sanitize_tv (struct timeval *tv)
static struct ast_framesend_dtmf (struct ast_rtp_instance *instance, enum ast_frame_type type, int compensate)
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_DEFAULT , .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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload_module, }
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
static int rtcpdebug
static struct sockaddr_in rtcpdebugaddr
static int rtcpinterval = RTCP_DEFAULT_INTERVALMS
static int rtcpstats
static int rtpdebug
static struct sockaddr_in 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 100 of file res_rtp_asterisk.c.

Referenced by process_cn_rfc3389().

#define FLAG_DTMF_COMPENSATE   (1 << 4)

Definition at line 105 of file res_rtp_asterisk.c.

#define FLAG_NAT_ACTIVE   (3 << 1)

Definition at line 101 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 102 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 103 of file res_rtp_asterisk.c.

Referenced by ast_rtp_raw_write(), and bridge_p2p_rtp_write().

#define FLAG_NEED_MARKER_BIT   (1 << 3)

#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

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 94 of file res_rtp_asterisk.c.

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


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 2667 of file res_rtp_asterisk.c.

static void __unreg_module ( void   )  [static]

Definition at line 2667 of file res_rtp_asterisk.c.

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

Todo:
XXX Do a more reasonable calculation on this one Look in RFC 3550 Section A.7 for an example

Definition at line 330 of file res_rtp_asterisk.c.

Referenced by ast_rtp_raw_write(), and ast_rtp_read().

00331 {
00332    unsigned int interval;
00333    /*! \todo XXX Do a more reasonable calculation on this one
00334     * Look in RFC 3550 Section A.7 for an example*/
00335    interval = rtcpinterval;
00336    return interval;
00337 }

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

Definition at line 1538 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_inet_ntoa(), ast_log(), ast_null_frame, ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), AST_RTP_PROPERTY_NAT, ast_verbose, ast_frame::datalen, errno, EVENT_FLAG_REPORTING, ast_rtp::f, f, ast_frame::frametype, len(), 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, ast_rtcp::rtt, ast_rtcp::rtt_count, ast_rtcp::rxlsr, ast_rtcp::s, 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().

01539 {
01540    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
01541    struct sockaddr_in sin;
01542    socklen_t len = sizeof(sin);
01543    unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET];
01544    unsigned int *rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET);
01545    int res, packetwords, position = 0;
01546    struct ast_frame *f = &ast_null_frame;
01547 
01548    /* Read in RTCP data from the socket */
01549    if ((res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET, 0, (struct sockaddr *)&sin, &len)) < 0) {
01550       ast_assert(errno != EBADF);
01551       if (errno != EAGAIN) {
01552          ast_log(LOG_WARNING, "RTCP Read error: %s.  Hanging up.\n", strerror(errno));
01553          return NULL;
01554       }
01555       return &ast_null_frame;
01556    }
01557 
01558    packetwords = res / 4;
01559 
01560    if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT)) {
01561       /* Send to whoever sent to us */
01562       if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
01563           (rtp->rtcp->them.sin_port != sin.sin_port)) {
01564          memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
01565          if (option_debug || rtpdebug)
01566             ast_debug(0, "RTCP NAT: Got RTCP from other end. Now sending to address %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
01567       }
01568    }
01569 
01570    ast_debug(1, "Got RTCP report of %d bytes\n", res);
01571 
01572    while (position < packetwords) {
01573       int i, pt, rc;
01574       unsigned int length, dlsr, lsr, msw, lsw, comp;
01575       struct timeval now;
01576       double rttsec, reported_jitter, reported_normdev_jitter_current, normdevrtt_current, reported_lost, reported_normdev_lost_current;
01577       uint64_t rtt = 0;
01578 
01579       i = position;
01580       length = ntohl(rtcpheader[i]);
01581       pt = (length & 0xff0000) >> 16;
01582       rc = (length & 0x1f000000) >> 24;
01583       length &= 0xffff;
01584 
01585       if ((i + length) > packetwords) {
01586          if (option_debug || rtpdebug)
01587             ast_log(LOG_DEBUG, "RTCP Read too short\n");
01588          return &ast_null_frame;
01589       }
01590 
01591       if (rtcp_debug_test_addr(&sin)) {
01592          ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
01593          ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown");
01594          ast_verbose("Reception reports: %d\n", rc);
01595          ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]);
01596       }
01597 
01598       i += 2; /* Advance past header and ssrc */
01599 
01600       switch (pt) {
01601       case RTCP_PT_SR:
01602          gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */
01603          rtp->rtcp->spc = ntohl(rtcpheader[i+3]);
01604          rtp->rtcp->soc = ntohl(rtcpheader[i + 4]);
01605          rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/
01606 
01607          if (rtcp_debug_test_addr(&sin)) {
01608             ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096);
01609             ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2]));
01610             ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4]));
01611          }
01612          i += 5;
01613          if (rc < 1)
01614             break;
01615          /* Intentional fall through */
01616       case RTCP_PT_RR:
01617          /* Don't handle multiple reception reports (rc > 1) yet */
01618          /* Calculate RTT per RFC */
01619          gettimeofday(&now, NULL);
01620          timeval2ntp(now, &msw, &lsw);
01621          if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */
01622             comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16);
01623             lsr = ntohl(rtcpheader[i + 4]);
01624             dlsr = ntohl(rtcpheader[i + 5]);
01625             rtt = comp - lsr - dlsr;
01626 
01627             /* Convert end to end delay to usec (keeping the calculation in 64bit space)
01628                sess->ee_delay = (eedelay * 1000) / 65536; */
01629             if (rtt < 4294) {
01630                rtt = (rtt * 1000000) >> 16;
01631             } else {
01632                rtt = (rtt * 1000) >> 16;
01633                rtt *= 1000;
01634             }
01635             rtt = rtt / 1000.;
01636             rttsec = rtt / 1000.;
01637             rtp->rtcp->rtt = rttsec;
01638 
01639             if (comp - dlsr >= lsr) {
01640                rtp->rtcp->accumulated_transit += rttsec;
01641 
01642                if (rtp->rtcp->rtt_count == 0)
01643                   rtp->rtcp->minrtt = rttsec;
01644 
01645                if (rtp->rtcp->maxrtt<rttsec)
01646                   rtp->rtcp->maxrtt = rttsec;
01647                if (rtp->rtcp->minrtt>rttsec)
01648                   rtp->rtcp->minrtt = rttsec;
01649 
01650                normdevrtt_current = normdev_compute(rtp->rtcp->normdevrtt, rttsec, rtp->rtcp->rtt_count);
01651 
01652                rtp->rtcp->stdevrtt = stddev_compute(rtp->rtcp->stdevrtt, rttsec, rtp->rtcp->normdevrtt, normdevrtt_current, rtp->rtcp->rtt_count);
01653 
01654                rtp->rtcp->normdevrtt = normdevrtt_current;
01655 
01656                rtp->rtcp->rtt_count++;
01657             } else if (rtcp_debug_test_addr(&sin)) {
01658                ast_verbose("Internal RTCP NTP clock skew detected: "
01659                         "lsr=%u, now=%u, dlsr=%u (%d:%03dms), "
01660                       "diff=%d\n",
01661                       lsr, comp, dlsr, dlsr / 65536,
01662                       (dlsr % 65536) * 1000 / 65536,
01663                       dlsr - (comp - lsr));
01664             }
01665          }
01666 
01667          rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]);
01668          reported_jitter = (double) rtp->rtcp->reported_jitter;
01669 
01670          if (rtp->rtcp->reported_jitter_count == 0)
01671             rtp->rtcp->reported_minjitter = reported_jitter;
01672 
01673          if (reported_jitter < rtp->rtcp->reported_minjitter)
01674             rtp->rtcp->reported_minjitter = reported_jitter;
01675 
01676          if (reported_jitter > rtp->rtcp->reported_maxjitter)
01677             rtp->rtcp->reported_maxjitter = reported_jitter;
01678 
01679          reported_normdev_jitter_current = normdev_compute(rtp->rtcp->reported_normdev_jitter, reported_jitter, rtp->rtcp->reported_jitter_count);
01680 
01681          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);
01682 
01683          rtp->rtcp->reported_normdev_jitter = reported_normdev_jitter_current;
01684 
01685          rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff;
01686 
01687          reported_lost = (double) rtp->rtcp->reported_lost;
01688 
01689          /* using same counter as for jitter */
01690          if (rtp->rtcp->reported_jitter_count == 0)
01691             rtp->rtcp->reported_minlost = reported_lost;
01692 
01693          if (reported_lost < rtp->rtcp->reported_minlost)
01694             rtp->rtcp->reported_minlost = reported_lost;
01695 
01696          if (reported_lost > rtp->rtcp->reported_maxlost)
01697             rtp->rtcp->reported_maxlost = reported_lost;
01698          reported_normdev_lost_current = normdev_compute(rtp->rtcp->reported_normdev_lost, reported_lost, rtp->rtcp->reported_jitter_count);
01699 
01700          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);
01701 
01702          rtp->rtcp->reported_normdev_lost = reported_normdev_lost_current;
01703 
01704          rtp->rtcp->reported_jitter_count++;
01705 
01706          if (rtcp_debug_test_addr(&sin)) {
01707             ast_verbose("  Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24));
01708             ast_verbose("  Packets lost so far: %d\n", rtp->rtcp->reported_lost);
01709             ast_verbose("  Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff));
01710             ast_verbose("  Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16);
01711             ast_verbose("  Interarrival jitter: %u\n", rtp->rtcp->reported_jitter);
01712             ast_verbose("  Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096);
01713             ast_verbose("  DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0);
01714             if (rtt)
01715                ast_verbose("  RTT: %lu(sec)\n", (unsigned long) rtt);
01716          }
01717          if (rtt) {
01718             manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From %s:%d\r\n"
01719                             "PT: %d(%s)\r\n"
01720                             "ReceptionReports: %d\r\n"
01721                             "SenderSSRC: %u\r\n"
01722                             "FractionLost: %ld\r\n"
01723                             "PacketsLost: %d\r\n"
01724                             "HighestSequence: %ld\r\n"
01725                             "SequenceNumberCycles: %ld\r\n"
01726                             "IAJitter: %u\r\n"
01727                             "LastSR: %lu.%010lu\r\n"
01728                             "DLSR: %4.4f(sec)\r\n"
01729                      "RTT: %llu(sec)\r\n",
01730                      ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port),
01731                      pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
01732                      rc,
01733                      rtcpheader[i + 1],
01734                      (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24),
01735                      rtp->rtcp->reported_lost,
01736                      (long) (ntohl(rtcpheader[i + 2]) & 0xffff),
01737                      (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16,
01738                      rtp->rtcp->reported_jitter,
01739                      (unsigned long) ntohl(rtcpheader[i + 4]) >> 16, ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096,
01740                      ntohl(rtcpheader[i + 5])/65536.0,
01741                      (unsigned long long)rtt);
01742          } else {
01743             manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From %s:%d\r\n"
01744                             "PT: %d(%s)\r\n"
01745                             "ReceptionReports: %d\r\n"
01746                             "SenderSSRC: %u\r\n"
01747                             "FractionLost: %ld\r\n"
01748                             "PacketsLost: %d\r\n"
01749                             "HighestSequence: %ld\r\n"
01750                             "SequenceNumberCycles: %ld\r\n"
01751                             "IAJitter: %u\r\n"
01752                             "LastSR: %lu.%010lu\r\n"
01753                      "DLSR: %4.4f(sec)\r\n",
01754                      ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port),
01755                      pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
01756                      rc,
01757                      rtcpheader[i + 1],
01758                      (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24),
01759                      rtp->rtcp->reported_lost,
01760                      (long) (ntohl(rtcpheader[i + 2]) & 0xffff),
01761                      (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16,
01762                      rtp->rtcp->reported_jitter,
01763                      (unsigned long) ntohl(rtcpheader[i + 4]) >> 16,
01764                      ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096,
01765                      ntohl(rtcpheader[i + 5])/65536.0);
01766          }
01767          break;
01768       case RTCP_PT_FUR:
01769          if (rtcp_debug_test_addr(&sin))
01770             ast_verbose("Received an RTCP Fast Update Request\n");
01771          rtp->f.frametype = AST_FRAME_CONTROL;
01772          rtp->f.subclass = AST_CONTROL_VIDUPDATE;
01773          rtp->f.datalen = 0;
01774          rtp->f.samples = 0;
01775          rtp->f.mallocd = 0;
01776          rtp->f.src = "RTP";
01777          f = &rtp->f;
01778          break;
01779       case RTCP_PT_SDES:
01780          if (rtcp_debug_test_addr(&sin))
01781             ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
01782          break;
01783       case RTCP_PT_BYE:
01784          if (rtcp_debug_test_addr(&sin))
01785             ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
01786          break;
01787       default:
01788          ast_debug(1, "Unknown RTCP packet (pt=%d) received from %s:%d\n", pt, ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
01789          break;
01790       }
01791       position += (length + 1);
01792    }
01793 
01794    rtp->rtcp->rtcp_info = 1;
01795 
01796    return f;
01797 }

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 931 of file res_rtp_asterisk.c.

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

Referenced by ast_rtp_raw_write(), and ast_rtp_read().

00932 {
00933    struct ast_rtp *rtp = (struct ast_rtp *)data;
00934    int res;
00935 
00936    if (!rtp || !rtp->rtcp)
00937       return 0;
00938 
00939    if (rtp->txcount > rtp->rtcp->lastsrtxcount)
00940       res = ast_rtcp_write_sr(data);
00941    else
00942       res = ast_rtcp_write_rr(data);
00943 
00944    return res;
00945 }

static int ast_rtcp_write_rr ( const void *  data  )  [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 700 of file res_rtp_asterisk.c.

References ast_inet_ntoa(), ast_log(), AST_SCHED_DEL, 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, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtcp::rxlost, ast_rtcp::rxlost_count, ast_rtcp::rxlsr, ast_rtcp::s, 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().

00701 {
00702    struct ast_rtp *rtp = (struct ast_rtp *)data;
00703    int res;
00704    int len = 32;
00705    unsigned int lost;
00706    unsigned int extended;
00707    unsigned int expected;
00708    unsigned int expected_interval;
00709    unsigned int received_interval;
00710    int lost_interval;
00711    struct timeval now;
00712    unsigned int *rtcpheader;
00713    char bdata[1024];
00714    struct timeval dlsr;
00715    int fraction;
00716 
00717    double rxlost_current;
00718 
00719    if (!rtp || !rtp->rtcp || (&rtp->rtcp->them.sin_addr == 0))
00720       return 0;
00721 
00722    if (!rtp->rtcp->them.sin_addr.s_addr) {
00723       ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted\n");
00724       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
00725       return 0;
00726    }
00727 
00728    extended = rtp->cycles + rtp->lastrxseqno;
00729    expected = extended - rtp->seedrxseqno + 1;
00730    lost = expected - rtp->rxcount;
00731    expected_interval = expected - rtp->rtcp->expected_prior;
00732    rtp->rtcp->expected_prior = expected;
00733    received_interval = rtp->rxcount - rtp->rtcp->received_prior;
00734    rtp->rtcp->received_prior = rtp->rxcount;
00735    lost_interval = expected_interval - received_interval;
00736 
00737    if (lost_interval <= 0)
00738       rtp->rtcp->rxlost = 0;
00739    else rtp->rtcp->rxlost = rtp->rtcp->rxlost;
00740    if (rtp->rtcp->rxlost_count == 0)
00741       rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
00742    if (lost_interval < rtp->rtcp->minrxlost)
00743       rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
00744    if (lost_interval > rtp->rtcp->maxrxlost)
00745       rtp->rtcp->maxrxlost = rtp->rtcp->rxlost;
00746 
00747    rxlost_current = normdev_compute(rtp->rtcp->normdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->rxlost_count);
00748    rtp->rtcp->stdev_rxlost = stddev_compute(rtp->rtcp->stdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->normdev_rxlost, rxlost_current, rtp->rtcp->rxlost_count);
00749    rtp->rtcp->normdev_rxlost = rxlost_current;
00750    rtp->rtcp->rxlost_count++;
00751 
00752    if (expected_interval == 0 || lost_interval <= 0)
00753       fraction = 0;
00754    else
00755       fraction = (lost_interval << 8) / expected_interval;
00756    gettimeofday(&now, NULL);
00757    timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
00758    rtcpheader = (unsigned int *)bdata;
00759    rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1));
00760    rtcpheader[1] = htonl(rtp->ssrc);
00761    rtcpheader[2] = htonl(rtp->themssrc);
00762    rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
00763    rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
00764    rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * 65536.));
00765    rtcpheader[6] = htonl(rtp->rtcp->themrxlsr);
00766    rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
00767 
00768    /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos
00769      it can change mid call, and SDES can't) */
00770    rtcpheader[len/4]     = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
00771    rtcpheader[(len/4)+1] = htonl(rtp->ssrc);               /* Our SSRC */
00772    rtcpheader[(len/4)+2] = htonl(0x01 << 24);              /* Empty for the moment */
00773    len += 12;
00774 
00775    res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
00776 
00777    if (res < 0) {
00778       ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno));
00779       /* Remove the scheduler */
00780       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
00781       return 0;
00782    }
00783 
00784    rtp->rtcp->rr_count++;
00785    if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
00786       ast_verbose("\n* Sending RTCP RR to %s:%d\n"
00787          "  Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n"
00788          "  IA jitter: %.4f\n"
00789          "  Their last SR: %u\n"
00790              "  DLSR: %4.4f (sec)\n\n",
00791              ast_inet_ntoa(rtp->rtcp->them.sin_addr),
00792              ntohs(rtp->rtcp->them.sin_port),
00793              rtp->ssrc, rtp->themssrc, fraction, lost,
00794              rtp->rxjitter,
00795              rtp->rtcp->themrxlsr,
00796              (double)(ntohl(rtcpheader[7])/65536.0));
00797    }
00798 
00799    return res;
00800 }

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

Send RTCP sender's report.

Definition at line 803 of file res_rtp_asterisk.c.

References ast_inet_ntoa(), ast_log(), AST_SCHED_DEL, 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, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtcp::rxlsr, ast_rtcp::s, 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().

00804 {
00805    struct ast_rtp *rtp = (struct ast_rtp *)data;
00806    int res;
00807    int len = 0;
00808    struct timeval now;
00809    unsigned int now_lsw;
00810    unsigned int now_msw;
00811    unsigned int *rtcpheader;
00812    unsigned int lost;
00813    unsigned int extended;
00814    unsigned int expected;
00815    unsigned int expected_interval;
00816    unsigned int received_interval;
00817    int lost_interval;
00818    int fraction;
00819    struct timeval dlsr;
00820    char bdata[512];
00821 
00822    /* Commented condition is always not NULL if rtp->rtcp is not NULL */
00823    if (!rtp || !rtp->rtcp/* || (&rtp->rtcp->them.sin_addr == 0)*/)
00824       return 0;
00825 
00826    if (!rtp->rtcp->them.sin_addr.s_addr) {  /* This'll stop rtcp for this rtp session */
00827       ast_verbose("RTCP SR transmission error, rtcp halted\n");
00828       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
00829       return 0;
00830    }
00831 
00832    gettimeofday(&now, NULL);
00833    timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/
00834    rtcpheader = (unsigned int *)bdata;
00835    rtcpheader[1] = htonl(rtp->ssrc);               /* Our SSRC */
00836    rtcpheader[2] = htonl(now_msw);                 /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/
00837    rtcpheader[3] = htonl(now_lsw);                 /* now, LSW */
00838    rtcpheader[4] = htonl(rtp->lastts);             /* FIXME shouldn't be that, it should be now */
00839    rtcpheader[5] = htonl(rtp->txcount);            /* No. packets sent */
00840    rtcpheader[6] = htonl(rtp->txoctetcount);       /* No. bytes sent */
00841    len += 28;
00842 
00843    extended = rtp->cycles + rtp->lastrxseqno;
00844    expected = extended - rtp->seedrxseqno + 1;
00845    if (rtp->rxcount > expected)
00846       expected += rtp->rxcount - expected;
00847    lost = expected - rtp->rxcount;
00848    expected_interval = expected - rtp->rtcp->expected_prior;
00849    rtp->rtcp->expected_prior = expected;
00850    received_interval = rtp->rxcount - rtp->rtcp->received_prior;
00851    rtp->rtcp->received_prior = rtp->rxcount;
00852    lost_interval = expected_interval - received_interval;
00853    if (expected_interval == 0 || lost_interval <= 0)
00854       fraction = 0;
00855    else
00856       fraction = (lost_interval << 8) / expected_interval;
00857    timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
00858    rtcpheader[7] = htonl(rtp->themssrc);
00859    rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
00860    rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
00861    rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * 65536.));
00862    rtcpheader[11] = htonl(rtp->rtcp->themrxlsr);
00863    rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
00864    len += 24;
00865 
00866    rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1));
00867 
00868    /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */
00869    /* it can change mid call, and SDES can't) */
00870    rtcpheader[len/4]     = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
00871    rtcpheader[(len/4)+1] = htonl(rtp->ssrc);               /* Our SSRC */
00872    rtcpheader[(len/4)+2] = htonl(0x01 << 24);                    /* Empty for the moment */
00873    len += 12;
00874 
00875    res = sendto(rtp->rtcp->s, (unsigned int *)rtcpheader, len, 0, (struct sockaddr *)&rtp->rtcp->them, sizeof(rtp->rtcp->them));
00876    if (res < 0) {
00877       ast_log(LOG_ERROR, "RTCP SR transmission error to %s:%d, rtcp halted %s\n",ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port), strerror(errno));
00878       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
00879       return 0;
00880    }
00881 
00882    /* FIXME Don't need to get a new one */
00883    gettimeofday(&rtp->rtcp->txlsr, NULL);
00884    rtp->rtcp->sr_count++;
00885 
00886    rtp->rtcp->lastsrtxcount = rtp->txcount;
00887 
00888    if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
00889       ast_verbose("* Sent RTCP SR to %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
00890       ast_verbose("  Our SSRC: %u\n", rtp->ssrc);
00891       ast_verbose("  Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096);
00892       ast_verbose("  Sent(RTP): %u\n", rtp->lastts);
00893       ast_verbose("  Sent packets: %u\n", rtp->txcount);
00894       ast_verbose("  Sent octets: %u\n", rtp->txoctetcount);
00895       ast_verbose("  Report block:\n");
00896       ast_verbose("  Fraction lost: %u\n", fraction);
00897       ast_verbose("  Cumulative loss: %u\n", lost);
00898       ast_verbose("  IA jitter: %.4f\n", rtp->rxjitter);
00899       ast_verbose("  Their last SR: %u\n", rtp->rtcp->themrxlsr);
00900       ast_verbose("  DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0));
00901    }
00902    manager_event(EVENT_FLAG_REPORTING, "RTCPSent", "To %s:%d\r\n"
00903                    "OurSSRC: %u\r\n"
00904                    "SentNTP: %u.%010u\r\n"
00905                    "SentRTP: %u\r\n"
00906                    "SentPackets: %u\r\n"
00907                    "SentOctets: %u\r\n"
00908                    "ReportBlock:\r\n"
00909                    "FractionLost: %u\r\n"
00910                    "CumulativeLoss: %u\r\n"
00911                    "IAJitter: %.4f\r\n"
00912                    "TheirLastSR: %u\r\n"
00913             "DLSR: %4.4f (sec)\r\n",
00914             ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port),
00915             rtp->ssrc,
00916             (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096,
00917             rtp->lastts,
00918             rtp->txcount,
00919             rtp->txoctetcount,
00920             fraction,
00921             lost,
00922             rtp->rxjitter,
00923             rtp->rtcp->themrxlsr,
00924             (double)(ntohl(rtcpheader[12])/65536.0));
00925    return res;
00926 }

static void ast_rtp_alt_remote_address_set ( struct ast_rtp_instance instance,
struct sockaddr_in *  sin 
) [static]

Definition at line 2230 of file res_rtp_asterisk.c.

References ast_rtp::alt_rtp_address, and ast_rtp_instance_get_data().

02231 {
02232    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02233 
02234    /* No need to futz with rtp->rtcp here because ast_rtcp_read is already able to adjust if receiving
02235     * RTCP from an "unexpected" source
02236     */
02237    rtp->alt_rtp_address = *sin;
02238 
02239    return;
02240 }

static int ast_rtp_destroy ( struct ast_rtp_instance instance  )  [static]

Definition at line 447 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.

00448 {
00449    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00450 
00451    /* Destroy the smoother that was smoothing out audio if present */
00452    if (rtp->smoother) {
00453       ast_smoother_free(rtp->smoother);
00454    }
00455 
00456    /* Close our own socket so we no longer get packets */
00457    if (rtp->s > -1) {
00458       close(rtp->s);
00459    }
00460 
00461    /* Destroy RTCP if it was being used */
00462    if (rtp->rtcp) {
00463       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
00464       close(rtp->rtcp->s);
00465       ast_free(rtp->rtcp);
00466    }
00467 
00468    /* Destroy RED if it was being used */
00469    if (rtp->red) {
00470       AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
00471       ast_free(rtp->red);
00472    }
00473 
00474    /* Finally destroy ourselves */
00475    ast_free(rtp);
00476 
00477    return 0;
00478 }

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

Definition at line 480 of file res_rtp_asterisk.c.

References ast_inet_ntoa(), 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_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(), ast_rtp::s, ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::sending_digit, ast_rtp::seqno, and ast_rtp::ssrc.

00481 {
00482    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00483    struct sockaddr_in remote_address = { 0, };
00484    int hdrlen = 12, res = 0, i = 0, payload = 101;
00485    char data[256];
00486    unsigned int *rtpheader = (unsigned int*)data;
00487 
00488    ast_rtp_instance_get_remote_address(instance, &remote_address);
00489 
00490    /* If we have no remote address information bail out now */
00491    if (!remote_address.sin_addr.s_addr || !remote_address.sin_port) {
00492       return -1;
00493    }
00494 
00495    /* Convert given digit into what we want to transmit */
00496    if ((digit <= '9') && (digit >= '0')) {
00497       digit -= '0';
00498    } else if (digit == '*') {
00499       digit = 10;
00500    } else if (digit == '#') {
00501       digit = 11;
00502    } else if ((digit >= 'A') && (digit <= 'D')) {
00503       digit = digit - 'A' + 12;
00504    } else if ((digit >= 'a') && (digit <= 'd')) {
00505       digit = digit - 'a' + 12;
00506    } else {
00507       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
00508       return -1;
00509    }
00510 
00511    /* Grab the payload that they expect the RFC2833 packet to be received in */
00512    payload = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 0, AST_RTP_DTMF);
00513 
00514    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
00515    rtp->send_duration = 160;
00516    rtp->lastdigitts = rtp->lastts + rtp->send_duration;
00517 
00518    /* Create the actual packet that we will be sending */
00519    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
00520    rtpheader[1] = htonl(rtp->lastdigitts);
00521    rtpheader[2] = htonl(rtp->ssrc);
00522 
00523    /* Actually send the packet */
00524    for (i = 0; i < 2; i++) {
00525       rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
00526       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &remote_address, sizeof(remote_address));
00527       if (res < 0) {
00528          ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n",
00529             ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port), strerror(errno));
00530       }
00531       if (rtp_debug_test_addr(&remote_address)) {
00532          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
00533                 ast_inet_ntoa(remote_address.sin_addr),
00534                 ntohs(remote_address.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
00535       }
00536       rtp->seqno++;
00537       rtp->send_duration += 160;
00538       rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
00539    }
00540 
00541    /* Record that we are in the process of sending a digit and information needed to continue doing so */
00542    rtp->sending_digit = 1;
00543    rtp->send_digit = digit;
00544    rtp->send_payload = payload;
00545 
00546    return 0;
00547 }

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 2361 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.

02362 {
02363    /* If both sides are not using the same method of DTMF transmission
02364     * (ie: one is RFC2833, other is INFO... then we can not do direct media.
02365     * --------------------------------------------------
02366     * | DTMF Mode |  HAS_DTMF  |  Accepts Begin Frames |
02367     * |-----------|------------|-----------------------|
02368     * | Inband    | False      | True                  |
02369     * | RFC2833   | True       | True                  |
02370     * | SIP INFO  | False      | False                 |
02371     * --------------------------------------------------
02372     */
02373    return (((ast_rtp_instance_get_prop(instance0, AST_RTP_PROPERTY_DTMF) != ast_rtp_instance_get_prop(instance1, AST_RTP_PROPERTY_DTMF)) ||
02374        (!chan0->tech->send_digit_begin != !chan1->tech->send_digit_begin)) ? 0 : 1);
02375 }

static int ast_rtp_dtmf_continuation ( struct ast_rtp_instance instance  )  [static]

Definition at line 549 of file res_rtp_asterisk.c.

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

Referenced by ast_rtp_read().

00550 {
00551    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00552    struct sockaddr_in remote_address = { 0, };
00553    int hdrlen = 12, res = 0;
00554    char data[256];
00555    unsigned int *rtpheader = (unsigned int*)data;
00556 
00557    ast_rtp_instance_get_remote_address(instance, &remote_address);
00558 
00559    /* Make sure we know where the other side is so we can send them the packet */
00560    if (!remote_address.sin_addr.s_addr || !remote_address.sin_port) {
00561       return -1;
00562    }
00563 
00564    /* Actually create the packet we will be sending */
00565    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
00566    rtpheader[1] = htonl(rtp->lastdigitts);
00567    rtpheader[2] = htonl(rtp->ssrc);
00568    rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration));
00569    rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
00570 
00571    /* Boom, send it on out */
00572    res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &remote_address, sizeof(remote_address));
00573    if (res < 0) {
00574       ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
00575          ast_inet_ntoa(remote_address.sin_addr),
00576          ntohs(remote_address.sin_port), strerror(errno));
00577    }
00578 
00579    if (rtp_debug_test_addr(&remote_address)) {
00580       ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
00581              ast_inet_ntoa(remote_address.sin_addr),
00582              ntohs(remote_address.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
00583    }
00584 
00585    /* And now we increment some values for the next time we swing by */
00586    rtp->seqno++;
00587    rtp->send_duration += 160;
00588 
00589    return 0;
00590 }

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

Definition at line 592 of file res_rtp_asterisk.c.

References ast_inet_ntoa(), ast_log(), ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address(), 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(), ast_rtp::s, ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::sending_digit, ast_rtp::seqno, and ast_rtp::ssrc.

00593 {
00594    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00595    struct sockaddr_in remote_address = { 0, };
00596    int hdrlen = 12, res = 0, i = 0;
00597    char data[256];
00598    unsigned int *rtpheader = (unsigned int*)data;
00599 
00600    ast_rtp_instance_get_remote_address(instance, &remote_address);
00601 
00602    /* Make sure we know where the remote side is so we can send them the packet we construct */
00603    if (!remote_address.sin_addr.s_addr || !remote_address.sin_port) {
00604       return -1;
00605    }
00606 
00607    /* Convert the given digit to the one we are going to send */
00608    if ((digit <= '9') && (digit >= '0')) {
00609       digit -= '0';
00610    } else if (digit == '*') {
00611       digit = 10;
00612    } else if (digit == '#') {
00613       digit = 11;
00614    } else if ((digit >= 'A') && (digit <= 'D')) {
00615       digit = digit - 'A' + 12;
00616    } else if ((digit >= 'a') && (digit <= 'd')) {
00617       digit = digit - 'a' + 12;
00618    } else {
00619       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
00620       return -1;
00621    }
00622 
00623    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
00624 
00625    /* Construct the packet we are going to send */
00626    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
00627    rtpheader[1] = htonl(rtp->lastdigitts);
00628    rtpheader[2] = htonl(rtp->ssrc);
00629    rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
00630    rtpheader[3] |= htonl((1 << 23));
00631    rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
00632 
00633    /* Send it 3 times, that's the magical number */
00634    for (i = 0; i < 3; i++) {
00635       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &remote_address, sizeof(remote_address));
00636       if (res < 0) {
00637          ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
00638             ast_inet_ntoa(remote_address.sin_addr),
00639             ntohs(remote_address.sin_port), strerror(errno));
00640       }
00641       if (rtp_debug_test_addr(&remote_address)) {
00642          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
00643                 ast_inet_ntoa(remote_address.sin_addr),
00644                 ntohs(remote_address.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
00645       }
00646    }
00647 
00648    /* Oh and we can't forget to turn off the stuff that says we are sending DTMF */
00649    rtp->lastts += rtp->send_duration;
00650    rtp->sending_digit = 0;
00651    rtp->send_digit = 0;
00652 
00653    return 0;
00654 }

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

Definition at line 2204 of file res_rtp_asterisk.c.

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

02205 {
02206    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02207 
02208    return rtcp ? (rtp->rtcp ? rtp->rtcp->s : -1) : rtp->s;
02209 }

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 2313 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.

02314 {
02315    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02316 
02317    if (!rtp->rtcp) {
02318       return -1;
02319    }
02320 
02321    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_TXCOUNT, -1, stats->txcount, rtp->txcount);
02322    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_RXCOUNT, -1, stats->rxcount, rtp->rxcount);
02323 
02324    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_TXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->txploss, rtp->rtcp->reported_lost);
02325    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);
02326    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MAXRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_maxrxploss, rtp->rtcp->reported_maxlost);
02327    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MINRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_minrxploss, rtp->rtcp->reported_minlost);
02328    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_normdevrxploss, rtp->rtcp->reported_normdev_lost);
02329    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_STDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_stdevrxploss, rtp->rtcp->reported_stdev_lost);
02330    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MAXRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_maxrxploss, rtp->rtcp->maxrxlost);
02331    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MINRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_minrxploss, rtp->rtcp->minrxlost);
02332    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_normdevrxploss, rtp->rtcp->normdev_rxlost);
02333    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_STDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_stdevrxploss, rtp->rtcp->stdev_rxlost);
02334    AST_RTP_STAT_TERMINATOR(AST_RTP_INSTANCE_STAT_COMBINED_LOSS);
02335 
02336    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_TXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->txjitter, rtp->rxjitter);
02337    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);
02338    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MAXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_maxjitter, rtp->rtcp->reported_maxjitter);
02339    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MINJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_minjitter, rtp->rtcp->reported_minjitter);
02340    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_normdevjitter, rtp->rtcp->reported_normdev_jitter);
02341    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_STDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_stdevjitter, rtp->rtcp->reported_stdev_jitter);
02342    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MAXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_maxjitter, rtp->rtcp->maxrxjitter);
02343    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MINJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_minjitter, rtp->rtcp->minrxjitter);
02344    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_normdevjitter, rtp->rtcp->normdev_rxjitter);
02345    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_STDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_stdevjitter, rtp->rtcp->stdev_rxjitter);
02346    AST_RTP_STAT_TERMINATOR(AST_RTP_INSTANCE_STAT_COMBINED_JITTER);
02347 
02348    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_RTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->rtt, rtp->rtcp->rtt);
02349    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_MAX_RTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->maxrtt, rtp->rtcp->maxrtt);
02350    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_MIN_RTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->minrtt, rtp->rtcp->minrtt);
02351    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_NORMDEVRTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->normdevrtt, rtp->rtcp->normdevrtt);
02352    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_STDEVRTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->stdevrtt, rtp->rtcp->stdevrtt);
02353    AST_RTP_STAT_TERMINATOR(AST_RTP_INSTANCE_STAT_COMBINED_RTT);
02354 
02355    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_SSRC, -1, stats->local_ssrc, rtp->ssrc);
02356    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_SSRC, -1, stats->remote_ssrc, rtp->themssrc);
02357 
02358    return 0;
02359 }

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

Definition at line 2304 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data(), ast_set_flag, and FLAG_NEED_MARKER_BIT.

02305 {
02306    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance0);
02307 
02308    ast_set_flag(rtp, FLAG_NEED_MARKER_BIT);
02309 
02310    return 0;
02311 }

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

Definition at line 390 of file res_rtp_asterisk.c.

References ast_calloc, ast_debug, ast_free, ast_log(), ast_random(), ast_rtp_instance_set_data(), ast_rtp_instance_set_local_address(), create_new_socket(), errno, LOG_ERROR, ast_rtp::s, ast_rtp::sched, ast_rtp::seqno, ast_rtp::ssrc, STRICT_RTP_LEARN, STRICT_RTP_OPEN, and ast_rtp::strict_rtp_state.

00391 {
00392    struct ast_rtp *rtp = NULL;
00393    int x, startplace;
00394 
00395    /* Create a new RTP structure to hold all of our data */
00396    if (!(rtp = ast_calloc(1, sizeof(*rtp)))) {
00397       return -1;
00398    }
00399 
00400    /* Set default parameters on the newly created RTP structure */
00401    rtp->ssrc = ast_random();
00402    rtp->seqno = ast_random() & 0xffff;
00403    rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN);
00404 
00405    /* Create a new socket for us to listen on and use */
00406    if ((rtp->s = create_new_socket("RTP")) < 0) {
00407       ast_debug(1, "Failed to create a new socket for RTP instance '%p'\n", instance);
00408       ast_free(rtp);
00409       return -1;
00410    }
00411 
00412    /* Now actually find a free RTP port to use */
00413    x = (rtpend == rtpstart) ? rtpstart : (ast_random() % (rtpend - rtpstart)) + rtpstart;
00414    x = x & ~1;
00415    startplace = x;
00416 
00417    for (;;) {
00418       sin->sin_port = htons(x);
00419       /* Try to bind, this will tell us whether the port is available or not */
00420       if (!bind(rtp->s, (struct sockaddr *)sin, sizeof(*sin))) {
00421          ast_debug(1, "Allocated port %d for RTP instance '%p'\n", x, instance);
00422          ast_rtp_instance_set_local_address(instance, sin);
00423          break;
00424       }
00425 
00426       x += 2;
00427       if (x > rtpend) {
00428          x = (rtpstart + 1) & ~1;
00429       }
00430 
00431       /* See if we ran out of ports or if the bind actually failed because of something other than the address being in use */
00432       if (x == startplace || errno != EADDRINUSE) {
00433          ast_log(LOG_ERROR, "Oh dear... we couldn't allocate a port for RTP instance '%p'\n", instance);
00434          return -1;
00435       }
00436    }
00437 
00438    /* Record any information we may need */
00439    rtp->sched = sched;
00440 
00441    /* Associate the RTP structure with the RTP instance and be done */
00442    ast_rtp_instance_set_data(instance, rtp);
00443 
00444    return 0;
00445 }

static void ast_rtp_new_source ( struct ast_rtp_instance instance  )  [static]

Definition at line 656 of file res_rtp_asterisk.c.

References ast_random(), ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), AST_RTP_PROPERTY_CONSTANT_SSRC, ast_set_flag, FLAG_NEED_MARKER_BIT, and ast_rtp::ssrc.

00657 {
00658    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00659 
00660    /* We simply set this bit so that the next packet sent will have the marker bit turned on */
00661    ast_set_flag(rtp, FLAG_NEED_MARKER_BIT);
00662 
00663    if (!ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_CONSTANT_SSRC)) {
00664       rtp->ssrc = ast_random();
00665    }
00666 
00667    return;
00668 }

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

Definition at line 2163 of file res_rtp_asterisk.c.

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

02164 {
02165    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02166 
02167    if (property == AST_RTP_PROPERTY_RTCP) {
02168       if (rtp->rtcp) {
02169          ast_debug(1, "Ignoring duplicate RTCP property on RTP instance '%p'\n", instance);
02170          return;
02171       }
02172       if (!(rtp->rtcp = ast_calloc(1, sizeof(*rtp->rtcp)))) {
02173          return;
02174       }
02175       if ((rtp->rtcp->s = create_new_socket("RTCP")) < 0) {
02176          ast_debug(1, "Failed to create a new socket for RTCP on instance '%p'\n", instance);
02177          ast_free(rtp->rtcp);
02178          rtp->rtcp = NULL;
02179          return;
02180       }
02181 
02182       /* Grab the IP address and port we are going to use */
02183       ast_rtp_instance_get_local_address(instance, &rtp->rtcp->us);
02184       rtp->rtcp->us.sin_port = htons(ntohs(rtp->rtcp->us.sin_port) + 1);
02185 
02186       /* 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 */
02187       if (bind(rtp->rtcp->s, (struct sockaddr*)&rtp->rtcp->us, sizeof(rtp->rtcp->us))) {
02188          ast_debug(1, "Failed to setup RTCP on RTP instance '%p'\n", instance);
02189          close(rtp->rtcp->s);
02190          ast_free(rtp->rtcp);
02191          rtp->rtcp = NULL;
02192          return;
02193       }
02194 
02195       ast_debug(1, "Setup RTCP on RTP instance '%p'\n", instance);
02196       rtp->rtcp->schedid = -1;
02197 
02198       return;
02199    }
02200 
02201    return;
02202 }

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

Definition at line 947 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_inet_ntoa(), 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_test_flag, ast_tvzero(), ast_verbose, calc_txstamp(), 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(), ast_rtp::s, 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().

00948 {
00949    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00950    int pred, mark = 0;
00951    unsigned int ms = calc_txstamp(rtp, &frame->delivery);
00952    struct sockaddr_in remote_address = { 0, };
00953    int rate = rtp_get_rate(frame->subclass) / 1000;
00954 
00955    if (frame->subclass == AST_FORMAT_G722) {
00956       frame->samples /= 2;
00957    }
00958 
00959    if (rtp->sending_digit) {
00960       return 0;
00961    }
00962 
00963    if (frame->frametype == AST_FRAME_VOICE) {
00964       pred = rtp->lastts + frame->samples;
00965 
00966       /* Re-calculate last TS */
00967       rtp->lastts = rtp->lastts + ms * rate;
00968       if (ast_tvzero(frame->delivery)) {
00969          /* If this isn't an absolute delivery time, Check if it is close to our prediction,
00970             and if so, go with our prediction */
00971          if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW) {
00972             rtp->lastts = pred;
00973          } else {
00974             ast_debug(3, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms);
00975             mark = 1;
00976          }
00977       }
00978    } else if (frame->frametype == AST_FRAME_VIDEO) {
00979       mark = frame->subclass & 0x1;
00980       pred = rtp->lastovidtimestamp + frame->samples;
00981       /* Re-calculate last TS */
00982       rtp->lastts = rtp->lastts + ms * 90;
00983       /* If it's close to our prediction, go for it */
00984       if (ast_tvzero(frame->delivery)) {
00985          if (abs(rtp->lastts - pred) < 7200) {
00986             rtp->lastts = pred;
00987             rtp->lastovidtimestamp += frame->samples;
00988          } else {
00989             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);
00990             rtp->lastovidtimestamp = rtp->lastts;
00991          }
00992       }
00993    } else {
00994       pred = rtp->lastotexttimestamp + frame->samples;
00995       /* Re-calculate last TS */
00996       rtp->lastts = rtp->lastts + ms;
00997       /* If it's close to our prediction, go for it */
00998       if (ast_tvzero(frame->delivery)) {
00999          if (abs(rtp->lastts - pred) < 7200) {
01000             rtp->lastts = pred;
01001             rtp->lastotexttimestamp += frame->samples;
01002          } else {
01003             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);
01004             rtp->lastotexttimestamp = rtp->lastts;
01005          }
01006       }
01007    }
01008 
01009    /* If we have been explicitly told to set the marker bit then do so */
01010    if (ast_test_flag(rtp, FLAG_NEED_MARKER_BIT)) {
01011       mark = 1;
01012       ast_clear_flag(rtp, FLAG_NEED_MARKER_BIT);
01013    }
01014 
01015    /* If the timestamp for non-digt packets has moved beyond the timestamp for digits, update the digit timestamp */
01016    if (rtp->lastts > rtp->lastdigitts) {
01017       rtp->lastdigitts = rtp->lastts;
01018    }
01019 
01020    if (ast_test_flag(frame, AST_FRFLAG_HAS_TIMING_INFO)) {
01021       rtp->lastts = frame->ts * rate;
01022    }
01023 
01024    ast_rtp_instance_get_remote_address(instance, &remote_address);
01025 
01026    /* If we know the remote address construct a packet and send it out */
01027    if (remote_address.sin_port && remote_address.sin_addr.s_addr) {
01028       int hdrlen = 12, res;
01029       unsigned char *rtpheader = (unsigned char *)(frame->data.ptr - hdrlen);
01030 
01031       put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23)));
01032       put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts));
01033       put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc));
01034 
01035       if ((res = sendto(rtp->s, (void *)rtpheader, frame->datalen + hdrlen, 0, (struct sockaddr *)&remote_address, sizeof(remote_address))) < 0) {
01036          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))) {
01037             ast_debug(1, "RTP Transmission error of packet %d to %s:%d: %s\n", rtp->seqno, ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port), strerror(errno));
01038          } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) {
01039             /* Only give this error message once if we are not RTP debugging */
01040             if (option_debug || rtpdebug)
01041                ast_debug(0, "RTP NAT: Can't write RTP to private address %s:%d, waiting for other end to send audio...\n", ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port));
01042             ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN);
01043          }
01044       } else {
01045          rtp->txcount++;
01046          rtp->txoctetcount += (res - hdrlen);
01047 
01048          if (rtp->rtcp && rtp->rtcp->schedid < 1) {
01049             ast_debug(1, "Starting RTCP transmission on RTP instance '%p'\n", instance);
01050             rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
01051          }
01052       }
01053 
01054       if (rtp_debug_test_addr(&remote_address)) {
01055          ast_verbose("Sent RTP packet to      %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
01056                 ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port), codec, rtp->seqno, rtp->lastts, res - hdrlen);
01057       }
01058    }
01059 
01060    rtp->seqno++;
01061 
01062    return 0;
01063 }

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

Definition at line 1855 of file res_rtp_asterisk.c.

References ast_rtp::alt_rtp_address, ast_assert, ast_codec_get_samples(), ast_debug, AST_FORMAT_AUDIO_MASK, ast_format_rate(), AST_FORMAT_SLINEAR, AST_FORMAT_T140, AST_FORMAT_T140RED, AST_FORMAT_VIDEO_MASK, ast_frame_byteswap_be, AST_FRAME_DTMF_END, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), 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_STUN_ACCEPT, ast_stun_handle_packet(), ast_tv(), ast_tvdiff_ms(), ast_verbose, ast_rtp_payload_type::asterisk_format, bridge_p2p_rtp_write(), calc_rxstamp(), ast_rtp_payload_type::code, ast_rtp::cycles, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp::dtmf_duration, ast_rtp::dtmf_timeout, errno, ext, ast_rtp::f, f, FLAG_NAT_ACTIVE, ast_frame::frametype, ast_rtp::lastitexttimestamp, ast_rtp::lastividtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxseqno, ast_rtp::lastrxts, ast_frame::len, 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_SEQ_MOD, ast_rtp::rxcount, ast_rtp::rxseqno, ast_rtp::rxssrc, ast_rtp::s, ast_frame::samples, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, send_dtmf(), 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, ast_frame::ts, and version.

01856 {
01857    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
01858    struct sockaddr_in sin;
01859    socklen_t len = sizeof(sin);
01860    int res, hdrlen = 12, version, payloadtype, padding, mark, ext, cc, prev_seqno;
01861    unsigned int *rtpheader = (unsigned int*)(rtp->rawdata + AST_FRIENDLY_OFFSET), seqno, ssrc, timestamp;
01862    struct ast_rtp_payload_type payload;
01863    struct sockaddr_in remote_address = { 0, };
01864 
01865    /* If this is actually RTCP let's hop on over and handle it */
01866    if (rtcp) {
01867       if (rtp->rtcp) {
01868          return ast_rtcp_read(instance);
01869       }
01870       return &ast_null_frame;
01871    }
01872 
01873    /* If we are currently sending DTMF to the remote party send a continuation packet */
01874    if (rtp->sending_digit) {
01875       ast_rtp_dtmf_continuation(instance);
01876    }
01877 
01878    /* Actually read in the data from the socket */
01879    if ((res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 0, (struct sockaddr*)&sin, &len)) < 0) {
01880       ast_assert(errno != EBADF);
01881       if (errno != EAGAIN) {
01882          ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n", strerror(errno));
01883          return NULL;
01884       }
01885       return &ast_null_frame;
01886    }
01887 
01888    /* Make sure the data that was read in is actually enough to make up an RTP packet */
01889    if (res < hdrlen) {
01890       ast_log(LOG_WARNING, "RTP Read too short\n");
01891       return &ast_null_frame;
01892    }
01893 
01894    /* If strict RTP protection is enabled see if we need to learn the remote address or if we need to drop the packet */
01895    if (rtp->strict_rtp_state == STRICT_RTP_LEARN) {
01896       memcpy(&rtp->strict_rtp_address, &sin, sizeof(rtp->strict_rtp_address));
01897       rtp->strict_rtp_state = STRICT_RTP_CLOSED;
01898    } else if (rtp->strict_rtp_state == STRICT_RTP_CLOSED) {
01899       if ((rtp->strict_rtp_address.sin_addr.s_addr != sin.sin_addr.s_addr) || (rtp->strict_rtp_address.sin_port != sin.sin_port)) {
01900          /* Hmm, not the strict addres. Perhaps we're getting audio from the alternate? */
01901          if ((rtp->alt_rtp_address.sin_addr.s_addr == sin.sin_addr.s_addr) && (rtp->alt_rtp_address.sin_port == sin.sin_port)) {
01902             /* ooh, we did! You're now the new expected address, son! */
01903             rtp->strict_rtp_address = sin;
01904          } else  {
01905             ast_debug(1, "Received RTP packet from %s:%d, dropping due to strict RTP protection. Expected it to be from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), ast_inet_ntoa(rtp->strict_rtp_address.sin_addr), ntohs(rtp->strict_rtp_address.sin_port));
01906             return &ast_null_frame;
01907          }
01908       }
01909    }
01910 
01911    /* Get fields and verify this is an RTP packet */
01912    seqno = ntohl(rtpheader[0]);
01913 
01914    ast_rtp_instance_get_remote_address(instance, &remote_address);
01915 
01916    if (!(version = (seqno & 0xC0000000) >> 30)) {
01917       if ((ast_stun_handle_packet(rtp->s, &sin, rtp->rawdata + AST_FRIENDLY_OFFSET, res, NULL, NULL) == AST_STUN_ACCEPT) &&
01918           (!remote_address.sin_port && !remote_address.sin_addr.s_addr)) {
01919          ast_rtp_instance_set_remote_address(instance, &sin);
01920       }
01921       return &ast_null_frame;
01922    }
01923 
01924    /* If symmetric RTP is enabled see if the remote side is not what we expected and change where we are sending audio */
01925    if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT)) {
01926       if ((remote_address.sin_addr.s_addr != sin.sin_addr.s_addr) ||
01927           (remote_address.sin_port != sin.sin_port)) {
01928          ast_rtp_instance_set_remote_address(instance, &sin);
01929          memcpy(&remote_address, &sin, sizeof(remote_address));
01930          if (rtp->rtcp) {
01931             memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
01932             rtp->rtcp->them.sin_port = htons(ntohs(sin.sin_port)+1);
01933          }
01934          rtp->rxseqno = 0;
01935          ast_set_flag(rtp, FLAG_NAT_ACTIVE);
01936          if (option_debug || rtpdebug)
01937             ast_debug(0, "RTP NAT: Got audio from other end. Now sending to address %s:%d\n", ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port));
01938       }
01939    }
01940 
01941    /* If we are directly bridged to another instance send the audio directly out */
01942    if (ast_rtp_instance_get_bridged(instance) && !bridge_p2p_rtp_write(instance, rtpheader, res, hdrlen)) {
01943       return &ast_null_frame;
01944    }
01945 
01946    /* If the version is not what we expected by this point then just drop the packet */
01947    if (version != 2) {
01948       return &ast_null_frame;
01949    }
01950 
01951    /* Pull out the various other fields we will need */
01952    payloadtype = (seqno & 0x7f0000) >> 16;
01953    padding = seqno & (1 << 29);
01954    mark = seqno & (1 << 23);
01955    ext = seqno & (1 << 28);
01956    cc = (seqno & 0xF000000) >> 24;
01957    seqno &= 0xffff;
01958    timestamp = ntohl(rtpheader[1]);
01959    ssrc = ntohl(rtpheader[2]);
01960 
01961    /* Force a marker bit if the SSRC changes */
01962    if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) {
01963       if (option_debug || rtpdebug) {
01964          ast_debug(1, "Forcing Marker bit, because SSRC has changed\n");
01965       }
01966       mark = 1;
01967    }
01968 
01969    /* Remove any padding bytes that may be present */
01970    if (padding) {
01971       res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1];
01972    }
01973 
01974    /* Skip over any CSRC fields */
01975    if (cc) {
01976       hdrlen += cc * 4;
01977    }
01978 
01979    /* Look for any RTP extensions, currently we do not support any */
01980    if (ext) {
01981       hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2;
01982       hdrlen += 4;
01983       if (option_debug) {
01984          int profile;
01985          profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16;
01986          if (profile == 0x505a)
01987             ast_debug(1, "Found Zfone extension in RTP stream - zrtp - not supported.\n");
01988          else
01989             ast_debug(1, "Found unknown RTP Extensions %x\n", profile);
01990       }
01991    }
01992 
01993    /* Make sure after we potentially mucked with the header length that it is once again valid */
01994    if (res < hdrlen) {
01995       ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d\n", res, hdrlen);
01996       return &ast_null_frame;
01997    }
01998 
01999    rtp->rxcount++;
02000    if (rtp->rxcount == 1) {
02001       rtp->seedrxseqno = seqno;
02002    }
02003 
02004    /* Do not schedule RR if RTCP isn't run */
02005    if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) {
02006       /* Schedule transmission of Receiver Report */
02007       rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
02008    }
02009    if ((int)rtp->lastrxseqno - (int)seqno  > 100) /* if so it would indicate that the sender cycled; allow for misordering */
02010       rtp->cycles += RTP_SEQ_MOD;
02011 
02012    prev_seqno = rtp->lastrxseqno;
02013    rtp->lastrxseqno = seqno;
02014 
02015    if (!rtp->themssrc) {
02016       rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */
02017    }
02018 
02019    if (rtp_debug_test_addr(&sin)) {
02020       ast_verbose("Got  RTP packet from    %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02021              ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen);
02022    }
02023 
02024    payload = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(instance), payloadtype);
02025 
02026    /* If the payload is not actually an Asterisk one but a special one pass it off to the respective handler */
02027    if (!payload.asterisk_format) {
02028       struct ast_frame *f = NULL;
02029       if (payload.code == AST_RTP_DTMF) {
02030          f = process_dtmf_rfc2833(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &sin, payloadtype, mark);
02031       } else if (payload.code == AST_RTP_CISCO_DTMF) {
02032          f = process_dtmf_cisco(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &sin, payloadtype, mark);
02033       } else if (payload.code == AST_RTP_CN) {
02034          f = process_cn_rfc3389(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &sin, payloadtype, mark);
02035       } else {
02036          ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(remote_address.sin_addr));
02037       }
02038 
02039       return f ? f : &ast_null_frame;
02040    }
02041 
02042    rtp->lastrxformat = rtp->f.subclass = payload.code;
02043    rtp->f.frametype = (rtp->f.subclass & AST_FORMAT_AUDIO_MASK) ? AST_FRAME_VOICE : (rtp->f.subclass & AST_FORMAT_VIDEO_MASK) ? AST_FRAME_VIDEO : AST_FRAME_TEXT;
02044 
02045    rtp->rxseqno = seqno;
02046 
02047    if (rtp->dtmf_timeout && rtp->dtmf_timeout < timestamp) {
02048       rtp->dtmf_timeout = 0;
02049 
02050       if (rtp->resp) {
02051          struct ast_frame *f;
02052          f = send_dtmf(instance, AST_FRAME_DTMF_END, 0);
02053          f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass)), ast_tv(0, 0));
02054          rtp->resp = 0;
02055          rtp->dtmf_timeout = rtp->dtmf_duration = 0;
02056          return f;
02057       }
02058    }
02059 
02060    rtp->lastrxts = timestamp;
02061 
02062    rtp->f.src = "RTP";
02063    rtp->f.mallocd = 0;
02064    rtp->f.datalen = res - hdrlen;
02065    rtp->f.data.ptr = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
02066    rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
02067    rtp->f.seqno = seqno;
02068 
02069    if (rtp->f.subclass == AST_FORMAT_T140 && (int)seqno - (prev_seqno+1) > 0 && (int)seqno - (prev_seqno+1) < 10) {
02070       unsigned char *data = rtp->f.data.ptr;
02071 
02072       memmove(rtp->f.data.ptr+3, rtp->f.data.ptr, rtp->f.datalen);
02073       rtp->f.datalen +=3;
02074       *data++ = 0xEF;
02075       *data++ = 0xBF;
02076       *data = 0xBD;
02077    }
02078 
02079    if (rtp->f.subclass == AST_FORMAT_T140RED) {
02080       unsigned char *data = rtp->f.data.ptr;
02081       unsigned char *header_end;
02082       int num_generations;
02083       int header_length;
02084       int len;
02085       int diff =(int)seqno - (prev_seqno+1); /* if diff = 0, no drop*/
02086       int x;
02087 
02088       rtp->f.subclass = AST_FORMAT_T140;
02089       header_end = memchr(data, ((*data) & 0x7f), rtp->f.datalen);
02090       if (header_end == NULL) {
02091          return &ast_null_frame;
02092       }
02093       header_end++;
02094 
02095       header_length = header_end - data;
02096       num_generations = header_length / 4;
02097       len = header_length;
02098 
02099       if (!diff) {
02100          for (x = 0; x < num_generations; x++)
02101             len += data[x * 4 + 3];
02102 
02103          if (!(rtp->f.datalen - len))
02104             return &ast_null_frame;
02105 
02106          rtp->f.data.ptr += len;
02107          rtp->f.datalen -= len;
02108       } else if (diff > num_generations && diff < 10) {
02109          len -= 3;
02110          rtp->f.data.ptr += len;
02111          rtp->f.datalen -= len;
02112 
02113          data = rtp->f.data.ptr;
02114          *data++ = 0xEF;
02115          *data++ = 0xBF;
02116          *data = 0xBD;
02117       } else {
02118          for ( x = 0; x < num_generations - diff; x++)
02119             len += data[x * 4 + 3];
02120 
02121          rtp->f.data.ptr += len;
02122          rtp->f.datalen -= len;
02123       }
02124    }
02125 
02126    if (rtp->f.subclass & AST_FORMAT_AUDIO_MASK) {
02127       rtp->f.samples = ast_codec_get_samples(&rtp->f);
02128       if (rtp->f.subclass == AST_FORMAT_SLINEAR)
02129          ast_frame_byteswap_be(&rtp->f);
02130       calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
02131       /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */
02132       ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO);
02133       rtp->f.ts = timestamp / (rtp_get_rate(rtp->f.subclass) / 1000);
02134       rtp->f.len = rtp->f.samples / ((ast_format_rate(rtp->f.subclass) / 1000));
02135    } else if (rtp->f.subclass & AST_FORMAT_VIDEO_MASK) {
02136       /* Video -- samples is # of samples vs. 90000 */
02137       if (!rtp->lastividtimestamp)
02138          rtp->lastividtimestamp = timestamp;
02139       rtp->f.samples = timestamp - rtp->lastividtimestamp;
02140       rtp->lastividtimestamp = timestamp;
02141       rtp->f.delivery.tv_sec = 0;
02142       rtp->f.delivery.tv_usec = 0;
02143       /* Pass the RTP marker bit as bit 0 in the subclass field.
02144        * This is ok because subclass is actually a bitmask, and
02145        * the low bits represent audio formats, that are not
02146        * involved here since we deal with video.
02147        */
02148       if (mark)
02149          rtp->f.subclass |= 0x1;
02150    } else {
02151       /* TEXT -- samples is # of samples vs. 1000 */
02152       if (!rtp->lastitexttimestamp)
02153          rtp->lastitexttimestamp = timestamp;
02154       rtp->f.samples = timestamp - rtp->lastitexttimestamp;
02155       rtp->lastitexttimestamp = timestamp;
02156       rtp->f.delivery.tv_sec = 0;
02157       rtp->f.delivery.tv_usec = 0;
02158    }
02159 
02160    return &rtp->f;
02161 }

static void ast_rtp_remote_address_set ( struct ast_rtp_instance instance,
struct sockaddr_in *  sin 
) [static]

Definition at line 2211 of file res_rtp_asterisk.c.

References ast_debug, ast_rtp_instance_get_data(), ast_rtp::rtcp, ast_rtp::rxseqno, STRICT_RTP_LEARN, ast_rtp::strict_rtp_state, and ast_rtcp::them.

02212 {
02213    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02214 
02215    if (rtp->rtcp) {
02216       ast_debug(1, "Setting RTCP address on RTP instance '%p'\n", instance);
02217       memcpy(&rtp->rtcp->them, sin, sizeof(rtp->rtcp->them));
02218       rtp->rtcp->them.sin_port = htons(ntohs(sin->sin_port) + 1);
02219    }
02220 
02221    rtp->rxseqno = 0;
02222 
02223    if (strictrtp) {
02224       rtp->strict_rtp_state = STRICT_RTP_LEARN;
02225    }
02226 
02227    return;
02228 }

static void ast_rtp_stop ( struct ast_rtp_instance instance  )  [static]

Definition at line 2384 of file res_rtp_asterisk.c.

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

02385 {
02386    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02387    struct sockaddr_in sin = { 0, };
02388 
02389    if (rtp->rtcp) {
02390       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02391    }
02392    if (rtp->red) {
02393       AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
02394       free(rtp->red);
02395       rtp->red = NULL;
02396    }
02397 
02398    ast_rtp_instance_set_remote_address(instance, &sin);
02399    if (rtp->rtcp) {
02400       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
02401       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
02402    }
02403 
02404    ast_set_flag(rtp, FLAG_NEED_MARKER_BIT);
02405 }

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

Definition at line 2377 of file res_rtp_asterisk.c.

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

02378 {
02379    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02380 
02381    ast_stun_request(rtp->s, suggestion, username, NULL);
02382 }

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

Definition at line 1102 of file res_rtp_asterisk.c.

References ast_codec_pref_getsize(), ast_debug, AST_FORMAT_G723_1, AST_FORMAT_SIREN14, AST_FORMAT_SIREN7, AST_FORMAT_SPEEX, 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_format_list::cur_ms, ast_frame::data, 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_frame::ptr, ast_rtp::red, red_t140_to_red(), ast_rtp::smoother, and ast_frame::subclass.

Referenced by red_write().

01103 {
01104    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
01105    struct sockaddr_in remote_address = { 0, };
01106    int codec, subclass;
01107 
01108    ast_rtp_instance_get_remote_address(instance, &remote_address);
01109 
01110    /* If we don't actually know the remote address don't even bother doing anything */
01111    if (!remote_address.sin_addr.s_addr) {
01112       ast_debug(1, "No remote address on RTP instance '%p' so dropping frame\n", instance);
01113       return 0;
01114    }
01115 
01116    /* If there is no data length we can't very well send the packet */
01117    if (!frame->datalen) {
01118       ast_debug(1, "Received frame with no data for RTP instance '%p' so dropping frame\n", instance);
01119       return 0;
01120    }
01121 
01122    /* If the packet is not one our RTP stack supports bail out */
01123    if (frame->frametype != AST_FRAME_VOICE && frame->frametype != AST_FRAME_VIDEO && frame->frametype != AST_FRAME_TEXT) {
01124       ast_log(LOG_WARNING, "RTP can only send voice, video, and text\n");
01125       return -1;
01126    }
01127 
01128    if (rtp->red) {
01129       /* return 0; */
01130       /* no primary data or generations to send */
01131       if ((frame = red_t140_to_red(rtp->red)) == NULL)
01132          return 0;
01133    }
01134 
01135    /* Grab the subclass and look up the payload we are going to use */
01136    subclass = frame->subclass;
01137    if (frame->frametype == AST_FRAME_VIDEO) {
01138       subclass &= ~0x1;
01139    }
01140    if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, subclass)) < 0) {
01141       ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(frame->subclass));
01142       return -1;
01143    }
01144 
01145    /* Oh dear, if the format changed we will have to set up a new smoother */
01146    if (rtp->lasttxformat != subclass) {
01147       ast_debug(1, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
01148       rtp->lasttxformat = subclass;
01149       if (rtp->smoother) {
01150          ast_smoother_free(rtp->smoother);
01151          rtp->smoother = NULL;
01152       }
01153    }
01154 
01155    /* If no smoother is present see if we have to set one up */
01156    if (!rtp->smoother) {
01157       struct ast_format_list fmt = ast_codec_pref_getsize(&ast_rtp_instance_get_codecs(instance)->pref, subclass);
01158 
01159       switch (subclass) {
01160       case AST_FORMAT_SPEEX:
01161       case AST_FORMAT_G723_1:
01162       case AST_FORMAT_SIREN7:
01163       case AST_FORMAT_SIREN14:
01164          /* these are all frame-based codecs and cannot be safely run through
01165             a smoother */
01166          break;
01167       default:
01168          if (fmt.inc_ms) {
01169             if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
01170                ast_log(LOG_WARNING, "Unable to create smoother: format %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
01171                return -1;
01172             }
01173             if (fmt.flags) {
01174                ast_smoother_set_flags(rtp->smoother, fmt.flags);
01175             }
01176             ast_debug(1, "Created smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
01177          }
01178       }
01179    }
01180 
01181    /* Feed audio frames into the actual function that will create a frame and send it */
01182    if (rtp->smoother) {
01183       struct ast_frame *f;
01184 
01185       if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) {
01186          ast_smoother_feed_be(rtp->smoother, frame);
01187       } else {
01188          ast_smoother_feed(rtp->smoother, frame);
01189       }
01190 
01191       while ((f = ast_smoother_read(rtp->smoother)) && (f->data.ptr)) {
01192             ast_rtp_raw_write(instance, f, codec);
01193       }
01194    } else {
01195       int hdrlen = 12;
01196       struct ast_frame *f = NULL;
01197 
01198       if (frame->offset < hdrlen) {
01199          f = ast_frdup(frame);
01200       } else {
01201          f = frame;
01202       }
01203       if (f->data.ptr) {
01204          ast_rtp_raw_write(instance, f, codec);
01205       }
01206       if (f != frame) {
01207          ast_frfree(f);
01208       }
01209 
01210    }
01211 
01212    return 0;
01213 }

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

Definition at line 1799 of file res_rtp_asterisk.c.

References ast_clear_flag, ast_debug, ast_inet_ntoa(), 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_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, option_debug, reconstruct(), and rtp_debug_test_addr().

Referenced by ast_rtp_read().

01800 {
01801    struct ast_rtp_instance *instance1 = ast_rtp_instance_get_bridged(instance);
01802    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance), *bridged = ast_rtp_instance_get_data(instance1);
01803    int res = 0, payload = 0, bridged_payload = 0, mark;
01804    struct ast_rtp_payload_type payload_type;
01805    int reconstruct = ntohl(rtpheader[0]);
01806    struct sockaddr_in remote_address = { 0, };
01807 
01808    /* Get fields from packet */
01809    payload = (reconstruct & 0x7f0000) >> 16;
01810    mark = (((reconstruct & 0x800000) >> 23) != 0);
01811 
01812    /* Check what the payload value should be */
01813    payload_type = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(instance), payload);
01814 
01815    /* Otherwise adjust bridged payload to match */
01816    bridged_payload = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance1), payload_type.asterisk_format, payload_type.code);
01817 
01818    /* 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 */
01819    if (!(ast_rtp_instance_get_codecs(instance1)->payloads[bridged_payload].code)) {
01820       return -1;
01821    }
01822 
01823    /* If the marker bit has been explicitly set turn it on */
01824    if (ast_test_flag(rtp, FLAG_NEED_MARKER_BIT)) {
01825       mark = 1;
01826       ast_clear_flag(rtp, FLAG_NEED_MARKER_BIT);
01827    }
01828 
01829    /* Reconstruct part of the packet */
01830    reconstruct &= 0xFF80FFFF;
01831    reconstruct |= (bridged_payload << 16);
01832    reconstruct |= (mark << 23);
01833    rtpheader[0] = htonl(reconstruct);
01834 
01835    ast_rtp_instance_get_remote_address(instance1, &remote_address);
01836 
01837    /* Send the packet back out */
01838    res = sendto(bridged->s, (void *)rtpheader, len, 0, (struct sockaddr *)&remote_address, sizeof(remote_address));
01839    if (res < 0) {
01840       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))) {
01841          ast_debug(1, "RTP Transmission error of packet to %s:%d: %s\n", ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port), strerror(errno));
01842       } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) {
01843          if (option_debug || rtpdebug)
01844             ast_debug(0, "RTP NAT: Can't write RTP to private address %s:%d, waiting for other end to send audio...\n", ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port));
01845          ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN);
01846       }
01847       return 0;
01848    } else if (rtp_debug_test_addr(&remote_address)) {
01849       ast_verbose("Sent RTP P2P packet to %s:%u (type %-2.2d, len %-6.6u)\n", ast_inet_ntoa(remote_address.sin_addr), ntohs(remote_address.sin_port), bridged_payload, len - hdrlen);
01850    }
01851 
01852    return 0;
01853 }

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

Definition at line 1227 of file res_rtp_asterisk.c.

References 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, sanitize_tv(), ast_rtp::seedrxts, stddev_compute(), ast_rtcp::stdev_rxjitter, and ast_frame::subclass.

01228 {
01229    struct timeval now;
01230    double transit;
01231    double current_time;
01232    double d;
01233    double dtv;
01234    double prog;
01235    int rate = rtp_get_rate(rtp->f.subclass);
01236 
01237    double normdev_rxjitter_current;
01238    if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) {
01239       gettimeofday(&rtp->rxcore, NULL);
01240       rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000;
01241       /* map timestamp to a real time */
01242       rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */
01243       rtp->rxcore.tv_sec -= timestamp / rate;
01244       rtp->rxcore.tv_usec -= (timestamp % rate) * 125;
01245       /* Round to 0.1ms for nice, pretty timestamps */
01246       rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100;
01247       sanitize_tv(&rtp->rxcore);
01248    }
01249 
01250    gettimeofday(&now,NULL);
01251    /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */
01252    tv->tv_sec = rtp->rxcore.tv_sec + timestamp / rate;
01253    tv->tv_usec = rtp->rxcore.tv_usec + (timestamp % rate) * 125;
01254    sanitize_tv(tv);
01255    prog = (double)((timestamp-rtp->seedrxts)/(float)(rate));
01256    dtv = (double)rtp->drxcore + (double)(prog);
01257    current_time = (double)now.tv_sec + (double)now.tv_usec/1000000;
01258    transit = current_time - dtv;
01259    d = transit - rtp->rxtransit;
01260    rtp->rxtransit = transit;
01261    if (d<0)
01262       d=-d;
01263    rtp->rxjitter += (1./16.) * (d - rtp->rxjitter);
01264 
01265    if (rtp->rtcp) {
01266       if (rtp->rxjitter > rtp->rtcp->maxrxjitter)
01267          rtp->rtcp->maxrxjitter = rtp->rxjitter;
01268       if (rtp->rtcp->rxjitter_count == 1)
01269          rtp->rtcp->minrxjitter = rtp->rxjitter;
01270       if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter)
01271          rtp->rtcp->minrxjitter = rtp->rxjitter;
01272 
01273       normdev_rxjitter_current = normdev_compute(rtp->rtcp->normdev_rxjitter,rtp->rxjitter,rtp->rtcp->rxjitter_count);
01274       rtp->rtcp->stdev_rxjitter = stddev_compute(rtp->rtcp->stdev_rxjitter,rtp->rxjitter,rtp->rtcp->normdev_rxjitter,normdev_rxjitter_current,rtp->rtcp->rxjitter_count);
01275 
01276       rtp->rtcp->normdev_rxjitter = normdev_rxjitter_current;
01277       rtp->rtcp->rxjitter_count++;
01278    }
01279 }

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

Definition at line 670 of file res_rtp_asterisk.c.

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

Referenced by ast_rtp_raw_write().

00671 {
00672    struct timeval t;
00673    long ms;
00674 
00675    if (ast_tvzero(rtp->txcore)) {
00676       rtp->txcore = ast_tvnow();
00677       rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
00678    }
00679 
00680    t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
00681    if ((ms = ast_tvdiff_ms(t, rtp->txcore)) < 0) {
00682       ms = 0;
00683    }
00684    rtp->txcore = t;
00685 
00686    return (unsigned int) ms;
00687 }

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

Definition at line 368 of file res_rtp_asterisk.c.

References ast_log(), errno, and LOG_WARNING.

Referenced by ast_rtp_new(), and ast_rtp_prop_set().

00369 {
00370    int sock = socket(AF_INET, SOCK_DGRAM, 0);
00371 
00372    if (sock < 0) {
00373       if (!type) {
00374          type = "RTP/RTCP";
00375       }
00376       ast_log(LOG_WARNING, "Unable to allocate %s socket: %s\n", type, strerror(errno));
00377    } else {
00378       long flags = fcntl(sock, F_GETFL);
00379       fcntl(sock, F_SETFL, flags | O_NONBLOCK);
00380 #ifdef SO_NO_CHECK
00381       if (nochecksums) {
00382          setsockopt(sock, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
00383       }
00384 #endif
00385    }
00386 
00387    return sock;
00388 }

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

Definition at line 2498 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(), rtcpdebugaddr, and ast_cli_entry::usage.

02499 {
02500    switch (cmd) {
02501    case CLI_INIT:
02502       e->command = "rtcp set debug {on|off|ip}";
02503       e->usage =
02504          "Usage: rtcp set debug {on|off|ip host[:port]}\n"
02505          "       Enable/Disable dumping of all RTCP packets. If 'ip' is\n"
02506          "       specified, limit the dumped packets to those to and from\n"
02507          "       the specified 'host' with optional port.\n";
02508       return NULL;
02509    case CLI_GENERATE:
02510       return NULL;
02511    }
02512 
02513    if (a->argc == e->args) { /* set on or off */
02514       if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
02515          rtcpdebug = 1;
02516          memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr));
02517          ast_cli(a->fd, "RTCP Debugging Enabled\n");
02518          return CLI_SUCCESS;
02519       } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
02520          rtcpdebug = 0;
02521          ast_cli(a->fd, "RTCP Debugging Disabled\n");
02522          return CLI_SUCCESS;
02523       }
02524    } else if (a->argc == e->args +1) { /* ip */
02525       return rtcp_do_debug_ip(a);
02526    }
02527 
02528    return CLI_SHOWUSAGE;   /* default, failure */
02529 }

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

Definition at line 2531 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, and ast_cli_entry::usage.

02532 {
02533    switch (cmd) {
02534    case CLI_INIT:
02535       e->command = "rtcp set stats {on|off}";
02536       e->usage =
02537          "Usage: rtcp set stats {on|off}\n"
02538          "       Enable/Disable dumping of RTCP stats.\n";
02539       return NULL;
02540    case CLI_GENERATE:
02541       return NULL;
02542    }
02543 
02544    if (a->argc != e->args)
02545       return CLI_SHOWUSAGE;
02546 
02547    if (!strncasecmp(a->argv[e->args-1], "on", 2))
02548       rtcpstats = 1;
02549    else if (!strncasecmp(a->argv[e->args-1], "off", 3))
02550       rtcpstats = 0;
02551    else
02552       return CLI_SHOWUSAGE;
02553 
02554    ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled");
02555    return CLI_SUCCESS;
02556 }

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

Definition at line 2465 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(), rtpdebugaddr, and ast_cli_entry::usage.

02466 {
02467    switch (cmd) {
02468    case CLI_INIT:
02469       e->command = "rtp set debug {on|off|ip}";
02470       e->usage =
02471          "Usage: rtp set debug {on|off|ip host[:port]}\n"
02472          "       Enable/Disable dumping of all RTP packets. If 'ip' is\n"
02473          "       specified, limit the dumped packets to those to and from\n"
02474          "       the specified 'host' with optional port.\n";
02475       return NULL;
02476    case CLI_GENERATE:
02477       return NULL;
02478    }
02479 
02480    if (a->argc == e->args) { /* set on or off */
02481       if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
02482          rtpdebug = 1;
02483          memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr));
02484          ast_cli(a->fd, "RTP Debugging Enabled\n");
02485          return CLI_SUCCESS;
02486       } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
02487          rtpdebug = 0;
02488          ast_cli(a->fd, "RTP Debugging Disabled\n");
02489          return CLI_SUCCESS;
02490       }
02491    } else if (a->argc == e->args +1) { /* ip */
02492       return rtp_do_debug_ip(a);
02493    }
02494 
02495    return CLI_SHOWUSAGE;   /* default, failure */
02496 }

static int load_module ( void   )  [static]

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

Calculate normal deviation.

Definition at line 340 of file res_rtp_asterisk.c.

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

00341 {
00342    normdev = normdev * sample_count + sample;
00343    sample_count++;
00344 
00345    return normdev / sample_count;
00346 }

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

Definition at line 1496 of file res_rtp_asterisk.c.

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

Referenced by ast_rtp_read().

01497 {
01498    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
01499 
01500    /* Convert comfort noise into audio with various codecs.  Unfortunately this doesn't
01501       totally help us out becuase we don't have an engine to keep it going and we are not
01502       guaranteed to have it every 20ms or anything */
01503    if (rtpdebug)
01504       ast_debug(0, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len);
01505 
01506    if (ast_test_flag(rtp, FLAG_3389_WARNING)) {
01507       struct sockaddr_in remote_address = { 0, };
01508 
01509       ast_rtp_instance_get_remote_address(instance, &remote_address);
01510 
01511       ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n",
01512          ast_inet_ntoa(remote_address.sin_addr));
01513       ast_set_flag(rtp, FLAG_3389_WARNING);
01514    }
01515 
01516    /* Must have at least one byte */
01517    if (!len)
01518       return NULL;
01519    if (len < 24) {
01520       rtp->f.data.ptr = rtp->rawdata + AST_FRIENDLY_OFFSET;
01521       rtp->f.datalen = len - 1;
01522       rtp->f.offset = AST_FRIENDLY_OFFSET;
01523       memcpy(rtp->f.data.ptr, data + 1, len - 1);
01524    } else {
01525       rtp->f.data.ptr = NULL;
01526       rtp->f.offset = 0;
01527       rtp->f.datalen = 0;
01528    }
01529    rtp->f.frametype = AST_FRAME_CNG;
01530    rtp->f.subclass = data[0] & 0x7f;
01531    rtp->f.datalen = len - 1;
01532    rtp->f.samples = 0;
01533    rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0;
01534 
01535    return &rtp->f;
01536 }

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

Definition at line 1418 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, ast_rtp::dtmf_timeout, ast_rtp::dtmfsamples, f, ast_rtp::flags, option_debug, ast_rtp::resp, rtp_get_rate(), ast_frame::samples, send_dtmf(), seq, and ast_frame::subclass.

Referenced by ast_rtp_read().

01419 {
01420    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
01421    unsigned int event, flags, power;
01422    char resp = 0;
01423    unsigned char seq;
01424    struct ast_frame *f = NULL;
01425 
01426    if (len < 4) {
01427       return NULL;
01428    }
01429 
01430    /*      The format of Cisco RTP DTMF packet looks like next:
01431       +0                              - sequence number of DTMF RTP packet (begins from 1,
01432                     wrapped to 0)
01433       +1                              - set of flags
01434       +1 (bit 0)              - flaps by different DTMF digits delimited by audio
01435                     or repeated digit without audio???
01436       +2 (+4,+6,...)  - power level? (rises from 0 to 32 at begin of tone
01437                     then falls to 0 at its end)
01438       +3 (+5,+7,...)  - detected DTMF digit (0..9,*,#,A-D,...)
01439       Repeated DTMF information (bytes 4/5, 6/7) is history shifted right
01440       by each new packet and thus provides some redudancy.
01441 
01442       Sample of Cisco RTP DTMF packet is (all data in hex):
01443          19 07 00 02 12 02 20 02
01444       showing end of DTMF digit '2'.
01445 
01446       The packets
01447          27 07 00 02 0A 02 20 02
01448          28 06 20 02 00 02 0A 02
01449       shows begin of new digit '2' with very short pause (20 ms) after
01450       previous digit '2'. Bit +1.0 flips at begin of new digit.
01451 
01452       Cisco RTP DTMF packets comes as replacement of audio RTP packets
01453       so its uses the same sequencing and timestamping rules as replaced
01454       audio packets. Repeat interval of DTMF packets is 20 ms and not rely
01455       on audio framing parameters. Marker bit isn't used within stream of
01456       DTMFs nor audio stream coming immediately after DTMF stream. Timestamps
01457       are not sequential at borders between DTMF and audio streams,
01458    */
01459 
01460    seq = data[0];
01461    flags = data[1];
01462    power = data[2];
01463    event = data[3] & 0x1f;
01464 
01465    if (option_debug > 2 || rtpdebug)
01466       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);
01467    if (event < 10) {
01468       resp = '0' + event;
01469    } else if (event < 11) {
01470       resp = '*';
01471    } else if (event < 12) {
01472       resp = '#';
01473    } else if (event < 16) {
01474       resp = 'A' + (event - 12);
01475    } else if (event < 17) {
01476       resp = 'X';
01477    }
01478    if ((!rtp->resp && power) || (rtp->resp && (rtp->resp != resp))) {
01479       rtp->resp = resp;
01480       /* Why we should care on DTMF compensation at reception? */
01481       if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE)) {
01482          f = send_dtmf(instance, AST_FRAME_DTMF_BEGIN, 0);
01483          rtp->dtmfsamples = 0;
01484       }
01485    } else if ((rtp->resp == resp) && !power) {
01486       f = send_dtmf(instance, AST_FRAME_DTMF_END, ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE));
01487       f->samples = rtp->dtmfsamples * (rtp_get_rate(f->subclass) / 1000);
01488       rtp->resp = 0;
01489    } else if (rtp->resp == resp)
01490       rtp->dtmfsamples += 20 * (rtp_get_rate(f->subclass) / 1000);
01491    rtp->dtmf_timeout = 0;
01492 
01493    return f;
01494 }

static struct ast_frame* process_dtmf_rfc2833 ( struct ast_rtp_instance instance,
unsigned char *  data,
int  len,
unsigned int  seqno,
unsigned int  timestamp,
struct sockaddr_in *  sin,
int  payloadtype,
int  mark 
) [static, read]

Definition at line 1310 of file res_rtp_asterisk.c.

References ast_debug, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), ast_rtp_instance_get_remote_address(), AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_samp2tv(), ast_tv(), ast_tvdiff_ms(), ast_verbose, ast_rtp::dtmf_duration, ast_rtp::dtmf_timeout, ast_rtp::dtmfsamples, f, ast_rtp::lastevent, ast_frame::len, LOG_DEBUG, option_debug, ast_rtp::resp, rtp_debug_test_addr(), rtp_get_rate(), send_dtmf(), and ast_frame::subclass.

Referenced by ast_rtp_read().

01311 {
01312    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
01313    struct sockaddr_in remote_address = { 0, };
01314    unsigned int event, event_end, samples;
01315    char resp = 0;
01316    struct ast_frame *f = NULL;
01317 
01318    ast_rtp_instance_get_remote_address(instance, &remote_address);
01319 
01320    /* Figure out event, event end, and samples */
01321    event = ntohl(*((unsigned int *)(data)));
01322    event >>= 24;
01323    event_end = ntohl(*((unsigned int *)(data)));
01324    event_end <<= 8;
01325    event_end >>= 24;
01326    samples = ntohl(*((unsigned int *)(data)));
01327    samples &= 0xFFFF;
01328 
01329    if (rtp_debug_test_addr(&remote_address)) {
01330       ast_verbose("Got  RTP RFC2833 from   %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u, mark %d, event %08x, end %d, duration %-5.5d) \n", ast_inet_ntoa(remote_address.sin_addr),
01331              ntohs(remote_address.sin_port), payloadtype, seqno, timestamp, len, (mark?1:0), event, ((event_end & 0x80)?1:0), samples);
01332    }
01333 
01334    /* Print out debug if turned on */
01335    if (rtpdebug || option_debug > 2)
01336       ast_debug(0, "- RTP 2833 Event: %08x (len = %d)\n", event, len);
01337 
01338    /* Figure out what digit was pressed */
01339    if (event < 10) {
01340       resp = '0' + event;
01341    } else if (event < 11) {
01342       resp = '*';
01343    } else if (event < 12) {
01344       resp = '#';
01345    } else if (event < 16) {
01346       resp = 'A' + (event - 12);
01347    } else if (event < 17) {        /* Event 16: Hook flash */
01348       resp = 'X';
01349    } else {
01350       /* Not a supported event */
01351       ast_log(LOG_DEBUG, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event);
01352       return &ast_null_frame;
01353    }
01354 
01355    if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE)) {
01356       if ((rtp->lastevent != timestamp) || (rtp->resp && rtp->resp != resp)) {
01357          rtp->resp = resp;
01358          rtp->dtmf_timeout = 0;
01359          f = send_dtmf(instance, AST_FRAME_DTMF_END, ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE));
01360          f->len = 0;
01361          rtp->lastevent = timestamp;
01362       }
01363    } else {
01364       /*  The duration parameter measures the complete
01365           duration of the event (from the beginning) - RFC2833.
01366           Account for the fact that duration is only 16 bits long
01367           (about 8 seconds at 8000 Hz) and can wrap is digit
01368           is hold for too long. */
01369       unsigned int new_duration = rtp->dtmf_duration;
01370       unsigned int last_duration = new_duration & 0xFFFF;
01371 
01372       if (last_duration > 64000 && samples < last_duration) {
01373          new_duration += 0xFFFF + 1;
01374       }
01375       new_duration = (new_duration & ~0xFFFF) | samples;
01376 
01377       if (event_end & 0x80) {
01378          /* End event */
01379          if ((rtp->lastevent != seqno) && rtp->resp) {
01380             rtp->dtmf_duration = new_duration;
01381             f = send_dtmf(instance, AST_FRAME_DTMF_END, 0);
01382             f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass)), ast_tv(0, 0));
01383             rtp->resp = 0;
01384             rtp->dtmf_duration = rtp->dtmf_timeout = 0;
01385          }
01386       } else {
01387          /* Begin/continuation */
01388 
01389          if (rtp->resp && rtp->resp != resp) {
01390             /* Another digit already began. End it */
01391             f = send_dtmf(instance, AST_FRAME_DTMF_END, 0);
01392             f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass)), ast_tv(0, 0));
01393             rtp->resp = 0;
01394             rtp->dtmf_duration = rtp->dtmf_timeout = 0;
01395          }
01396 
01397          if (rtp->resp) {
01398             /* Digit continues */
01399             rtp->dtmf_duration = new_duration;
01400          } else {
01401             /* New digit began */
01402             rtp->resp = resp;
01403             f = send_dtmf(instance, AST_FRAME_DTMF_BEGIN, 0);
01404             rtp->dtmf_duration = samples;
01405          }
01406 
01407          rtp->dtmf_timeout = timestamp + rtp->dtmf_duration + dtmftimeout;
01408       }
01409 
01410       rtp->lastevent = seqno;
01411    }
01412 
01413    rtp->dtmfsamples = samples;
01414 
01415    return f;
01416 }

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

Definition at line 1065 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().

01065                                                               {
01066    unsigned char *data = red->t140red.data.ptr;
01067    int len = 0;
01068    int i;
01069 
01070    /* replace most aged generation */
01071    if (red->len[0]) {
01072       for (i = 1; i < red->num_gen+1; i++)
01073          len += red->len[i];
01074 
01075       memmove(&data[red->hdrlen], &data[red->hdrlen+red->len[0]], len);
01076    }
01077 
01078    /* Store length of each generation and primary data length*/
01079    for (i = 0; i < red->num_gen; i++)
01080       red->len[i] = red->len[i+1];
01081    red->len[i] = red->t140.datalen;
01082 
01083    /* write each generation length in red header */
01084    len = red->hdrlen;
01085    for (i = 0; i < red->num_gen; i++)
01086       len += data[i*4+3] = red->len[i];
01087 
01088    /* add primary data to buffer */
01089    memcpy(&data[len], red->t140.data.ptr, red->t140.datalen);
01090    red->t140red.datalen = len + red->t140.datalen;
01091 
01092    /* no primary data and no generations to send */
01093    if (len == red->hdrlen && !red->t140.datalen)
01094       return NULL;
01095 
01096    /* reset t.140 buffer */
01097    red->t140.datalen = 0;
01098 
01099    return &red->t140red;
01100 }

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

Write t140 redundacy frame.

Parameters:
data primary data to be buffered

Definition at line 2245 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().

02246 {
02247    struct ast_rtp_instance *instance = (struct ast_rtp_instance*) data;
02248    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02249 
02250    ast_rtp_write(instance, &rtp->red->t140);
02251 
02252    return 1;
02253 }

static int reload_module ( void   )  [static]

Definition at line 2633 of file res_rtp_asterisk.c.

References rtp_reload().

02634 {
02635    rtp_reload(1);
02636    return 0;
02637 }

static int rtcp_debug_test_addr ( struct sockaddr_in *  addr  )  [inline, static]

Definition at line 309 of file res_rtp_asterisk.c.

References rtcpdebugaddr.

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

00310 {
00311    if (!rtcpdebug) {
00312       return 0;
00313    }
00314 
00315    if (rtcpdebugaddr.sin_addr.s_addr) {
00316       if (((ntohs(rtcpdebugaddr.sin_port) != 0)
00317            && (rtcpdebugaddr.sin_port != addr->sin_port))
00318           || (rtcpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
00319          return 0;
00320    }
00321 
00322    return 1;
00323 }

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

Definition at line 2436 of file res_rtp_asterisk.c.

References ast_cli_args::argv, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), ast_strdupa, CLI_FAILURE, CLI_SUCCESS, ast_cli_args::fd, hp, and rtcpdebugaddr.

Referenced by handle_cli_rtcp_set_debug().

02437 {
02438    struct hostent *hp;
02439    struct ast_hostent ahp;
02440    int port = 0;
02441    char *p, *arg = ast_strdupa(a->argv[3]);
02442 
02443    p = strstr(arg, ":");
02444    if (p) {
02445       *p = '\0';
02446       p++;
02447       port = atoi(p);
02448    }
02449    hp = ast_gethostbyname(arg, &ahp);
02450    if (hp == NULL) {
02451       ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
02452       return CLI_FAILURE;
02453    }
02454    rtcpdebugaddr.sin_family = AF_INET;
02455    memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
02456    rtcpdebugaddr.sin_port = htons(port);
02457    if (port == 0)
02458       ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
02459    else
02460       ast_cli(a->fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
02461    rtcpdebug = 1;
02462    return CLI_SUCCESS;
02463 }

static int rtp_debug_test_addr ( struct sockaddr_in *  addr  )  [inline, static]

Definition at line 293 of file res_rtp_asterisk.c.

References rtpdebugaddr.

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

00294 {
00295    if (!rtpdebug) {
00296       return 0;
00297    }
00298 
00299    if (rtpdebugaddr.sin_addr.s_addr) {
00300       if (((ntohs(rtpdebugaddr.sin_port) != 0)
00301            && (rtpdebugaddr.sin_port != addr->sin_port))
00302           || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
00303          return 0;
00304    }
00305 
00306    return 1;
00307 }

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

Definition at line 2407 of file res_rtp_asterisk.c.

References ast_cli_args::argv, ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), ast_strdupa, CLI_FAILURE, CLI_SUCCESS, ast_cli_args::fd, hp, and rtpdebugaddr.

Referenced by handle_cli_rtp_set_debug().

02408 {
02409    struct hostent *hp;
02410    struct ast_hostent ahp;
02411    int port = 0;
02412    char *p, *arg = ast_strdupa(a->argv[4]);
02413 
02414    p = strstr(arg, ":");
02415    if (p) {
02416       *p = '\0';
02417       p++;
02418       port = atoi(p);
02419    }
02420    hp = ast_gethostbyname(arg, &ahp);
02421    if (hp == NULL) {
02422       ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
02423       return CLI_FAILURE;
02424    }
02425    rtpdebugaddr.sin_family = AF_INET;
02426    memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr));
02427    rtpdebugaddr.sin_port = htons(port);
02428    if (port == 0)
02429       ast_cli(a->fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr));
02430    else
02431       ast_cli(a->fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port);
02432    rtpdebug = 1;
02433    return CLI_SUCCESS;
02434 }

static int rtp_get_rate ( int  subclass  )  [static]

Definition at line 325 of file res_rtp_asterisk.c.

References AST_FORMAT_G722, and ast_format_rate().

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

00326 {
00327    return (subclass == AST_FORMAT_G722) ? 8000 : ast_format_rate(subclass);
00328 }

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

Definition at line 2290 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.

02291 {
02292    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02293 
02294    if (frame->datalen > -1) {
02295       struct rtp_red *red = rtp->red;
02296       memcpy(&red->buf_data[red->t140.datalen], frame->data.ptr, frame->datalen);
02297       red->t140.datalen += frame->datalen;
02298       red->t140.ts = frame->ts;
02299    }
02300 
02301    return 0;
02302 }

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

Definition at line 2255 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::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.

02256 {
02257    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02258    int x;
02259 
02260    if (!(rtp->red = ast_calloc(1, sizeof(*rtp->red)))) {
02261       return -1;
02262    }
02263 
02264    rtp->red->t140.frametype = AST_FRAME_TEXT;
02265    rtp->red->t140.subclass = AST_FORMAT_T140RED;
02266    rtp->red->t140.data.ptr = &rtp->red->buf_data;
02267 
02268    rtp->red->t140.ts = 0;
02269    rtp->red->t140red = rtp->red->t140;
02270    rtp->red->t140red.data.ptr = &rtp->red->t140red_data;
02271    rtp->red->t140red.datalen = 0;
02272    rtp->red->ti = buffer_time;
02273    rtp->red->num_gen = generations;
02274    rtp->red->hdrlen = generations * 4 + 1;
02275    rtp->red->prev_ts = 0;
02276 
02277    for (x = 0; x < generations; x++) {
02278       rtp->red->pt[x] = payloads[x];
02279       rtp->red->pt[x] |= 1 << 7; /* mark redundant generations pt */
02280       rtp->red->t140red_data[x*4] = rtp->red->pt[x];
02281    }
02282    rtp->red->t140red_data[x*4] = rtp->red->pt[x] = payloads[x]; /* primary pt */
02283    rtp->red->schedid = ast_sched_add(rtp->sched, generations, red_write, instance);
02284 
02285    rtp->red->t140.datalen = 0;
02286 
02287    return 0;
02288 }

static int rtp_reload ( int  reload  )  [static]

Definition at line 2564 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_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_DTMF_TIMEOUT, DEFAULT_RTP_END, DEFAULT_RTP_START, LOG_WARNING, MAXIMUM_RTP_PORT, MINIMUM_RTP_PORT, RTCP_MAX_INTERVALMS, RTCP_MIN_INTERVALMS, s, and STRICT_RTP_OPEN.

Referenced by load_module(), and reload_module().

02565 {
02566    struct ast_config *cfg;
02567    const char *s;
02568    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
02569 
02570    cfg = ast_config_load2("rtp.conf", "rtp", config_flags);
02571    if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
02572       return 0;
02573    }
02574 
02575    rtpstart = DEFAULT_RTP_START;
02576    rtpend = DEFAULT_RTP_END;
02577    dtmftimeout = DEFAULT_DTMF_TIMEOUT;
02578    strictrtp = STRICT_RTP_OPEN;
02579    if (cfg) {
02580       if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
02581          rtpstart = atoi(s);
02582          if (rtpstart < MINIMUM_RTP_PORT)
02583             rtpstart = MINIMUM_RTP_PORT;
02584          if (rtpstart > MAXIMUM_RTP_PORT)
02585             rtpstart = MAXIMUM_RTP_PORT;
02586       }
02587       if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
02588          rtpend = atoi(s);
02589          if (rtpend < MINIMUM_RTP_PORT)
02590             rtpend = MINIMUM_RTP_PORT;
02591          if (rtpend > MAXIMUM_RTP_PORT)
02592             rtpend = MAXIMUM_RTP_PORT;
02593       }
02594       if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
02595          rtcpinterval = atoi(s);
02596          if (rtcpinterval == 0)
02597             rtcpinterval = 0; /* Just so we're clear... it's zero */
02598          if (rtcpinterval < RTCP_MIN_INTERVALMS)
02599             rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
02600          if (rtcpinterval > RTCP_MAX_INTERVALMS)
02601             rtcpinterval = RTCP_MAX_INTERVALMS;
02602       }
02603       if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
02604 #ifdef SO_NO_CHECK
02605          nochecksums = ast_false(s) ? 1 : 0;
02606 #else
02607          if (ast_false(s))
02608             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
02609 #endif
02610       }
02611       if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
02612          dtmftimeout = atoi(s);
02613          if ((dtmftimeout < 0) || (dtmftimeout > 64000)) {
02614             ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
02615                dtmftimeout, DEFAULT_DTMF_TIMEOUT);
02616             dtmftimeout = DEFAULT_DTMF_TIMEOUT;
02617          };
02618       }
02619       if ((s = ast_variable_retrieve(cfg, "general", "strictrtp"))) {
02620          strictrtp = ast_true(s);
02621       }
02622       ast_config_destroy(cfg);
02623    }
02624    if (rtpstart >= rtpend) {
02625       ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
02626       rtpstart = DEFAULT_RTP_START;
02627       rtpend = DEFAULT_RTP_END;
02628    }
02629    ast_verb(2, "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
02630    return 0;
02631 }

static void sanitize_tv ( struct timeval *  tv  )  [static]

Definition at line 1215 of file res_rtp_asterisk.c.

Referenced by calc_rxstamp().

01216 {
01217    while (tv->tv_usec < 0) {
01218       tv->tv_usec += 1000000;
01219       tv->tv_sec -= 1;
01220    }
01221    while (tv->tv_usec >= 1000000) {
01222       tv->tv_usec -= 1000000;
01223       tv->tv_sec += 1;
01224    }
01225 }

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

Definition at line 1281 of file res_rtp_asterisk.c.

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

01282 {
01283    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
01284    struct sockaddr_in remote_address = { 0, };
01285 
01286    ast_rtp_instance_get_remote_address(instance, &remote_address);
01287 
01288    if (((compensate && type == AST_FRAME_DTMF_END) || (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) {
01289       ast_debug(1, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(remote_address.sin_addr));
01290       rtp->resp = 0;
01291       rtp->dtmfsamples = 0;
01292       return &ast_null_frame;
01293    }
01294    ast_debug(1, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(remote_address.sin_addr));
01295    if (rtp->resp == 'X') {
01296       rtp->f.frametype = AST_FRAME_CONTROL;
01297       rtp->f.subclass = AST_CONTROL_FLASH;
01298    } else {
01299       rtp->f.frametype = type;
01300       rtp->f.subclass = rtp->resp;
01301    }
01302    rtp->f.datalen = 0;
01303    rtp->f.samples = 0;
01304    rtp->f.mallocd = 0;
01305    rtp->f.src = "RTP";
01306 
01307    return &rtp->f;
01308 }

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

Definition at line 348 of file res_rtp_asterisk.c.

References SQUARE.

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

00349 {
00350 /*
00351       for the formula check http://www.cs.umd.edu/~austinjp/constSD.pdf
00352       return sqrt( (sample_count*pow(stddev,2) + sample_count*pow((sample-normdev)/(sample_count+1),2) + pow(sample-normdev_curent,2)) / (sample_count+1));
00353       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
00354       optimized formula
00355 */
00356 #define SQUARE(x) ((x) * (x))
00357 
00358    stddev = sample_count * stddev;
00359    sample_count++;
00360 
00361    return stddev +
00362       ( sample_count * SQUARE( (sample - normdev) / sample_count ) ) +
00363       ( SQUARE(sample - normdev_curent) / sample_count );
00364 
00365 #undef SQUARE
00366 }

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

Definition at line 689 of file res_rtp_asterisk.c.

References sec.

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

00690 {
00691    unsigned int sec, usec, frac;
00692    sec = tv.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */
00693    usec = tv.tv_usec;
00694    frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6);
00695    *msw = sec;
00696    *lsw = frac;
00697 }

static int unload_module ( void   )  [static]


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload_module, } [static]

Definition at line 2667 of file res_rtp_asterisk.c.

Definition at line 2667 of file res_rtp_asterisk.c.

Definition at line 271 of file res_rtp_asterisk.c.

struct ast_cli_entry cli_rtp[] [static]

Initial value:

 {
   AST_CLI_DEFINE(handle_cli_rtp_set_debug,  "Enable/Disable RTP debugging"),
   AST_CLI_DEFINE(handle_cli_rtcp_set_debug, "Enable/Disable RTCP debugging"),
   AST_CLI_DEFINE(handle_cli_rtcp_set_stats, "Enable/Disable RTCP stats"),
}

Definition at line 2558 of file res_rtp_asterisk.c.

int dtmftimeout = DEFAULT_DTMF_TIMEOUT [static]

Definition at line 79 of file res_rtp_asterisk.c.

int rtcpdebug [static]

Are we debugging RTCP?

Definition at line 84 of file res_rtp_asterisk.c.

struct sockaddr_in rtcpdebugaddr [static]

Debug RTCP packets to/from this host

Definition at line 88 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 86 of file res_rtp_asterisk.c.

int rtcpstats [static]

Are we debugging RTCP?

Definition at line 85 of file res_rtp_asterisk.c.

int rtpdebug [static]

Are we debugging?

Definition at line 83 of file res_rtp_asterisk.c.

struct sockaddr_in rtpdebugaddr [static]

Debug packets to/from this host

Definition at line 87 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 82 of file res_rtp_asterisk.c.

int rtpstart = DEFAULT_RTP_START [static]

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

Definition at line 81 of file res_rtp_asterisk.c.

int strictrtp [static]

Definition at line 92 of file res_rtp_asterisk.c.


Generated on Wed Oct 28 13:33:33 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6