Mon Oct 8 12:39:28 2012

Asterisk developer's documentation


res_rtp_asterisk.c File Reference

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

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

Go to the source code of this file.

Data Structures

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

Defines

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

Enumerations

enum  strict_rtp_state { STRICT_RTP_OPEN = 0, STRICT_RTP_LEARN, STRICT_RTP_CLOSED }

Functions

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

Variables

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

Referenced by rtp_reload().

#define DEFAULT_LEARNING_MIN_SEQUENTIAL   4

Definition at line 83 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 65 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 64 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

#define FLAG_3389_WARNING   (1 << 0)

Definition at line 110 of file res_rtp_asterisk.c.

Referenced by process_cn_rfc3389().

#define FLAG_DTMF_COMPENSATE   (1 << 4)

Definition at line 115 of file res_rtp_asterisk.c.

#define FLAG_NAT_ACTIVE   (3 << 1)

Definition at line 111 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 112 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 113 of file res_rtp_asterisk.c.

Referenced by ast_rtp_raw_write(), and bridge_p2p_rtp_write().

#define FLAG_NEED_MARKER_BIT   (1 << 3)

Definition at line 114 of file res_rtp_asterisk.c.

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

#define MAX_TIMESTAMP_SKEW   640

Definition at line 57 of file res_rtp_asterisk.c.

#define MAXIMUM_RTP_PORT   65535

Maximum port number to accept

Definition at line 68 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

#define MINIMUM_RTP_PORT   1024

Minimum port number to accept

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

#define RTCP_MAX_INTERVALMS   60000

Max milli-seconds between RTCP reports we send

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

Referenced by rtp_reload().

#define RTCP_PT_APP   204

Definition at line 75 of file res_rtp_asterisk.c.

#define RTCP_PT_BYE   203

Definition at line 74 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_read().

#define RTCP_PT_FUR   192

Definition at line 70 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_read().

#define RTCP_PT_RR   201

Definition at line 72 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_rr().

#define RTCP_PT_SDES   202

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

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

#define RTP_MTU   1200

Definition at line 77 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 59 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 81 of file res_rtp_asterisk.c.


Enumeration Type Documentation

enum strict_rtp_state

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

Definition at line 104 of file res_rtp_asterisk.c.

00104                       {
00105    STRICT_RTP_OPEN = 0, /*! No RTP packets should be dropped, all sources accepted */
00106    STRICT_RTP_LEARN,    /*! Accept next packet as source */
00107    STRICT_RTP_CLOSED,   /*! Drop all RTP packets not coming from source that was learned */
00108 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 3072 of file res_rtp_asterisk.c.

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

Definition at line 358 of file res_rtp_asterisk.c.

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

Referenced by rtcp_recvfrom(), and rtp_recvfrom().

00359 {
00360    int len;
00361    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00362    struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance);
00363 
00364    if ((len = ast_recvfrom(rtcp ? rtp->rtcp->s : rtp->s, buf, size, flags, sa)) < 0) {
00365       return len;
00366    }
00367 
00368    if (res_srtp && srtp && res_srtp->unprotect(srtp, buf, &len, rtcp) < 0) {
00369       return -1;
00370    }
00371 
00372    return len;
00373 }

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

Definition at line 385 of file res_rtp_asterisk.c.

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

Referenced by rtcp_sendto(), and rtp_sendto().

00386 {
00387    int len = size;
00388    void *temp = buf;
00389    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00390    struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance);
00391 
00392    if (res_srtp && srtp && res_srtp->protect(srtp, &temp, &len, rtcp) < 0) {
00393       return -1;
00394    }
00395 
00396    return ast_sendto(rtcp ? rtp->rtcp->s : rtp->s, temp, len, flags, sa);
00397 }

static void __unreg_module ( void   )  [static]

Definition at line 3072 of file res_rtp_asterisk.c.

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

Definition at line 414 of file res_rtp_asterisk.c.

Referenced by ast_rtp_raw_write(), and ast_rtp_read().

00415 {
00416    unsigned int interval;
00417    /*! \todo XXX Do a more reasonable calculation on this one
00418     * Look in RFC 3550 Section A.7 for an example*/
00419    interval = rtcpinterval;
00420    return interval;
00421 }

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

Definition at line 1773 of file res_rtp_asterisk.c.

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

Referenced by ast_rtp_read().

01774 {
01775    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
01776    struct ast_sockaddr addr;
01777    unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET];
01778    unsigned int *rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET);
01779    int res, packetwords, position = 0;
01780    struct ast_frame *f = &ast_null_frame;
01781 
01782    /* Read in RTCP data from the socket */
01783    if ((res = rtcp_recvfrom(instance, rtcpdata + AST_FRIENDLY_OFFSET,
01784             sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET,
01785             0, &addr)) < 0) {
01786       ast_assert(errno != EBADF);
01787       if (errno != EAGAIN) {
01788          ast_log(LOG_WARNING, "RTCP Read error: %s.  Hanging up.\n", strerror(errno));
01789          return NULL;
01790       }
01791       return &ast_null_frame;
01792    }
01793 
01794    packetwords = res / 4;
01795 
01796    if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT)) {
01797       /* Send to whoever sent to us */
01798       if (ast_sockaddr_cmp(&rtp->rtcp->them, &addr)) {
01799          ast_sockaddr_copy(&rtp->rtcp->them, &addr);
01800          if (option_debug || rtpdebug)
01801             ast_debug(0, "RTCP NAT: Got RTCP from other end. Now sending to address %s\n",
01802                  ast_sockaddr_stringify(&rtp->rtcp->them));
01803       }
01804    }
01805 
01806    ast_debug(1, "Got RTCP report of %d bytes\n", res);
01807 
01808    while (position < packetwords) {
01809       int i, pt, rc;
01810       unsigned int length, dlsr, lsr, msw, lsw, comp;
01811       struct timeval now;
01812       double rttsec, reported_jitter, reported_normdev_jitter_current, normdevrtt_current, reported_lost, reported_normdev_lost_current;
01813       uint64_t rtt = 0;
01814 
01815       i = position;
01816       length = ntohl(rtcpheader[i]);
01817       pt = (length & 0xff0000) >> 16;
01818       rc = (length & 0x1f000000) >> 24;
01819       length &= 0xffff;
01820 
01821       if ((i + length) > packetwords) {
01822          if (option_debug || rtpdebug)
01823             ast_log(LOG_DEBUG, "RTCP Read too short\n");
01824          return &ast_null_frame;
01825       }
01826 
01827       if (rtcp_debug_test_addr(&addr)) {
01828          ast_verbose("\n\nGot RTCP from %s\n",
01829                 ast_sockaddr_stringify(&addr));
01830          ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown");
01831          ast_verbose("Reception reports: %d\n", rc);
01832          ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]);
01833       }
01834 
01835       i += 2; /* Advance past header and ssrc */
01836       if (rc == 0 && pt == RTCP_PT_RR) {      /* We're receiving a receiver report with no reports, which is ok */
01837          position += (length + 1);
01838          continue;
01839       }
01840 
01841       switch (pt) {
01842       case RTCP_PT_SR:
01843          gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */
01844          rtp->rtcp->spc = ntohl(rtcpheader[i+3]);
01845          rtp->rtcp->soc = ntohl(rtcpheader[i + 4]);
01846          rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/
01847 
01848          if (rtcp_debug_test_addr(&addr)) {
01849             ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096);
01850             ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2]));
01851             ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4]));
01852          }
01853          i += 5;
01854          if (rc < 1)
01855             break;
01856          /* Intentional fall through */
01857       case RTCP_PT_RR:
01858          /* Don't handle multiple reception reports (rc > 1) yet */
01859          /* Calculate RTT per RFC */
01860          gettimeofday(&now, NULL);
01861          timeval2ntp(now, &msw, &lsw);
01862          if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */
01863             comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16);
01864             lsr = ntohl(rtcpheader[i + 4]);
01865             dlsr = ntohl(rtcpheader[i + 5]);
01866             rtt = comp - lsr - dlsr;
01867 
01868             /* Convert end to end delay to usec (keeping the calculation in 64bit space)
01869                sess->ee_delay = (eedelay * 1000) / 65536; */
01870             if (rtt < 4294) {
01871                rtt = (rtt * 1000000) >> 16;
01872             } else {
01873                rtt = (rtt * 1000) >> 16;
01874                rtt *= 1000;
01875             }
01876             rtt = rtt / 1000.;
01877             rttsec = rtt / 1000.;
01878             rtp->rtcp->rtt = rttsec;
01879 
01880             if (comp - dlsr >= lsr) {
01881                rtp->rtcp->accumulated_transit += rttsec;
01882 
01883                if (rtp->rtcp->rtt_count == 0)
01884                   rtp->rtcp->minrtt = rttsec;
01885 
01886                if (rtp->rtcp->maxrtt<rttsec)
01887                   rtp->rtcp->maxrtt = rttsec;
01888                if (rtp->rtcp->minrtt>rttsec)
01889                   rtp->rtcp->minrtt = rttsec;
01890 
01891                normdevrtt_current = normdev_compute(rtp->rtcp->normdevrtt, rttsec, rtp->rtcp->rtt_count);
01892 
01893                rtp->rtcp->stdevrtt = stddev_compute(rtp->rtcp->stdevrtt, rttsec, rtp->rtcp->normdevrtt, normdevrtt_current, rtp->rtcp->rtt_count);
01894 
01895                rtp->rtcp->normdevrtt = normdevrtt_current;
01896 
01897                rtp->rtcp->rtt_count++;
01898             } else if (rtcp_debug_test_addr(&addr)) {
01899                ast_verbose("Internal RTCP NTP clock skew detected: "
01900                         "lsr=%u, now=%u, dlsr=%u (%d:%03dms), "
01901                       "diff=%d\n",
01902                       lsr, comp, dlsr, dlsr / 65536,
01903                       (dlsr % 65536) * 1000 / 65536,
01904                       dlsr - (comp - lsr));
01905             }
01906          }
01907 
01908          rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]);
01909          reported_jitter = (double) rtp->rtcp->reported_jitter;
01910 
01911          if (rtp->rtcp->reported_jitter_count == 0)
01912             rtp->rtcp->reported_minjitter = reported_jitter;
01913 
01914          if (reported_jitter < rtp->rtcp->reported_minjitter)
01915             rtp->rtcp->reported_minjitter = reported_jitter;
01916 
01917          if (reported_jitter > rtp->rtcp->reported_maxjitter)
01918             rtp->rtcp->reported_maxjitter = reported_jitter;
01919 
01920          reported_normdev_jitter_current = normdev_compute(rtp->rtcp->reported_normdev_jitter, reported_jitter, rtp->rtcp->reported_jitter_count);
01921 
01922          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);
01923 
01924          rtp->rtcp->reported_normdev_jitter = reported_normdev_jitter_current;
01925 
01926          rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff;
01927 
01928          reported_lost = (double) rtp->rtcp->reported_lost;
01929 
01930          /* using same counter as for jitter */
01931          if (rtp->rtcp->reported_jitter_count == 0)
01932             rtp->rtcp->reported_minlost = reported_lost;
01933 
01934          if (reported_lost < rtp->rtcp->reported_minlost)
01935             rtp->rtcp->reported_minlost = reported_lost;
01936 
01937          if (reported_lost > rtp->rtcp->reported_maxlost)
01938             rtp->rtcp->reported_maxlost = reported_lost;
01939          reported_normdev_lost_current = normdev_compute(rtp->rtcp->reported_normdev_lost, reported_lost, rtp->rtcp->reported_jitter_count);
01940 
01941          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);
01942 
01943          rtp->rtcp->reported_normdev_lost = reported_normdev_lost_current;
01944 
01945          rtp->rtcp->reported_jitter_count++;
01946 
01947          if (rtcp_debug_test_addr(&addr)) {
01948             ast_verbose("  Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24));
01949             ast_verbose("  Packets lost so far: %d\n", rtp->rtcp->reported_lost);
01950             ast_verbose("  Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff));
01951             ast_verbose("  Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2])) >> 16);
01952             ast_verbose("  Interarrival jitter: %u\n", rtp->rtcp->reported_jitter);
01953             ast_verbose("  Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096);
01954             ast_verbose("  DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0);
01955             if (rtt)
01956                ast_verbose("  RTT: %lu(sec)\n", (unsigned long) rtt);
01957          }
01958          if (rtt) {
01959             manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From: %s\r\n"
01960                             "PT: %d(%s)\r\n"
01961                             "ReceptionReports: %d\r\n"
01962                             "SenderSSRC: %u\r\n"
01963                             "FractionLost: %ld\r\n"
01964                             "PacketsLost: %d\r\n"
01965                             "HighestSequence: %ld\r\n"
01966                             "SequenceNumberCycles: %ld\r\n"
01967                             "IAJitter: %u\r\n"
01968                             "LastSR: %lu.%010lu\r\n"
01969                             "DLSR: %4.4f(sec)\r\n"
01970                      "RTT: %llu(sec)\r\n",
01971                      ast_sockaddr_stringify(&addr),
01972                      pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
01973                      rc,
01974                      rtcpheader[i + 1],
01975                      (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24),
01976                      rtp->rtcp->reported_lost,
01977                      (long) (ntohl(rtcpheader[i + 2]) & 0xffff),
01978                      (long) (ntohl(rtcpheader[i + 2])) >> 16,
01979                      rtp->rtcp->reported_jitter,
01980                      (unsigned long) ntohl(rtcpheader[i + 4]) >> 16, ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096,
01981                      ntohl(rtcpheader[i + 5])/65536.0,
01982                      (unsigned long long)rtt);
01983          } else {
01984             manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From: %s\r\n"
01985                             "PT: %d(%s)\r\n"
01986                             "ReceptionReports: %d\r\n"
01987                             "SenderSSRC: %u\r\n"
01988                             "FractionLost: %ld\r\n"
01989                             "PacketsLost: %d\r\n"
01990                             "HighestSequence: %ld\r\n"
01991                             "SequenceNumberCycles: %ld\r\n"
01992                             "IAJitter: %u\r\n"
01993                             "LastSR: %lu.%010lu\r\n"
01994                      "DLSR: %4.4f(sec)\r\n",
01995                      ast_sockaddr_stringify(&addr),
01996                      pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
01997                      rc,
01998                      rtcpheader[i + 1],
01999                      (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24),
02000                      rtp->rtcp->reported_lost,
02001                      (long) (ntohl(rtcpheader[i + 2]) & 0xffff),
02002                      (long) (ntohl(rtcpheader[i + 2])) >> 16,
02003                      rtp->rtcp->reported_jitter,
02004                      (unsigned long) ntohl(rtcpheader[i + 4]) >> 16,
02005                      ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096,
02006                      ntohl(rtcpheader[i + 5])/65536.0);
02007          }
02008          break;
02009       case RTCP_PT_FUR:
02010          if (rtcp_debug_test_addr(&addr))
02011             ast_verbose("Received an RTCP Fast Update Request\n");
02012          rtp->f.frametype = AST_FRAME_CONTROL;
02013          rtp->f.subclass.integer = AST_CONTROL_VIDUPDATE;
02014          rtp->f.datalen = 0;
02015          rtp->f.samples = 0;
02016          rtp->f.mallocd = 0;
02017          rtp->f.src = "RTP";
02018          f = &rtp->f;
02019          break;
02020       case RTCP_PT_SDES:
02021          if (rtcp_debug_test_addr(&addr))
02022             ast_verbose("Received an SDES from %s\n",
02023                    ast_sockaddr_stringify(&rtp->rtcp->them));
02024          break;
02025       case RTCP_PT_BYE:
02026          if (rtcp_debug_test_addr(&addr))
02027             ast_verbose("Received a BYE from %s\n",
02028                    ast_sockaddr_stringify(&rtp->rtcp->them));
02029          break;
02030       default:
02031          ast_debug(1, "Unknown RTCP packet (pt=%d) received from %s\n",
02032               pt, ast_sockaddr_stringify(&rtp->rtcp->them));
02033          break;
02034       }
02035       position += (length + 1);
02036    }
02037 
02038    rtp->rtcp->rtcp_info = 1;
02039 
02040    return f;
02041 }

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

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

Referenced by ast_rtp_raw_write(), and ast_rtp_read().

01123 {
01124    struct ast_rtp_instance *instance = (struct ast_rtp_instance *) data;
01125    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
01126    int res;
01127 
01128    if (!rtp || !rtp->rtcp || rtp->rtcp->schedid == -1) {
01129       ao2_ref(instance, -1);
01130       return 0;
01131    }
01132 
01133    if (rtp->txcount > rtp->rtcp->lastsrtxcount) {
01134       res = ast_rtcp_write_sr(instance);
01135    } else {
01136       res = ast_rtcp_write_rr(instance);
01137    }
01138 
01139    if (!res) {
01140       /* 
01141        * Not being rescheduled.
01142        */
01143       ao2_ref(instance, -1);
01144       rtp->rtcp->schedid = -1;
01145    }
01146 
01147    return res;
01148 }

static int ast_rtcp_write_rr ( struct ast_rtp_instance instance  )  [static]

Send RTCP recipient's report.

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

Definition at line 890 of file res_rtp_asterisk.c.

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

Referenced by ast_rtcp_write().

00891 {
00892    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00893    int res;
00894    int len = 32;
00895    unsigned int lost;
00896    unsigned int extended;
00897    unsigned int expected;
00898    unsigned int expected_interval;
00899    unsigned int received_interval;
00900    int lost_interval;
00901    struct timeval now;
00902    unsigned int *rtcpheader;
00903    char bdata[1024];
00904    struct timeval dlsr;
00905    int fraction;
00906    int rate = rtp_get_rate(rtp->f.subclass.codec);
00907 
00908    double rxlost_current;
00909 
00910    if (!rtp || !rtp->rtcp)
00911       return 0;
00912 
00913    if (ast_sockaddr_isnull(&rtp->rtcp->them)) {
00914       /*
00915        * RTCP was stopped.
00916        */
00917       return 0;
00918    }
00919 
00920    extended = rtp->cycles + rtp->lastrxseqno;
00921    expected = extended - rtp->seedrxseqno + 1;
00922    lost = expected - rtp->rxcount;
00923    expected_interval = expected - rtp->rtcp->expected_prior;
00924    rtp->rtcp->expected_prior = expected;
00925    received_interval = rtp->rxcount - rtp->rtcp->received_prior;
00926    rtp->rtcp->received_prior = rtp->rxcount;
00927    lost_interval = expected_interval - received_interval;
00928 
00929    if (lost_interval <= 0)
00930       rtp->rtcp->rxlost = 0;
00931    else rtp->rtcp->rxlost = rtp->rtcp->rxlost;
00932    if (rtp->rtcp->rxlost_count == 0)
00933       rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
00934    if (lost_interval < rtp->rtcp->minrxlost)
00935       rtp->rtcp->minrxlost = rtp->rtcp->rxlost;
00936    if (lost_interval > rtp->rtcp->maxrxlost)
00937       rtp->rtcp->maxrxlost = rtp->rtcp->rxlost;
00938 
00939    rxlost_current = normdev_compute(rtp->rtcp->normdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->rxlost_count);
00940    rtp->rtcp->stdev_rxlost = stddev_compute(rtp->rtcp->stdev_rxlost, rtp->rtcp->rxlost, rtp->rtcp->normdev_rxlost, rxlost_current, rtp->rtcp->rxlost_count);
00941    rtp->rtcp->normdev_rxlost = rxlost_current;
00942    rtp->rtcp->rxlost_count++;
00943 
00944    if (expected_interval == 0 || lost_interval <= 0)
00945       fraction = 0;
00946    else
00947       fraction = (lost_interval << 8) / expected_interval;
00948    gettimeofday(&now, NULL);
00949    timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
00950    rtcpheader = (unsigned int *)bdata;
00951    rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_RR << 16) | ((len/4)-1));
00952    rtcpheader[1] = htonl(rtp->ssrc);
00953    rtcpheader[2] = htonl(rtp->themssrc);
00954    rtcpheader[3] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
00955    rtcpheader[4] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
00956    rtcpheader[5] = htonl((unsigned int)(rtp->rxjitter * rate));
00957    rtcpheader[6] = htonl(rtp->rtcp->themrxlsr);
00958    rtcpheader[7] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
00959 
00960    /*! \note Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos
00961      it can change mid call, and SDES can't) */
00962    rtcpheader[len/4]     = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
00963    rtcpheader[(len/4)+1] = htonl(rtp->ssrc);               /* Our SSRC */
00964    rtcpheader[(len/4)+2] = htonl(0x01 << 24);              /* Empty for the moment */
00965    len += 12;
00966 
00967    res = rtcp_sendto(instance, (unsigned int *)rtcpheader, len, 0, &rtp->rtcp->them);
00968 
00969    if (res < 0) {
00970       ast_log(LOG_ERROR, "RTCP RR transmission error, rtcp halted: %s\n",strerror(errno));
00971       return 0;
00972    }
00973 
00974    rtp->rtcp->rr_count++;
00975    if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
00976       ast_verbose("\n* Sending RTCP RR to %s\n"
00977          "  Our SSRC: %u\nTheir SSRC: %u\niFraction lost: %d\nCumulative loss: %u\n"
00978          "  IA jitter: %.4f\n"
00979          "  Their last SR: %u\n"
00980              "  DLSR: %4.4f (sec)\n\n",
00981              ast_sockaddr_stringify(&rtp->rtcp->them),
00982              rtp->ssrc, rtp->themssrc, fraction, lost,
00983              rtp->rxjitter,
00984              rtp->rtcp->themrxlsr,
00985              (double)(ntohl(rtcpheader[7])/65536.0));
00986    }
00987 
00988    return res;
00989 }

static int ast_rtcp_write_sr ( struct ast_rtp_instance instance  )  [static]

Send RTCP sender's report.

Definition at line 992 of file res_rtp_asterisk.c.

References ast_log(), ast_rtp_instance_get_data(), ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_verbose, ast_frame_subclass::codec, ast_rtp::cycles, errno, EVENT_FLAG_REPORTING, ast_rtcp::expected_prior, ast_rtp::f, ast_rtp::lastrxseqno, ast_rtcp::lastsrtxcount, ast_rtp::lastts, len(), LOG_ERROR, manager_event, ast_rtcp::received_prior, ast_rtp::rtcp, rtcp_debug_test_addr(), RTCP_PT_SDES, RTCP_PT_SR, rtcp_sendto(), rtp_get_rate(), ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtcp::rxlsr, ast_rtp::seedrxseqno, ast_rtcp::sr_count, ast_rtp::ssrc, ast_frame::subclass, 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().

00993 {
00994    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00995    int res;
00996    int len = 0;
00997    struct timeval now;
00998    unsigned int now_lsw;
00999    unsigned int now_msw;
01000    unsigned int *rtcpheader;
01001    unsigned int lost;
01002    unsigned int extended;
01003    unsigned int expected;
01004    unsigned int expected_interval;
01005    unsigned int received_interval;
01006    int lost_interval;
01007    int fraction;
01008    struct timeval dlsr;
01009    char bdata[512];
01010    int rate = rtp_get_rate(rtp->f.subclass.codec);
01011 
01012    if (!rtp || !rtp->rtcp)
01013       return 0;
01014 
01015    if (ast_sockaddr_isnull(&rtp->rtcp->them)) {  /* This'll stop rtcp for this rtp session */
01016       /*
01017        * RTCP was stopped.
01018        */
01019       return 0;
01020    }
01021 
01022    gettimeofday(&now, NULL);
01023    timeval2ntp(now, &now_msw, &now_lsw); /* fill thses ones in from utils.c*/
01024    rtcpheader = (unsigned int *)bdata;
01025    rtcpheader[1] = htonl(rtp->ssrc);               /* Our SSRC */
01026    rtcpheader[2] = htonl(now_msw);                 /* now, MSW. gettimeofday() + SEC_BETWEEN_1900_AND_1970*/
01027    rtcpheader[3] = htonl(now_lsw);                 /* now, LSW */
01028    rtcpheader[4] = htonl(rtp->lastts);             /* FIXME shouldn't be that, it should be now */
01029    rtcpheader[5] = htonl(rtp->txcount);            /* No. packets sent */
01030    rtcpheader[6] = htonl(rtp->txoctetcount);       /* No. bytes sent */
01031    len += 28;
01032 
01033    extended = rtp->cycles + rtp->lastrxseqno;
01034    expected = extended - rtp->seedrxseqno + 1;
01035    if (rtp->rxcount > expected)
01036       expected += rtp->rxcount - expected;
01037    lost = expected - rtp->rxcount;
01038    expected_interval = expected - rtp->rtcp->expected_prior;
01039    rtp->rtcp->expected_prior = expected;
01040    received_interval = rtp->rxcount - rtp->rtcp->received_prior;
01041    rtp->rtcp->received_prior = rtp->rxcount;
01042    lost_interval = expected_interval - received_interval;
01043    if (expected_interval == 0 || lost_interval <= 0)
01044       fraction = 0;
01045    else
01046       fraction = (lost_interval << 8) / expected_interval;
01047    timersub(&now, &rtp->rtcp->rxlsr, &dlsr);
01048    rtcpheader[7] = htonl(rtp->themssrc);
01049    rtcpheader[8] = htonl(((fraction & 0xff) << 24) | (lost & 0xffffff));
01050    rtcpheader[9] = htonl((rtp->cycles) | ((rtp->lastrxseqno & 0xffff)));
01051    rtcpheader[10] = htonl((unsigned int)(rtp->rxjitter * rate));
01052    rtcpheader[11] = htonl(rtp->rtcp->themrxlsr);
01053    rtcpheader[12] = htonl((((dlsr.tv_sec * 1000) + (dlsr.tv_usec / 1000)) * 65536) / 1000);
01054    len += 24;
01055 
01056    rtcpheader[0] = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SR << 16) | ((len/4)-1));
01057 
01058    /* Insert SDES here. Probably should make SDES text equal to mimetypes[code].type (not subtype 'cos */
01059    /* it can change mid call, and SDES can't) */
01060    rtcpheader[len/4]     = htonl((2 << 30) | (1 << 24) | (RTCP_PT_SDES << 16) | 2);
01061    rtcpheader[(len/4)+1] = htonl(rtp->ssrc);               /* Our SSRC */
01062    rtcpheader[(len/4)+2] = htonl(0x01 << 24);                    /* Empty for the moment */
01063    len += 12;
01064 
01065    res = rtcp_sendto(instance, (unsigned int *)rtcpheader, len, 0, &rtp->rtcp->them);
01066    if (res < 0) {
01067       ast_log(LOG_ERROR, "RTCP SR transmission error to %s, rtcp halted %s\n",
01068          ast_sockaddr_stringify(&rtp->rtcp->them),
01069          strerror(errno));
01070       return 0;
01071    }
01072 
01073    /* FIXME Don't need to get a new one */
01074    gettimeofday(&rtp->rtcp->txlsr, NULL);
01075    rtp->rtcp->sr_count++;
01076 
01077    rtp->rtcp->lastsrtxcount = rtp->txcount;
01078 
01079    if (rtcp_debug_test_addr(&rtp->rtcp->them)) {
01080       ast_verbose("* Sent RTCP SR to %s\n", ast_sockaddr_stringify(&rtp->rtcp->them));
01081       ast_verbose("  Our SSRC: %u\n", rtp->ssrc);
01082       ast_verbose("  Sent(NTP): %u.%010u\n", (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096);
01083       ast_verbose("  Sent(RTP): %u\n", rtp->lastts);
01084       ast_verbose("  Sent packets: %u\n", rtp->txcount);
01085       ast_verbose("  Sent octets: %u\n", rtp->txoctetcount);
01086       ast_verbose("  Report block:\n");
01087       ast_verbose("  Fraction lost: %u\n", fraction);
01088       ast_verbose("  Cumulative loss: %u\n", lost);
01089       ast_verbose("  IA jitter: %.4f\n", rtp->rxjitter);
01090       ast_verbose("  Their last SR: %u\n", rtp->rtcp->themrxlsr);
01091       ast_verbose("  DLSR: %4.4f (sec)\n\n", (double)(ntohl(rtcpheader[12])/65536.0));
01092    }
01093    manager_event(EVENT_FLAG_REPORTING, "RTCPSent", "To: %s\r\n"
01094                    "OurSSRC: %u\r\n"
01095                    "SentNTP: %u.%010u\r\n"
01096                    "SentRTP: %u\r\n"
01097                    "SentPackets: %u\r\n"
01098                    "SentOctets: %u\r\n"
01099                    "ReportBlock:\r\n"
01100                    "FractionLost: %u\r\n"
01101                    "CumulativeLoss: %u\r\n"
01102                    "IAJitter: %.4f\r\n"
01103                    "TheirLastSR: %u\r\n"
01104             "DLSR: %4.4f (sec)\r\n",
01105             ast_sockaddr_stringify(&rtp->rtcp->them),
01106             rtp->ssrc,
01107             (unsigned int)now.tv_sec, (unsigned int)now.tv_usec*4096,
01108             rtp->lastts,
01109             rtp->txcount,
01110             rtp->txoctetcount,
01111             fraction,
01112             lost,
01113             rtp->rxjitter,
01114             rtp->rtcp->themrxlsr,
01115             (double)(ntohl(rtcpheader[12])/65536.0));
01116    return res;
01117 }

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

Definition at line 2594 of file res_rtp_asterisk.c.

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

02595 {
02596    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02597 
02598    /* No need to futz with rtp->rtcp here because ast_rtcp_read is already able to adjust if receiving
02599     * RTCP from an "unexpected" source
02600     */
02601    ast_sockaddr_copy(&rtp->alt_rtp_address, addr);
02602 
02603    return;
02604 }

static void ast_rtp_change_source ( struct ast_rtp_instance instance  )  [static]

Definition at line 834 of file res_rtp_asterisk.c.

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

00835 {
00836    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00837    struct ast_srtp *srtp = ast_rtp_instance_get_srtp(instance);
00838    unsigned int ssrc = ast_random();
00839 
00840    if (!rtp->lastts) {
00841       ast_debug(3, "Not changing SSRC since we haven't sent any RTP yet\n");
00842       return;
00843    }
00844 
00845    /* We simply set this bit so that the next packet sent will have the marker bit turned on */
00846    ast_set_flag(rtp, FLAG_NEED_MARKER_BIT);
00847 
00848    ast_debug(3, "Changing ssrc from %u to %u due to a source change\n", rtp->ssrc, ssrc);
00849 
00850    if (srtp) {
00851       ast_debug(3, "Changing ssrc for SRTP from %u to %u\n", rtp->ssrc, ssrc);
00852       res_srtp->change_source(srtp, rtp->ssrc, ssrc);
00853    }
00854 
00855    rtp->ssrc = ssrc;
00856 
00857    return;
00858 }

static int ast_rtp_destroy ( struct ast_rtp_instance instance  )  [static]

Definition at line 585 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, and ast_rtp::smoother.

00586 {
00587    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00588 
00589    /* Destroy the smoother that was smoothing out audio if present */
00590    if (rtp->smoother) {
00591       ast_smoother_free(rtp->smoother);
00592    }
00593 
00594    /* Close our own socket so we no longer get packets */
00595    if (rtp->s > -1) {
00596       close(rtp->s);
00597    }
00598 
00599    /* Destroy RTCP if it was being used */
00600    if (rtp->rtcp) {
00601       /*
00602        * It is not possible for there to be an active RTCP scheduler
00603        * entry at this point since it holds a reference to the
00604        * RTP instance while it's active.
00605        */
00606       close(rtp->rtcp->s);
00607       ast_free(rtp->rtcp);
00608    }
00609 
00610    /* Destroy RED if it was being used */
00611    if (rtp->red) {
00612       AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
00613       ast_free(rtp->red);
00614    }
00615 
00616    /* Finally destroy ourselves */
00617    ast_free(rtp);
00618 
00619    return 0;
00620 }

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

Definition at line 635 of file res_rtp_asterisk.c.

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

00636 {
00637    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00638    struct ast_sockaddr remote_address = { {0,} };
00639    int hdrlen = 12, res = 0, i = 0, payload = 101;
00640    char data[256];
00641    unsigned int *rtpheader = (unsigned int*)data;
00642 
00643    ast_rtp_instance_get_remote_address(instance, &remote_address);
00644 
00645    /* If we have no remote address information bail out now */
00646    if (ast_sockaddr_isnull(&remote_address)) {
00647       return -1;
00648    }
00649 
00650    /* Convert given digit into what we want to transmit */
00651    if ((digit <= '9') && (digit >= '0')) {
00652       digit -= '0';
00653    } else if (digit == '*') {
00654       digit = 10;
00655    } else if (digit == '#') {
00656       digit = 11;
00657    } else if ((digit >= 'A') && (digit <= 'D')) {
00658       digit = digit - 'A' + 12;
00659    } else if ((digit >= 'a') && (digit <= 'd')) {
00660       digit = digit - 'a' + 12;
00661    } else {
00662       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
00663       return -1;
00664    }
00665 
00666    /* Grab the payload that they expect the RFC2833 packet to be received in */
00667    payload = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 0, AST_RTP_DTMF);
00668 
00669    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
00670    rtp->send_duration = 160;
00671    rtp->lastdigitts = rtp->lastts + rtp->send_duration;
00672 
00673    /* Create the actual packet that we will be sending */
00674    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
00675    rtpheader[1] = htonl(rtp->lastdigitts);
00676    rtpheader[2] = htonl(rtp->ssrc);
00677 
00678    /* Actually send the packet */
00679    for (i = 0; i < 2; i++) {
00680       rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
00681       res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, &remote_address);
00682       if (res < 0) {
00683          ast_log(LOG_ERROR, "RTP Transmission error to %s: %s\n",
00684             ast_sockaddr_stringify(&remote_address),
00685             strerror(errno));
00686       }
00687       if (rtp_debug_test_addr(&remote_address)) {
00688          ast_verbose("Sent RTP DTMF packet to %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
00689                 ast_sockaddr_stringify(&remote_address),
00690                 payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
00691       }
00692       rtp->seqno++;
00693       rtp->send_duration += 160;
00694       rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
00695    }
00696 
00697    /* Record that we are in the process of sending a digit and information needed to continue doing so */
00698    rtp->sending_digit = 1;
00699    rtp->send_digit = digit;
00700    rtp->send_payload = payload;
00701 
00702    return 0;
00703 }

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

02726 {
02727    /* If both sides are not using the same method of DTMF transmission
02728     * (ie: one is RFC2833, other is INFO... then we can not do direct media.
02729     * --------------------------------------------------
02730     * | DTMF Mode |  HAS_DTMF  |  Accepts Begin Frames |
02731     * |-----------|------------|-----------------------|
02732     * | Inband    | False      | True                  |
02733     * | RFC2833   | True       | True                  |
02734     * | SIP INFO  | False      | False                 |
02735     * --------------------------------------------------
02736     */
02737    return (((ast_rtp_instance_get_prop(instance0, AST_RTP_PROPERTY_DTMF) != ast_rtp_instance_get_prop(instance1, AST_RTP_PROPERTY_DTMF)) ||
02738        (!chan0->tech->send_digit_begin != !chan1->tech->send_digit_begin)) ? 0 : 1);
02739 }

static int ast_rtp_dtmf_continuation ( struct ast_rtp_instance instance  )  [static]

Definition at line 705 of file res_rtp_asterisk.c.

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

Referenced by ast_rtp_read().

00706 {
00707    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00708    struct ast_sockaddr remote_address = { {0,} };
00709    int hdrlen = 12, res = 0;
00710    char data[256];
00711    unsigned int *rtpheader = (unsigned int*)data;
00712 
00713    ast_rtp_instance_get_remote_address(instance, &remote_address);
00714 
00715    /* Make sure we know where the other side is so we can send them the packet */
00716    if (ast_sockaddr_isnull(&remote_address)) {
00717       return -1;
00718    }
00719 
00720    /* Actually create the packet we will be sending */
00721    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
00722    rtpheader[1] = htonl(rtp->lastdigitts);
00723    rtpheader[2] = htonl(rtp->ssrc);
00724    rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration));
00725    rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
00726 
00727    /* Boom, send it on out */
00728    res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, &remote_address);
00729    if (res < 0) {
00730       ast_log(LOG_ERROR, "RTP Transmission error to %s: %s\n",
00731          ast_sockaddr_stringify(&remote_address),
00732          strerror(errno));
00733    }
00734 
00735    if (rtp_debug_test_addr(&remote_address)) {
00736       ast_verbose("Sent RTP DTMF packet to %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
00737              ast_sockaddr_stringify(&remote_address),
00738              rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
00739    }
00740 
00741    /* And now we increment some values for the next time we swing by */
00742    rtp->seqno++;
00743    rtp->send_duration += 160;
00744 
00745    return 0;
00746 }

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

Definition at line 818 of file res_rtp_asterisk.c.

References ast_rtp_dtmf_end_with_duration().

00819 {
00820    return ast_rtp_dtmf_end_with_duration(instance, digit, 0);
00821 }

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

Definition at line 748 of file res_rtp_asterisk.c.

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

Referenced by ast_rtp_dtmf_end().

00749 {
00750    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00751    struct ast_sockaddr remote_address = { {0,} };
00752    int hdrlen = 12, res = 0, i = 0;
00753    char data[256];
00754    unsigned int *rtpheader = (unsigned int*)data;
00755    unsigned int measured_samples;
00756 
00757    ast_rtp_instance_get_remote_address(instance, &remote_address);
00758 
00759    /* Make sure we know where the remote side is so we can send them the packet we construct */
00760    if (ast_sockaddr_isnull(&remote_address)) {
00761       return -1;
00762    }
00763 
00764    /* Convert the given digit to the one we are going to send */
00765    if ((digit <= '9') && (digit >= '0')) {
00766       digit -= '0';
00767    } else if (digit == '*') {
00768       digit = 10;
00769    } else if (digit == '#') {
00770       digit = 11;
00771    } else if ((digit >= 'A') && (digit <= 'D')) {
00772       digit = digit - 'A' + 12;
00773    } else if ((digit >= 'a') && (digit <= 'd')) {
00774       digit = digit - 'a' + 12;
00775    } else {
00776       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
00777       return -1;
00778    }
00779 
00780    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
00781 
00782    if (duration > 0 && (measured_samples = duration * rtp_get_rate(rtp->f.subclass.codec) / 1000) > rtp->send_duration) {
00783       ast_debug(2, "Adjusting final end duration from %u to %u\n", rtp->send_duration, measured_samples);
00784       rtp->send_duration = measured_samples;
00785    }
00786 
00787    /* Construct the packet we are going to send */
00788    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (rtp->send_payload << 16) | (rtp->seqno));
00789    rtpheader[1] = htonl(rtp->lastdigitts);
00790    rtpheader[2] = htonl(rtp->ssrc);
00791    rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
00792    rtpheader[3] |= htonl((1 << 23));
00793    rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
00794 
00795    /* Send it 3 times, that's the magical number */
00796    for (i = 0; i < 3; i++) {
00797       res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, &remote_address);
00798       if (res < 0) {
00799          ast_log(LOG_ERROR, "RTP Transmission error to %s: %s\n",
00800             ast_sockaddr_stringify(&remote_address),
00801             strerror(errno));
00802       }
00803       if (rtp_debug_test_addr(&remote_address)) {
00804          ast_verbose("Sent RTP DTMF packet to %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
00805                 ast_sockaddr_stringify(&remote_address),
00806                 rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
00807       }
00808    }
00809 
00810    /* Oh and we can't forget to turn off the stuff that says we are sending DTMF */
00811    rtp->lastts += rtp->send_duration;
00812    rtp->sending_digit = 0;
00813    rtp->send_digit = 0;
00814 
00815    return 0;
00816 }

static enum ast_rtp_dtmf_mode ast_rtp_dtmf_mode_get ( struct ast_rtp_instance instance  )  [static]

Definition at line 629 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data(), and ast_rtp::dtmfmode.

00630 {
00631    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00632    return rtp->dtmfmode;
00633 }

static int ast_rtp_dtmf_mode_set ( struct ast_rtp_instance instance,
enum ast_rtp_dtmf_mode  dtmf_mode 
) [static]

Definition at line 622 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data(), and ast_rtp::dtmfmode.

00623 {
00624    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00625    rtp->dtmfmode = dtmf_mode;
00626    return 0;
00627 }

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

Definition at line 2564 of file res_rtp_asterisk.c.

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

02565 {
02566    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02567 
02568    return rtcp ? (rtp->rtcp ? rtp->rtcp->s : -1) : rtp->s;
02569 }

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

02678 {
02679    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02680 
02681    if (!rtp->rtcp) {
02682       return -1;
02683    }
02684 
02685    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_TXCOUNT, -1, stats->txcount, rtp->txcount);
02686    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_RXCOUNT, -1, stats->rxcount, rtp->rxcount);
02687 
02688    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_TXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->txploss, rtp->rtcp->reported_lost);
02689    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);
02690    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MAXRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_maxrxploss, rtp->rtcp->reported_maxlost);
02691    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MINRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_minrxploss, rtp->rtcp->reported_minlost);
02692    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_normdevrxploss, rtp->rtcp->reported_normdev_lost);
02693    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_STDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_stdevrxploss, rtp->rtcp->reported_stdev_lost);
02694    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MAXRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_maxrxploss, rtp->rtcp->maxrxlost);
02695    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MINRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_minrxploss, rtp->rtcp->minrxlost);
02696    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_normdevrxploss, rtp->rtcp->normdev_rxlost);
02697    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_STDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_stdevrxploss, rtp->rtcp->stdev_rxlost);
02698    AST_RTP_STAT_TERMINATOR(AST_RTP_INSTANCE_STAT_COMBINED_LOSS);
02699 
02700    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_TXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->txjitter, rtp->rxjitter);
02701    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);
02702    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MAXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_maxjitter, rtp->rtcp->reported_maxjitter);
02703    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MINJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_minjitter, rtp->rtcp->reported_minjitter);
02704    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_normdevjitter, rtp->rtcp->reported_normdev_jitter);
02705    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_STDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_stdevjitter, rtp->rtcp->reported_stdev_jitter);
02706    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MAXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_maxjitter, rtp->rtcp->maxrxjitter);
02707    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MINJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_minjitter, rtp->rtcp->minrxjitter);
02708    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_normdevjitter, rtp->rtcp->normdev_rxjitter);
02709    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_STDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_stdevjitter, rtp->rtcp->stdev_rxjitter);
02710    AST_RTP_STAT_TERMINATOR(AST_RTP_INSTANCE_STAT_COMBINED_JITTER);
02711 
02712    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_RTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->rtt, rtp->rtcp->rtt);
02713    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_MAX_RTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->maxrtt, rtp->rtcp->maxrtt);
02714    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_MIN_RTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->minrtt, rtp->rtcp->minrtt);
02715    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_NORMDEVRTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->normdevrtt, rtp->rtcp->normdevrtt);
02716    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_STDEVRTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->stdevrtt, rtp->rtcp->stdevrtt);
02717    AST_RTP_STAT_TERMINATOR(AST_RTP_INSTANCE_STAT_COMBINED_RTT);
02718 
02719    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_SSRC, -1, stats->local_ssrc, rtp->ssrc);
02720    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_SSRC, -1, stats->remote_ssrc, rtp->themssrc);
02721 
02722    return 0;
02723 }

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

Definition at line 2668 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data(), ast_set_flag, and FLAG_NEED_MARKER_BIT.

02669 {
02670    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance0);
02671 
02672    ast_set_flag(rtp, FLAG_NEED_MARKER_BIT);
02673 
02674    return 0;
02675 }

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

Definition at line 518 of file res_rtp_asterisk.c.

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

00521 {
00522    struct ast_rtp *rtp = NULL;
00523    int x, startplace;
00524 
00525    /* Create a new RTP structure to hold all of our data */
00526    if (!(rtp = ast_calloc(1, sizeof(*rtp)))) {
00527       return -1;
00528    }
00529 
00530    /* Set default parameters on the newly created RTP structure */
00531    rtp->ssrc = ast_random();
00532    rtp->seqno = ast_random() & 0xffff;
00533    rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN);
00534    if (strictrtp) {
00535       rtp_learning_seq_init(rtp, (uint16_t)rtp->seqno);
00536    }
00537 
00538    /* Create a new socket for us to listen on and use */
00539    if ((rtp->s =
00540         create_new_socket("RTP",
00541                 ast_sockaddr_is_ipv4(addr) ? AF_INET  :
00542                 ast_sockaddr_is_ipv6(addr) ? AF_INET6 : -1)) < 0) {
00543       ast_debug(1, "Failed to create a new socket for RTP instance '%p'\n", instance);
00544       ast_free(rtp);
00545       return -1;
00546    }
00547 
00548    /* Now actually find a free RTP port to use */
00549    x = (rtpend == rtpstart) ? rtpstart : (ast_random() % (rtpend - rtpstart)) + rtpstart;
00550    x = x & ~1;
00551    startplace = x;
00552 
00553    for (;;) {
00554       ast_sockaddr_set_port(addr, x);
00555       /* Try to bind, this will tell us whether the port is available or not */
00556       if (!ast_bind(rtp->s, addr)) {
00557          ast_debug(1, "Allocated port %d for RTP instance '%p'\n", x, instance);
00558          ast_rtp_instance_set_local_address(instance, addr);
00559          break;
00560       }
00561 
00562       x += 2;
00563       if (x > rtpend) {
00564          x = (rtpstart + 1) & ~1;
00565       }
00566 
00567       /* See if we ran out of ports or if the bind actually failed because of something other than the address being in use */
00568       if (x == startplace || errno != EADDRINUSE) {
00569          ast_log(LOG_ERROR, "Oh dear... we couldn't allocate a port for RTP instance '%p'\n", instance);
00570          close(rtp->s);
00571          ast_free(rtp);
00572          return -1;
00573       }
00574    }
00575 
00576    /* Record any information we may need */
00577    rtp->sched = sched;
00578 
00579    /* Associate the RTP structure with the RTP instance and be done */
00580    ast_rtp_instance_set_data(instance, rtp);
00581 
00582    return 0;
00583 }

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

Definition at line 2495 of file res_rtp_asterisk.c.

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

02496 {
02497    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02498 
02499    if (property == AST_RTP_PROPERTY_RTCP) {
02500       if (value) {
02501          if (rtp->rtcp) {
02502             ast_debug(1, "Ignoring duplicate RTCP property on RTP instance '%p'\n", instance);
02503             return;
02504          }
02505          /* Setup RTCP to be activated on the next RTP write */
02506          if (!(rtp->rtcp = ast_calloc(1, sizeof(*rtp->rtcp)))) {
02507             return;
02508          }
02509 
02510          /* Grab the IP address and port we are going to use */
02511          ast_rtp_instance_get_local_address(instance, &rtp->rtcp->us);
02512          ast_sockaddr_set_port(&rtp->rtcp->us,
02513                      ast_sockaddr_port(&rtp->rtcp->us) + 1);
02514 
02515          if ((rtp->rtcp->s =
02516               create_new_socket("RTCP",
02517                       ast_sockaddr_is_ipv4(&rtp->rtcp->us) ?
02518                       AF_INET :
02519                       ast_sockaddr_is_ipv6(&rtp->rtcp->us) ?
02520                       AF_INET6 : -1)) < 0) {
02521             ast_debug(1, "Failed to create a new socket for RTCP on instance '%p'\n", instance);
02522             ast_free(rtp->rtcp);
02523             rtp->rtcp = NULL;
02524             return;
02525          }
02526 
02527          /* 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 */
02528          if (ast_bind(rtp->rtcp->s, &rtp->rtcp->us)) {
02529             ast_debug(1, "Failed to setup RTCP on RTP instance '%p'\n", instance);
02530             close(rtp->rtcp->s);
02531             ast_free(rtp->rtcp);
02532             rtp->rtcp = NULL;
02533             return;
02534          }
02535 
02536          ast_debug(1, "Setup RTCP on RTP instance '%p'\n", instance);
02537          rtp->rtcp->schedid = -1;
02538 
02539          return;
02540       } else {
02541          if (rtp->rtcp) {
02542             if (rtp->rtcp->schedid > 0) {
02543                if (!ast_sched_del(rtp->sched, rtp->rtcp->schedid)) {
02544                   /* Successfully cancelled scheduler entry. */
02545                   ao2_ref(instance, -1);
02546                } else {
02547                   /* Unable to cancel scheduler entry */
02548                   ast_debug(1, "Failed to tear down RTCP on RTP instance '%p'\n", instance);
02549                   return;
02550                }
02551                rtp->rtcp->schedid = -1;
02552             }
02553             close(rtp->rtcp->s);
02554             ast_free(rtp->rtcp);
02555             rtp->rtcp = NULL;
02556          }
02557          return;
02558       }
02559    }
02560 
02561    return;
02562 }

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

Definition at line 2778 of file res_rtp_asterisk.c.

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

02779 {
02780    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02781 
02782    return ast_set_qos(rtp->s, tos, cos, desc);
02783 }

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

Definition at line 1150 of file res_rtp_asterisk.c.

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

Referenced by ast_rtp_write().

01151 {
01152    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
01153    int pred, mark = 0;
01154    unsigned int ms = calc_txstamp(rtp, &frame->delivery);
01155    struct ast_sockaddr remote_address = { {0,} };
01156    int rate = rtp_get_rate(frame->subclass.codec) / 1000;
01157 
01158    if (frame->subclass.codec == AST_FORMAT_G722) {
01159       frame->samples /= 2;
01160    }
01161 
01162    if (rtp->sending_digit) {
01163       return 0;
01164    }
01165 
01166    if (frame->frametype == AST_FRAME_VOICE) {
01167       pred = rtp->lastts + frame->samples;
01168 
01169       /* Re-calculate last TS */
01170       rtp->lastts = rtp->lastts + ms * rate;
01171       if (ast_tvzero(frame->delivery)) {
01172          /* If this isn't an absolute delivery time, Check if it is close to our prediction,
01173             and if so, go with our prediction */
01174          if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW) {
01175             rtp->lastts = pred;
01176          } else {
01177             ast_debug(3, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms);
01178             mark = 1;
01179          }
01180       }
01181    } else if (frame->frametype == AST_FRAME_VIDEO) {
01182       mark = frame->subclass.codec & 0x1;
01183       pred = rtp->lastovidtimestamp + frame->samples;
01184       /* Re-calculate last TS */
01185       rtp->lastts = rtp->lastts + ms * 90;
01186       /* If it's close to our prediction, go for it */
01187       if (ast_tvzero(frame->delivery)) {
01188          if (abs(rtp->lastts - pred) < 7200) {
01189             rtp->lastts = pred;
01190             rtp->lastovidtimestamp += frame->samples;
01191          } else {
01192             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);
01193             rtp->lastovidtimestamp = rtp->lastts;
01194          }
01195       }
01196    } else {
01197       pred = rtp->lastotexttimestamp + frame->samples;
01198       /* Re-calculate last TS */
01199       rtp->lastts = rtp->lastts + ms;
01200       /* If it's close to our prediction, go for it */
01201       if (ast_tvzero(frame->delivery)) {
01202          if (abs(rtp->lastts - pred) < 7200) {
01203             rtp->lastts = pred;
01204             rtp->lastotexttimestamp += frame->samples;
01205          } else {
01206             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);
01207             rtp->lastotexttimestamp = rtp->lastts;
01208          }
01209       }
01210    }
01211 
01212    /* If we have been explicitly told to set the marker bit then do so */
01213    if (ast_test_flag(rtp, FLAG_NEED_MARKER_BIT)) {
01214       mark = 1;
01215       ast_clear_flag(rtp, FLAG_NEED_MARKER_BIT);
01216    }
01217 
01218    /* If the timestamp for non-digt packets has moved beyond the timestamp for digits, update the digit timestamp */
01219    if (rtp->lastts > rtp->lastdigitts) {
01220       rtp->lastdigitts = rtp->lastts;
01221    }
01222 
01223    if (ast_test_flag(frame, AST_FRFLAG_HAS_TIMING_INFO)) {
01224       rtp->lastts = frame->ts * rate;
01225    }
01226 
01227    ast_rtp_instance_get_remote_address(instance, &remote_address);
01228 
01229    /* If we know the remote address construct a packet and send it out */
01230    if (!ast_sockaddr_isnull(&remote_address)) {
01231       int hdrlen = 12, res;
01232       unsigned char *rtpheader = (unsigned char *)(frame->data.ptr - hdrlen);
01233 
01234       put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23)));
01235       put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts));
01236       put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc));
01237 
01238       if ((res = rtp_sendto(instance, (void *)rtpheader, frame->datalen + hdrlen, 0, &remote_address)) < 0) {
01239          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))) {
01240             ast_debug(1, "RTP Transmission error of packet %d to %s: %s\n",
01241                  rtp->seqno,
01242                  ast_sockaddr_stringify(&remote_address),
01243                  strerror(errno));
01244          } else if (((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(rtp, FLAG_NAT_INACTIVE_NOWARN)) {
01245             /* Only give this error message once if we are not RTP debugging */
01246             if (option_debug || rtpdebug)
01247                ast_debug(0, "RTP NAT: Can't write RTP to private address %s, waiting for other end to send audio...\n",
01248                     ast_sockaddr_stringify(&remote_address));
01249             ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN);
01250          }
01251       } else {
01252          rtp->txcount++;
01253          rtp->txoctetcount += (res - hdrlen);
01254 
01255          if (rtp->rtcp && rtp->rtcp->schedid < 1) {
01256             ast_debug(1, "Starting RTCP transmission on RTP instance '%p'\n", instance);
01257             ao2_ref(instance, +1);
01258             rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, instance);
01259             if (rtp->rtcp->schedid < 0) {
01260                ao2_ref(instance, -1);
01261                ast_log(LOG_WARNING, "scheduling RTCP transmission failed.\n");
01262             }
01263          }
01264       }
01265 
01266       if (rtp_debug_test_addr(&remote_address)) {
01267          ast_verbose("Sent RTP packet to      %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
01268                 ast_sockaddr_stringify(&remote_address),
01269                 codec, rtp->seqno, rtp->lastts, res - hdrlen);
01270       }
01271    }
01272 
01273    rtp->seqno++;
01274 
01275    return 0;
01276 }

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

Definition at line 2118 of file res_rtp_asterisk.c.

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

02119 {
02120    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02121    struct ast_sockaddr addr;
02122    int res, hdrlen = 12, version, payloadtype, padding, mark, ext, cc, prev_seqno;
02123    unsigned int *rtpheader = (unsigned int*)(rtp->rawdata + AST_FRIENDLY_OFFSET), seqno, ssrc, timestamp;
02124    struct ast_rtp_payload_type payload;
02125    struct ast_sockaddr remote_address = { {0,} };
02126    struct frame_list frames;
02127 
02128    /* If this is actually RTCP let's hop on over and handle it */
02129    if (rtcp) {
02130       if (rtp->rtcp) {
02131          return ast_rtcp_read(instance);
02132       }
02133       return &ast_null_frame;
02134    }
02135 
02136    /* If we are currently sending DTMF to the remote party send a continuation packet */
02137    if (rtp->sending_digit) {
02138       ast_rtp_dtmf_continuation(instance);
02139    }
02140 
02141    /* Actually read in the data from the socket */
02142    if ((res = rtp_recvfrom(instance, rtp->rawdata + AST_FRIENDLY_OFFSET,
02143             sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET, 0,
02144             &addr)) < 0) {
02145       ast_assert(errno != EBADF);
02146       if (errno != EAGAIN) {
02147          ast_log(LOG_WARNING, "RTP Read error: %s. Hanging up.\n", strerror(errno));
02148          return NULL;
02149       }
02150       return &ast_null_frame;
02151    }
02152 
02153    /* Make sure the data that was read in is actually enough to make up an RTP packet */
02154    if (res < hdrlen) {
02155       ast_log(LOG_WARNING, "RTP Read too short\n");
02156       return &ast_null_frame;
02157    }
02158 
02159    /* If strict RTP protection is enabled see if we need to learn the remote address or if we need to drop the packet */
02160    if (rtp->strict_rtp_state == STRICT_RTP_LEARN) {
02161       ast_debug(1, "%p -- start learning mode pass with addr = %s\n", rtp, ast_sockaddr_stringify(&addr));
02162       /* For now, we always copy the address. */
02163       ast_sockaddr_copy(&rtp->strict_rtp_address, &addr);
02164 
02165       /* Send the rtp and the seqno from header to rtp_learning_rtp_seq_update to see whether we can exit or not*/
02166       if (rtp_learning_rtp_seq_update(rtp, ntohl(rtpheader[0]))) {
02167          ast_debug(1, "%p -- Condition for learning hasn't exited, so reject the frame.\n", rtp);
02168          return &ast_null_frame;
02169       }
02170 
02171       ast_debug(1, "%p -- Probation Ended. Set strict_rtp_state to STRICT_RTP_CLOSED with address %s\n", rtp, ast_sockaddr_stringify(&addr));
02172       rtp->strict_rtp_state = STRICT_RTP_CLOSED;
02173    } else if (rtp->strict_rtp_state == STRICT_RTP_CLOSED) {
02174       if (ast_sockaddr_cmp(&rtp->strict_rtp_address, &addr)) {
02175          /* Hmm, not the strict addres. Perhaps we're getting audio from the alternate? */
02176          if (!ast_sockaddr_cmp(&rtp->alt_rtp_address, &addr)) {
02177             /* ooh, we did! You're now the new expected address, son! */
02178             ast_sockaddr_copy(&rtp->strict_rtp_address,
02179                     &addr);
02180          } else  {
02181             const char *real_addr = ast_strdupa(ast_sockaddr_stringify(&addr));
02182             const char *expected_addr = ast_strdupa(ast_sockaddr_stringify(&rtp->strict_rtp_address));
02183 
02184             ast_debug(1, "Received RTP packet from %s, dropping due to strict RTP protection. Expected it to be from %s\n",
02185                   real_addr, expected_addr);
02186 
02187             return &ast_null_frame;
02188          }
02189       }
02190    }
02191 
02192    /* Get fields and verify this is an RTP packet */
02193    seqno = ntohl(rtpheader[0]);
02194 
02195    ast_rtp_instance_get_remote_address(instance, &remote_address);
02196 
02197    if (!(version = (seqno & 0xC0000000) >> 30)) {
02198       struct sockaddr_in addr_tmp;
02199       struct ast_sockaddr addr_v4;
02200       if (ast_sockaddr_is_ipv4(&addr)) {
02201          ast_sockaddr_to_sin(&addr, &addr_tmp);
02202       } else if (ast_sockaddr_ipv4_mapped(&addr, &addr_v4)) {
02203          ast_debug(1, "Using IPv6 mapped address %s for STUN\n",
02204               ast_sockaddr_stringify(&addr));
02205          ast_sockaddr_to_sin(&addr_v4, &addr_tmp);
02206       } else {
02207          ast_debug(1, "Cannot do STUN for non IPv4 address %s\n",
02208               ast_sockaddr_stringify(&addr));
02209          return &ast_null_frame;
02210       }
02211       if ((ast_stun_handle_packet(rtp->s, &addr_tmp, rtp->rawdata + AST_FRIENDLY_OFFSET, res, NULL, NULL) == AST_STUN_ACCEPT) &&
02212           ast_sockaddr_isnull(&remote_address)) {
02213          ast_sockaddr_from_sin(&addr, &addr_tmp);
02214          ast_rtp_instance_set_remote_address(instance, &addr);
02215       }
02216       return &ast_null_frame;
02217    }
02218 
02219    /* If symmetric RTP is enabled see if the remote side is not what we expected and change where we are sending audio */
02220    if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_NAT)) {
02221       if (ast_sockaddr_cmp(&remote_address, &addr)) {
02222          ast_rtp_instance_set_remote_address(instance, &addr);
02223          ast_sockaddr_copy(&remote_address, &addr);
02224          if (rtp->rtcp) {
02225             ast_sockaddr_copy(&rtp->rtcp->them, &addr);
02226             ast_sockaddr_set_port(&rtp->rtcp->them, ast_sockaddr_port(&addr) + 1);
02227          }
02228          rtp->rxseqno = 0;
02229          ast_set_flag(rtp, FLAG_NAT_ACTIVE);
02230          if (option_debug || rtpdebug)
02231             ast_debug(0, "RTP NAT: Got audio from other end. Now sending to address %s\n",
02232                  ast_sockaddr_stringify(&remote_address));
02233       }
02234    }
02235 
02236    /* If we are directly bridged to another instance send the audio directly out */
02237    if (ast_rtp_instance_get_bridged(instance) && !bridge_p2p_rtp_write(instance, rtpheader, res, hdrlen)) {
02238       return &ast_null_frame;
02239    }
02240 
02241    /* If the version is not what we expected by this point then just drop the packet */
02242    if (version != 2) {
02243       return &ast_null_frame;
02244    }
02245 
02246    /* Pull out the various other fields we will need */
02247    payloadtype = (seqno & 0x7f0000) >> 16;
02248    padding = seqno & (1 << 29);
02249    mark = seqno & (1 << 23);
02250    ext = seqno & (1 << 28);
02251    cc = (seqno & 0xF000000) >> 24;
02252    seqno &= 0xffff;
02253    timestamp = ntohl(rtpheader[1]);
02254    ssrc = ntohl(rtpheader[2]);
02255 
02256    AST_LIST_HEAD_INIT_NOLOCK(&frames);
02257    /* Force a marker bit and change SSRC if the SSRC changes */
02258    if (rtp->rxssrc && rtp->rxssrc != ssrc) {
02259       struct ast_frame *f, srcupdate = {
02260          AST_FRAME_CONTROL,
02261          .subclass.integer = AST_CONTROL_SRCCHANGE,
02262       };
02263 
02264       if (!mark) {
02265          if (option_debug || rtpdebug) {
02266             ast_debug(1, "Forcing Marker bit, because SSRC has changed\n");
02267          }
02268          mark = 1;
02269       }
02270 
02271       f = ast_frisolate(&srcupdate);
02272       AST_LIST_INSERT_TAIL(&frames, f, frame_list);
02273    }
02274 
02275    rtp->rxssrc = ssrc;
02276 
02277    /* Remove any padding bytes that may be present */
02278    if (padding) {
02279       res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1];
02280    }
02281 
02282    /* Skip over any CSRC fields */
02283    if (cc) {
02284       hdrlen += cc * 4;
02285    }
02286 
02287    /* Look for any RTP extensions, currently we do not support any */
02288    if (ext) {
02289       hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2;
02290       hdrlen += 4;
02291       if (option_debug) {
02292          int profile;
02293          profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16;
02294          if (profile == 0x505a)
02295             ast_debug(1, "Found Zfone extension in RTP stream - zrtp - not supported.\n");
02296          else
02297             ast_debug(1, "Found unknown RTP Extensions %x\n", profile);
02298       }
02299    }
02300 
02301    /* Make sure after we potentially mucked with the header length that it is once again valid */
02302    if (res < hdrlen) {
02303       ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d\n", res, hdrlen);
02304       return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame;
02305    }
02306 
02307    rtp->rxcount++;
02308    if (rtp->rxcount == 1) {
02309       rtp->seedrxseqno = seqno;
02310    }
02311 
02312    /* Do not schedule RR if RTCP isn't run */
02313    if (rtp->rtcp && !ast_sockaddr_isnull(&rtp->rtcp->them) && rtp->rtcp->schedid < 1) {
02314       /* Schedule transmission of Receiver Report */
02315       ao2_ref(instance, +1);
02316       rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, instance);
02317       if (rtp->rtcp->schedid < 0) {
02318          ao2_ref(instance, -1);
02319          ast_log(LOG_WARNING, "scheduling RTCP transmission failed.\n");
02320       }
02321    }
02322    if ((int)rtp->lastrxseqno - (int)seqno  > 100) /* if so it would indicate that the sender cycled; allow for misordering */
02323       rtp->cycles += RTP_SEQ_MOD;
02324 
02325    prev_seqno = rtp->lastrxseqno;
02326    rtp->lastrxseqno = seqno;
02327 
02328    if (!rtp->themssrc) {
02329       rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */
02330    }
02331 
02332    if (rtp_debug_test_addr(&addr)) {
02333       ast_verbose("Got  RTP packet from    %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02334              ast_sockaddr_stringify(&addr),
02335              payloadtype, seqno, timestamp,res - hdrlen);
02336    }
02337 
02338    payload = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(instance), payloadtype);
02339 
02340    /* If the payload is not actually an Asterisk one but a special one pass it off to the respective handler */
02341    if (!payload.asterisk_format) {
02342       struct ast_frame *f = NULL;
02343       if (payload.code == AST_RTP_DTMF) {
02344          /* process_dtmf_rfc2833 may need to return multiple frames. We do this
02345           * by passing the pointer to the frame list to it so that the method
02346           * can append frames to the list as needed.
02347           */
02348          process_dtmf_rfc2833(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &addr, payloadtype, mark, &frames);
02349       } else if (payload.code == AST_RTP_CISCO_DTMF) {
02350          f = process_dtmf_cisco(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &addr, payloadtype, mark);
02351       } else if (payload.code == AST_RTP_CN) {
02352          f = process_cn_rfc3389(instance, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &addr, payloadtype, mark);
02353       } else {
02354          ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n",
02355             payloadtype,
02356             ast_sockaddr_stringify(&remote_address));
02357       }
02358 
02359       if (f) {
02360          AST_LIST_INSERT_TAIL(&frames, f, frame_list);
02361       }
02362       /* Even if no frame was returned by one of the above methods,
02363        * we may have a frame to return in our frame list
02364        */
02365       if (!AST_LIST_EMPTY(&frames)) {
02366          return AST_LIST_FIRST(&frames);
02367       }
02368       return &ast_null_frame;
02369    }
02370 
02371    rtp->lastrxformat = rtp->f.subclass.codec = payload.code;
02372    rtp->f.frametype = (rtp->f.subclass.codec & AST_FORMAT_AUDIO_MASK) ? AST_FRAME_VOICE : (rtp->f.subclass.codec & AST_FORMAT_VIDEO_MASK) ? AST_FRAME_VIDEO : AST_FRAME_TEXT;
02373 
02374    rtp->rxseqno = seqno;
02375 
02376    if (rtp->dtmf_timeout && rtp->dtmf_timeout < timestamp) {
02377       rtp->dtmf_timeout = 0;
02378 
02379       if (rtp->resp) {
02380          struct ast_frame *f;
02381          f = create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0);
02382          f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass.codec)), ast_tv(0, 0));
02383          rtp->resp = 0;
02384          rtp->dtmf_timeout = rtp->dtmf_duration = 0;
02385          AST_LIST_INSERT_TAIL(&frames, f, frame_list);
02386          return AST_LIST_FIRST(&frames);
02387       }
02388    }
02389 
02390    rtp->lastrxts = timestamp;
02391 
02392    rtp->f.src = "RTP";
02393    rtp->f.mallocd = 0;
02394    rtp->f.datalen = res - hdrlen;
02395    rtp->f.data.ptr = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
02396    rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
02397    rtp->f.seqno = seqno;
02398 
02399    if (rtp->f.subclass.codec == AST_FORMAT_T140 && (int)seqno - (prev_seqno+1) > 0 && (int)seqno - (prev_seqno+1) < 10) {
02400       unsigned char *data = rtp->f.data.ptr;
02401 
02402       memmove(rtp->f.data.ptr+3, rtp->f.data.ptr, rtp->f.datalen);
02403       rtp->f.datalen +=3;
02404       *data++ = 0xEF;
02405       *data++ = 0xBF;
02406       *data = 0xBD;
02407    }
02408 
02409    if (rtp->f.subclass.codec == AST_FORMAT_T140RED) {
02410       unsigned char *data = rtp->f.data.ptr;
02411       unsigned char *header_end;
02412       int num_generations;
02413       int header_length;
02414       int len;
02415       int diff =(int)seqno - (prev_seqno+1); /* if diff = 0, no drop*/
02416       int x;
02417 
02418       rtp->f.subclass.codec = AST_FORMAT_T140;
02419       header_end = memchr(data, ((*data) & 0x7f), rtp->f.datalen);
02420       if (header_end == NULL) {
02421          return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame;
02422       }
02423       header_end++;
02424 
02425       header_length = header_end - data;
02426       num_generations = header_length / 4;
02427       len = header_length;
02428 
02429       if (!diff) {
02430          for (x = 0; x < num_generations; x++)
02431             len += data[x * 4 + 3];
02432 
02433          if (!(rtp->f.datalen - len))
02434             return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame;
02435 
02436          rtp->f.data.ptr += len;
02437          rtp->f.datalen -= len;
02438       } else if (diff > num_generations && diff < 10) {
02439          len -= 3;
02440          rtp->f.data.ptr += len;
02441          rtp->f.datalen -= len;
02442 
02443          data = rtp->f.data.ptr;
02444          *data++ = 0xEF;
02445          *data++ = 0xBF;
02446          *data = 0xBD;
02447       } else {
02448          for ( x = 0; x < num_generations - diff; x++)
02449             len += data[x * 4 + 3];
02450 
02451          rtp->f.data.ptr += len;
02452          rtp->f.datalen -= len;
02453       }
02454    }
02455 
02456    if (rtp->f.subclass.codec & AST_FORMAT_AUDIO_MASK) {
02457       rtp->f.samples = ast_codec_get_samples(&rtp->f);
02458       if ((rtp->f.subclass.codec == AST_FORMAT_SLINEAR) || (rtp->f.subclass.codec == AST_FORMAT_SLINEAR16)) {
02459          ast_frame_byteswap_be(&rtp->f);
02460       }
02461       calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
02462       /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */
02463       ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO);
02464       rtp->f.ts = timestamp / (rtp_get_rate(rtp->f.subclass.codec) / 1000);
02465       rtp->f.len = rtp->f.samples / ((ast_format_rate(rtp->f.subclass.codec) / 1000));
02466    } else if (rtp->f.subclass.codec & AST_FORMAT_VIDEO_MASK) {
02467       /* Video -- samples is # of samples vs. 90000 */
02468       if (!rtp->lastividtimestamp)
02469          rtp->lastividtimestamp = timestamp;
02470       rtp->f.samples = timestamp - rtp->lastividtimestamp;
02471       rtp->lastividtimestamp = timestamp;
02472       rtp->f.delivery.tv_sec = 0;
02473       rtp->f.delivery.tv_usec = 0;
02474       /* Pass the RTP marker bit as bit 0 in the subclass field.
02475        * This is ok because subclass is actually a bitmask, and
02476        * the low bits represent audio formats, that are not
02477        * involved here since we deal with video.
02478        */
02479       if (mark)
02480          rtp->f.subclass.codec |= 0x1;
02481    } else {
02482       /* TEXT -- samples is # of samples vs. 1000 */
02483       if (!rtp->lastitexttimestamp)
02484          rtp->lastitexttimestamp = timestamp;
02485       rtp->f.samples = timestamp - rtp->lastitexttimestamp;
02486       rtp->lastitexttimestamp = timestamp;
02487       rtp->f.delivery.tv_sec = 0;
02488       rtp->f.delivery.tv_usec = 0;
02489    }
02490 
02491    AST_LIST_INSERT_TAIL(&frames, &rtp->f, frame_list);
02492    return AST_LIST_FIRST(&frames);
02493 }

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

Definition at line 2571 of file res_rtp_asterisk.c.

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

02572 {
02573    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02574 
02575    if (rtp->rtcp) {
02576       ast_debug(1, "Setting RTCP address on RTP instance '%p'\n", instance);
02577       ast_sockaddr_copy(&rtp->rtcp->them, addr);
02578       if (!ast_sockaddr_isnull(addr)) {
02579          ast_sockaddr_set_port(&rtp->rtcp->them,
02580                      ast_sockaddr_port(addr) + 1);
02581       }
02582    }
02583 
02584    rtp->rxseqno = 0;
02585 
02586    if (strictrtp) {
02587       rtp->strict_rtp_state = STRICT_RTP_LEARN;
02588       rtp_learning_seq_init(rtp, rtp->seqno);
02589    }
02590 
02591    return;
02592 }

static int ast_rtp_sendcng ( struct ast_rtp_instance instance,
int  level 
) [static]

generate comfort noice (CNG)

Definition at line 2786 of file res_rtp_asterisk.c.

References ast_log(), AST_RTP_CN, ast_rtp_codecs_payload_lookup(), ast_rtp_instance_get_codecs(), ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address(), ast_sockaddr_isnull(), ast_sockaddr_stringify(), ast_tv(), ast_tvadd(), ast_tvnow(), ast_verbose, ast_rtp_payload_type::code, ast_rtp::dtmfmute, errno, ast_rtp::lastdigitts, ast_rtp::lastts, LOG_ERROR, rtp_debug_test_addr(), rtp_sendto(), ast_rtp::seqno, and ast_rtp::ssrc.

02787 {
02788    unsigned int *rtpheader;
02789    int hdrlen = 12;
02790    int res;
02791    struct ast_rtp_payload_type payload;
02792    char data[256];
02793    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02794    struct ast_sockaddr remote_address = { {0,} };
02795 
02796    ast_rtp_instance_get_remote_address(instance, &remote_address);
02797 
02798    if (ast_sockaddr_isnull(&remote_address)) {
02799       return -1;
02800    }
02801 
02802    payload = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(instance), AST_RTP_CN);
02803 
02804    level = 127 - (level & 0x7f);
02805    
02806    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
02807 
02808    /* Get a pointer to the header */
02809    rtpheader = (unsigned int *)data;
02810    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload.code << 16) | (rtp->seqno++));
02811    rtpheader[1] = htonl(rtp->lastts);
02812    rtpheader[2] = htonl(rtp->ssrc); 
02813    data[12] = level;
02814 
02815    res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 1, 0, &remote_address);
02816 
02817    if (res < 0) {
02818       ast_log(LOG_ERROR, "RTP Comfort Noise Transmission error to %s: %s\n", ast_sockaddr_stringify(&remote_address), strerror(errno));
02819    } else if (rtp_debug_test_addr(&remote_address)) {
02820       ast_verbose("Sent Comfort Noise RTP packet to %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02821             ast_sockaddr_stringify(&remote_address),
02822             AST_RTP_CN, rtp->seqno, rtp->lastdigitts, res - hdrlen);
02823    }
02824 
02825    return res;
02826 }

static void ast_rtp_stop ( struct ast_rtp_instance instance  )  [static]

Definition at line 2751 of file res_rtp_asterisk.c.

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

02752 {
02753    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02754    struct ast_sockaddr addr = { {0,} };
02755 
02756    if (rtp->rtcp && rtp->rtcp->schedid > 0) {
02757       if (!ast_sched_del(rtp->sched, rtp->rtcp->schedid)) {
02758          /* successfully cancelled scheduler entry. */
02759          ao2_ref(instance, -1);
02760       }
02761       rtp->rtcp->schedid = -1;
02762    }
02763 
02764    if (rtp->red) {
02765       AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
02766       free(rtp->red);
02767       rtp->red = NULL;
02768    }
02769 
02770    ast_rtp_instance_set_remote_address(instance, &addr);
02771    if (rtp->rtcp) {
02772       ast_sockaddr_setnull(&rtp->rtcp->them);
02773    }
02774 
02775    ast_set_flag(rtp, FLAG_NEED_MARKER_BIT);
02776 }

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

Definition at line 2741 of file res_rtp_asterisk.c.

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

02742 {
02743    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02744    struct sockaddr_in suggestion_tmp;
02745 
02746    ast_sockaddr_to_sin(suggestion, &suggestion_tmp);
02747    ast_stun_request(rtp->s, &suggestion_tmp, username, NULL);
02748    ast_sockaddr_from_sin(suggestion, &suggestion_tmp);
02749 }

static void ast_rtp_update_source ( struct ast_rtp_instance instance  )  [static]

Definition at line 823 of file res_rtp_asterisk.c.

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

00824 {
00825    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00826 
00827    /* We simply set this bit so that the next packet sent will have the marker bit turned on */
00828    ast_set_flag(rtp, FLAG_NEED_MARKER_BIT);
00829    ast_debug(3, "Setting the marker bit due to a source update\n");
00830 
00831    return;
00832 }

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

Definition at line 1315 of file res_rtp_asterisk.c.

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

Referenced by red_write().

01316 {
01317    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
01318    struct ast_sockaddr remote_address = { {0,} };
01319    format_t codec, subclass;
01320 
01321    ast_rtp_instance_get_remote_address(instance, &remote_address);
01322 
01323    /* If we don't actually know the remote address don't even bother doing anything */
01324    if (ast_sockaddr_isnull(&remote_address)) {
01325       ast_debug(1, "No remote address on RTP instance '%p' so dropping frame\n", instance);
01326       return 0;
01327    }
01328 
01329    /* If there is no data length we can't very well send the packet */
01330    if (!frame->datalen) {
01331       ast_debug(1, "Received frame with no data for RTP instance '%p' so dropping frame\n", instance);
01332       return 0;
01333    }
01334 
01335    /* If the packet is not one our RTP stack supports bail out */
01336    if (frame->frametype != AST_FRAME_VOICE && frame->frametype != AST_FRAME_VIDEO && frame->frametype != AST_FRAME_TEXT) {
01337       ast_log(LOG_WARNING, "RTP can only send voice, video, and text\n");
01338       return -1;
01339    }
01340 
01341    if (rtp->red) {
01342       /* return 0; */
01343       /* no primary data or generations to send */
01344       if ((frame = red_t140_to_red(rtp->red)) == NULL)
01345          return 0;
01346    }
01347 
01348    /* Grab the subclass and look up the payload we are going to use */
01349    subclass = frame->subclass.codec;
01350    if (frame->frametype == AST_FRAME_VIDEO) {
01351       subclass &= ~0x1LL;
01352    }
01353    if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, subclass)) < 0) {
01354       ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(frame->subclass.codec));
01355       return -1;
01356    }
01357 
01358    /* Oh dear, if the format changed we will have to set up a new smoother */
01359    if (rtp->lasttxformat != subclass) {
01360       ast_debug(1, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
01361       rtp->lasttxformat = subclass;
01362       if (rtp->smoother) {
01363          ast_smoother_free(rtp->smoother);
01364          rtp->smoother = NULL;
01365       }
01366    }
01367 
01368    /* If no smoother is present see if we have to set one up */
01369    if (!rtp->smoother) {
01370       struct ast_format_list fmt = ast_codec_pref_getsize(&ast_rtp_instance_get_codecs(instance)->pref, subclass);
01371 
01372       switch (subclass) {
01373       case AST_FORMAT_SPEEX:
01374       case AST_FORMAT_SPEEX16:
01375       case AST_FORMAT_G723_1:
01376       case AST_FORMAT_SIREN7:
01377       case AST_FORMAT_SIREN14:
01378       case AST_FORMAT_G719:
01379          /* these are all frame-based codecs and cannot be safely run through
01380             a smoother */
01381          break;
01382       default:
01383          if (fmt.inc_ms) {
01384             if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
01385                ast_log(LOG_WARNING, "Unable to create smoother: format %s ms: %d len: %d\n", ast_getformatname(subclass), fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
01386                return -1;
01387             }
01388             if (fmt.flags) {
01389                ast_smoother_set_flags(rtp->smoother, fmt.flags);
01390             }
01391             ast_debug(1, "Created smoother: format: %s ms: %d len: %d\n", ast_getformatname(subclass), fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
01392          }
01393       }
01394    }
01395 
01396    /* Feed audio frames into the actual function that will create a frame and send it */
01397    if (rtp->smoother) {
01398       struct ast_frame *f;
01399 
01400       if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) {
01401          ast_smoother_feed_be(rtp->smoother, frame);
01402       } else {
01403          ast_smoother_feed(rtp->smoother, frame);
01404       }
01405 
01406       while ((f = ast_smoother_read(rtp->smoother)) && (f->data.ptr)) {
01407             ast_rtp_raw_write(instance, f, codec);
01408       }
01409    } else {
01410       int hdrlen = 12;
01411       struct ast_frame *f = NULL;
01412 
01413       if (frame->offset < hdrlen) {
01414          f = ast_frdup(frame);
01415       } else {
01416          f = frame;
01417       }
01418       if (f->data.ptr) {
01419          ast_rtp_raw_write(instance, f, codec);
01420       }
01421       if (f != frame) {
01422          ast_frfree(f);
01423       }
01424 
01425    }
01426 
01427    return 0;
01428 }

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

Definition at line 2043 of file res_rtp_asterisk.c.

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

Referenced by ast_rtp_read().

02044 {
02045    struct ast_rtp_instance *instance1 = ast_rtp_instance_get_bridged(instance);
02046    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance), *bridged = ast_rtp_instance_get_data(instance1);
02047    int res = 0, payload = 0, bridged_payload = 0, mark;
02048    struct ast_rtp_payload_type payload_type;
02049    int reconstruct = ntohl(rtpheader[0]);
02050    struct ast_sockaddr remote_address = { {0,} };
02051 
02052    /* Get fields from packet */
02053    payload = (reconstruct & 0x7f0000) >> 16;
02054    mark = (((reconstruct & 0x800000) >> 23) != 0);
02055 
02056    /* Check what the payload value should be */
02057    payload_type = ast_rtp_codecs_payload_lookup(ast_rtp_instance_get_codecs(instance), payload);
02058 
02059    /* Otherwise adjust bridged payload to match */
02060    bridged_payload = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance1), payload_type.asterisk_format, payload_type.code);
02061 
02062    /* If no codec could be matched between instance and instance1, then somehow things were made incompatible while we were still bridged.  Bail. */
02063    if (bridged_payload < 0) {
02064       return -1;
02065    }
02066 
02067    /* 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 */
02068    if (!(ast_rtp_instance_get_codecs(instance1)->payloads[bridged_payload].code)) {
02069       return -1;
02070    }
02071 
02072    /* If the marker bit has been explicitly set turn it on */
02073    if (ast_test_flag(rtp, FLAG_NEED_MARKER_BIT)) {
02074       mark = 1;
02075       ast_clear_flag(rtp, FLAG_NEED_MARKER_BIT);
02076    }
02077 
02078    /* Reconstruct part of the packet */
02079    reconstruct &= 0xFF80FFFF;
02080    reconstruct |= (bridged_payload << 16);
02081    reconstruct |= (mark << 23);
02082    rtpheader[0] = htonl(reconstruct);
02083 
02084    ast_rtp_instance_get_remote_address(instance1, &remote_address);
02085 
02086    if (ast_sockaddr_isnull(&remote_address)) {
02087       ast_debug(1, "Remote address is null, most likely RTP has been stopped\n");
02088       return 0;
02089    }
02090 
02091    /* Send the packet back out */
02092    res = rtp_sendto(instance1, (void *)rtpheader, len, 0, &remote_address);
02093    if (res < 0) {
02094       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))) {
02095          ast_log(LOG_WARNING,
02096             "RTP Transmission error of packet to %s: %s\n",
02097             ast_sockaddr_stringify(&remote_address),
02098             strerror(errno));
02099       } else if (((ast_test_flag(bridged, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) && !ast_test_flag(bridged, FLAG_NAT_INACTIVE_NOWARN)) {
02100          if (option_debug || rtpdebug)
02101             ast_log(LOG_WARNING,
02102                "RTP NAT: Can't write RTP to private "
02103                "address %s, waiting for other end to "
02104                "send audio...\n",
02105                ast_sockaddr_stringify(&remote_address));
02106          ast_set_flag(bridged, FLAG_NAT_INACTIVE_NOWARN);
02107       }
02108       return 0;
02109    } else if (rtp_debug_test_addr(&remote_address)) {
02110       ast_verbose("Sent RTP P2P packet to %s (type %-2.2d, len %-6.6u)\n",
02111              ast_sockaddr_stringify(&remote_address),
02112              bridged_payload, len - hdrlen);
02113    }
02114 
02115    return 0;
02116 }

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

Definition at line 1430 of file res_rtp_asterisk.c.

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

01431 {
01432    struct timeval now;
01433    struct timeval tmp;
01434    double transit;
01435    double current_time;
01436    double d;
01437    double dtv;
01438    double prog;
01439    int rate = rtp_get_rate(rtp->f.subclass.codec);
01440 
01441    double normdev_rxjitter_current;
01442    if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) {
01443       gettimeofday(&rtp->rxcore, NULL);
01444       rtp->drxcore = (double) rtp->rxcore.tv_sec + (double) rtp->rxcore.tv_usec / 1000000;
01445       /* map timestamp to a real time */
01446       rtp->seedrxts = timestamp; /* Their RTP timestamp started with this */
01447       tmp = ast_samp2tv(timestamp, rate);
01448       rtp->rxcore = ast_tvsub(rtp->rxcore, tmp);
01449       /* Round to 0.1ms for nice, pretty timestamps */
01450       rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 100;
01451    }
01452 
01453    gettimeofday(&now,NULL);
01454    /* rxcore is the mapping between the RTP timestamp and _our_ real time from gettimeofday() */
01455    tmp = ast_samp2tv(timestamp, rate);
01456    *tv = ast_tvadd(rtp->rxcore, tmp);
01457 
01458    prog = (double)((timestamp-rtp->seedrxts)/(float)(rate));
01459    dtv = (double)rtp->drxcore + (double)(prog);
01460    current_time = (double)now.tv_sec + (double)now.tv_usec/1000000;
01461    transit = current_time - dtv;
01462    d = transit - rtp->rxtransit;
01463    rtp->rxtransit = transit;
01464    if (d<0)
01465       d=-d;
01466    rtp->rxjitter += (1./16.) * (d - rtp->rxjitter);
01467 
01468    if (rtp->rtcp) {
01469       if (rtp->rxjitter > rtp->rtcp->maxrxjitter)
01470          rtp->rtcp->maxrxjitter = rtp->rxjitter;
01471       if (rtp->rtcp->rxjitter_count == 1)
01472          rtp->rtcp->minrxjitter = rtp->rxjitter;
01473       if (rtp->rtcp && rtp->rxjitter < rtp->rtcp->minrxjitter)
01474          rtp->rtcp->minrxjitter = rtp->rxjitter;
01475 
01476       normdev_rxjitter_current = normdev_compute(rtp->rtcp->normdev_rxjitter,rtp->rxjitter,rtp->rtcp->rxjitter_count);
01477       rtp->rtcp->stdev_rxjitter = stddev_compute(rtp->rtcp->stdev_rxjitter,rtp->rxjitter,rtp->rtcp->normdev_rxjitter,normdev_rxjitter_current,rtp->rtcp->rxjitter_count);
01478 
01479       rtp->rtcp->normdev_rxjitter = normdev_rxjitter_current;
01480       rtp->rtcp->rxjitter_count++;
01481    }
01482 }

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

Definition at line 860 of file res_rtp_asterisk.c.

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

Referenced by ast_rtp_raw_write().

00861 {
00862    struct timeval t;
00863    long ms;
00864 
00865    if (ast_tvzero(rtp->txcore)) {
00866       rtp->txcore = ast_tvnow();
00867       rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
00868    }
00869 
00870    t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
00871    if ((ms = ast_tvdiff_ms(t, rtp->txcore)) < 0) {
00872       ms = 0;
00873    }
00874    rtp->txcore = t;
00875 
00876    return (unsigned int) ms;
00877 }

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

Definition at line 1484 of file res_rtp_asterisk.c.

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

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

01485 {
01486    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
01487    struct ast_sockaddr remote_address = { {0,} };
01488 
01489    ast_rtp_instance_get_remote_address(instance, &remote_address);
01490 
01491    if (((compensate && type == AST_FRAME_DTMF_END) || (type == AST_FRAME_DTMF_BEGIN)) && ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) {
01492       ast_debug(1, "Ignore potential DTMF echo from '%s'\n",
01493            ast_sockaddr_stringify(&remote_address));
01494       rtp->resp = 0;
01495       rtp->dtmfsamples = 0;
01496       return &ast_null_frame;
01497    }
01498    ast_debug(1, "Creating %s DTMF Frame: %d (%c), at %s\n",
01499       type == AST_FRAME_DTMF_END ? "END" : "BEGIN",
01500       rtp->resp, rtp->resp,
01501       ast_sockaddr_stringify(&remote_address));
01502    if (rtp->resp == 'X') {
01503       rtp->f.frametype = AST_FRAME_CONTROL;
01504       rtp->f.subclass.integer = AST_CONTROL_FLASH;
01505    } else {
01506       rtp->f.frametype = type;
01507       rtp->f.subclass.integer = rtp->resp;
01508    }
01509    rtp->f.datalen = 0;
01510    rtp->f.samples = 0;
01511    rtp->f.mallocd = 0;
01512    rtp->f.src = "RTP";
01513    AST_LIST_NEXT(&rtp->f, frame_list) = NULL;
01514 
01515    return &rtp->f;
01516 }

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

Definition at line 452 of file res_rtp_asterisk.c.

References ast_log(), errno, and LOG_WARNING.

Referenced by ast_rtp_new(), and ast_rtp_prop_set().

00453 {
00454    int sock = socket(af, SOCK_DGRAM, 0);
00455 
00456    if (sock < 0) {
00457       if (!type) {
00458          type = "RTP/RTCP";
00459       }
00460       ast_log(LOG_WARNING, "Unable to allocate %s socket: %s\n", type, strerror(errno));
00461    } else {
00462       long flags = fcntl(sock, F_GETFL);
00463       fcntl(sock, F_SETFL, flags | O_NONBLOCK);
00464 #ifdef SO_NO_CHECK
00465       if (nochecksums) {
00466          setsockopt(sock, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
00467       }
00468 #endif
00469    }
00470 
00471    return sock;
00472 }

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

Definition at line 2895 of file res_rtp_asterisk.c.

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

02896 {
02897    switch (cmd) {
02898    case CLI_INIT:
02899       e->command = "rtcp set debug {on|off|ip}";
02900       e->usage =
02901          "Usage: rtcp set debug {on|off|ip host[:port]}\n"
02902          "       Enable/Disable dumping of all RTCP packets. If 'ip' is\n"
02903          "       specified, limit the dumped packets to those to and from\n"
02904          "       the specified 'host' with optional port.\n";
02905       return NULL;
02906    case CLI_GENERATE:
02907       return NULL;
02908    }
02909 
02910    if (a->argc == e->args) { /* set on or off */
02911       if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
02912          rtcpdebug = 1;
02913          memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr));
02914          ast_cli(a->fd, "RTCP Debugging Enabled\n");
02915          return CLI_SUCCESS;
02916       } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
02917          rtcpdebug = 0;
02918          ast_cli(a->fd, "RTCP Debugging Disabled\n");
02919          return CLI_SUCCESS;
02920       }
02921    } else if (a->argc == e->args +1) { /* ip */
02922       return rtcp_do_debug_ip(a);
02923    }
02924 
02925    return CLI_SHOWUSAGE;   /* default, failure */
02926 }

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

Definition at line 2928 of file res_rtp_asterisk.c.

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

02929 {
02930    switch (cmd) {
02931    case CLI_INIT:
02932       e->command = "rtcp set stats {on|off}";
02933       e->usage =
02934          "Usage: rtcp set stats {on|off}\n"
02935          "       Enable/Disable dumping of RTCP stats.\n";
02936       return NULL;
02937    case CLI_GENERATE:
02938       return NULL;
02939    }
02940 
02941    if (a->argc != e->args)
02942       return CLI_SHOWUSAGE;
02943 
02944    if (!strncasecmp(a->argv[e->args-1], "on", 2))
02945       rtcpstats = 1;
02946    else if (!strncasecmp(a->argv[e->args-1], "off", 3))
02947       rtcpstats = 0;
02948    else
02949       return CLI_SHOWUSAGE;
02950 
02951    ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled");
02952    return CLI_SUCCESS;
02953 }

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

Definition at line 2862 of file res_rtp_asterisk.c.

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

02863 {
02864    switch (cmd) {
02865    case CLI_INIT:
02866       e->command = "rtp set debug {on|off|ip}";
02867       e->usage =
02868          "Usage: rtp set debug {on|off|ip host[:port]}\n"
02869          "       Enable/Disable dumping of all RTP packets. If 'ip' is\n"
02870          "       specified, limit the dumped packets to those to and from\n"
02871          "       the specified 'host' with optional port.\n";
02872       return NULL;
02873    case CLI_GENERATE:
02874       return NULL;
02875    }
02876 
02877    if (a->argc == e->args) { /* set on or off */
02878       if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
02879          rtpdebug = 1;
02880          memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr));
02881          ast_cli(a->fd, "RTP Debugging Enabled\n");
02882          return CLI_SUCCESS;
02883       } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
02884          rtpdebug = 0;
02885          ast_cli(a->fd, "RTP Debugging Disabled\n");
02886          return CLI_SUCCESS;
02887       }
02888    } else if (a->argc == e->args +1) { /* ip */
02889       return rtp_do_debug_ip(a);
02890    }
02891 
02892    return CLI_SHOWUSAGE;   /* default, failure */
02893 }

static int load_module ( void   )  [static]

Definition at line 3043 of file res_rtp_asterisk.c.

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

03044 {
03045    if (ast_rtp_engine_register(&asterisk_rtp_engine)) {
03046       return AST_MODULE_LOAD_DECLINE;
03047    }
03048 
03049    if (ast_cli_register_multiple(cli_rtp, ARRAY_LEN(cli_rtp))) {
03050       ast_rtp_engine_unregister(&asterisk_rtp_engine);
03051       return AST_MODULE_LOAD_DECLINE;
03052    }
03053 
03054    rtp_reload(0);
03055 
03056    return AST_MODULE_LOAD_SUCCESS;
03057 }

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

Calculate normal deviation.

Definition at line 424 of file res_rtp_asterisk.c.

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

00425 {
00426    normdev = normdev * sample_count + sample;
00427    sample_count++;
00428 
00429    return normdev / sample_count;
00430 }

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

Definition at line 1732 of file res_rtp_asterisk.c.

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

Referenced by ast_rtp_read().

01733 {
01734    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
01735 
01736    /* Convert comfort noise into audio with various codecs.  Unfortunately this doesn't
01737       totally help us out becuase we don't have an engine to keep it going and we are not
01738       guaranteed to have it every 20ms or anything */
01739    if (rtpdebug)
01740       ast_debug(0, "- RTP 3389 Comfort noise event: Level %" PRId64 " (len = %d)\n", rtp->lastrxformat, len);
01741 
01742    if (ast_test_flag(rtp, FLAG_3389_WARNING)) {
01743       struct ast_sockaddr remote_address = { {0,} };
01744 
01745       ast_rtp_instance_get_remote_address(instance, &remote_address);
01746 
01747       ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client address: %s\n",
01748          ast_sockaddr_stringify(&remote_address));
01749       ast_set_flag(rtp, FLAG_3389_WARNING);
01750    }
01751 
01752    /* Must have at least one byte */
01753    if (!len)
01754       return NULL;
01755    if (len < 24) {
01756       rtp->f.data.ptr = rtp->rawdata + AST_FRIENDLY_OFFSET;
01757       rtp->f.datalen = len - 1;
01758       rtp->f.offset = AST_FRIENDLY_OFFSET;
01759       memcpy(rtp->f.data.ptr, data + 1, len - 1);
01760    } else {
01761       rtp->f.data.ptr = NULL;
01762       rtp->f.offset = 0;
01763       rtp->f.datalen = 0;
01764    }
01765    rtp->f.frametype = AST_FRAME_CNG;
01766    rtp->f.subclass.integer = data[0] & 0x7f;
01767    rtp->f.samples = 0;
01768    rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0;
01769 
01770    return &rtp->f;
01771 }

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

Definition at line 1653 of file res_rtp_asterisk.c.

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

Referenced by ast_rtp_read().

01654 {
01655    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
01656    unsigned int event, flags, power;
01657    char resp = 0;
01658    unsigned char seq;
01659    struct ast_frame *f = NULL;
01660 
01661    if (len < 4) {
01662       return NULL;
01663    }
01664 
01665    /*      The format of Cisco RTP DTMF packet looks like next:
01666       +0                              - sequence number of DTMF RTP packet (begins from 1,
01667                     wrapped to 0)
01668       +1                              - set of flags
01669       +1 (bit 0)              - flaps by different DTMF digits delimited by audio
01670                     or repeated digit without audio???
01671       +2 (+4,+6,...)  - power level? (rises from 0 to 32 at begin of tone
01672                     then falls to 0 at its end)
01673       +3 (+5,+7,...)  - detected DTMF digit (0..9,*,#,A-D,...)
01674       Repeated DTMF information (bytes 4/5, 6/7) is history shifted right
01675       by each new packet and thus provides some redudancy.
01676 
01677       Sample of Cisco RTP DTMF packet is (all data in hex):
01678          19 07 00 02 12 02 20 02
01679       showing end of DTMF digit '2'.
01680 
01681       The packets
01682          27 07 00 02 0A 02 20 02
01683          28 06 20 02 00 02 0A 02
01684       shows begin of new digit '2' with very short pause (20 ms) after
01685       previous digit '2'. Bit +1.0 flips at begin of new digit.
01686 
01687       Cisco RTP DTMF packets comes as replacement of audio RTP packets
01688       so its uses the same sequencing and timestamping rules as replaced
01689       audio packets. Repeat interval of DTMF packets is 20 ms and not rely
01690       on audio framing parameters. Marker bit isn't used within stream of
01691       DTMFs nor audio stream coming immediately after DTMF stream. Timestamps
01692       are not sequential at borders between DTMF and audio streams,
01693    */
01694 
01695    seq = data[0];
01696    flags = data[1];
01697    power = data[2];
01698    event = data[3] & 0x1f;
01699 
01700    if (option_debug > 2 || rtpdebug)
01701       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);
01702    if (event < 10) {
01703       resp = '0' + event;
01704    } else if (event < 11) {
01705       resp = '*';
01706    } else if (event < 12) {
01707       resp = '#';
01708    } else if (event < 16) {
01709       resp = 'A' + (event - 12);
01710    } else if (event < 17) {
01711       resp = 'X';
01712    }
01713    if ((!rtp->resp && power) || (rtp->resp && (rtp->resp != resp))) {
01714       rtp->resp = resp;
01715       /* Why we should care on DTMF compensation at reception? */
01716       if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE)) {
01717          f = create_dtmf_frame(instance, AST_FRAME_DTMF_BEGIN, 0);
01718          rtp->dtmfsamples = 0;
01719       }
01720    } else if ((rtp->resp == resp) && !power) {
01721       f = create_dtmf_frame(instance, AST_FRAME_DTMF_END, ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE));
01722       f->samples = rtp->dtmfsamples * (rtp->lastrxformat ? (rtp_get_rate(rtp->lastrxformat) / 1000) : 8);
01723       rtp->resp = 0;
01724    } else if (rtp->resp == resp)
01725       rtp->dtmfsamples += 20 * (rtp->lastrxformat ? (rtp_get_rate(rtp->lastrxformat) / 1000) : 8);
01726 
01727    rtp->dtmf_timeout = 0;
01728 
01729    return f;
01730 }

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

Definition at line 1518 of file res_rtp_asterisk.c.

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

Referenced by ast_rtp_read().

01519 {
01520    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
01521    struct ast_sockaddr remote_address = { {0,} };
01522    unsigned int event, event_end, samples;
01523    char resp = 0;
01524    struct ast_frame *f = NULL;
01525 
01526    ast_rtp_instance_get_remote_address(instance, &remote_address);
01527 
01528    /* Figure out event, event end, and samples */
01529    event = ntohl(*((unsigned int *)(data)));
01530    event >>= 24;
01531    event_end = ntohl(*((unsigned int *)(data)));
01532    event_end <<= 8;
01533    event_end >>= 24;
01534    samples = ntohl(*((unsigned int *)(data)));
01535    samples &= 0xFFFF;
01536 
01537    if (rtp_debug_test_addr(&remote_address)) {
01538       ast_verbose("Got  RTP RFC2833 from   %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u, mark %d, event %08x, end %d, duration %-5.5d) \n",
01539              ast_sockaddr_stringify(&remote_address),
01540              payloadtype, seqno, timestamp, len, (mark?1:0), event, ((event_end & 0x80)?1:0), samples);
01541    }
01542 
01543    /* Print out debug if turned on */
01544    if (rtpdebug || option_debug > 2)
01545       ast_debug(0, "- RTP 2833 Event: %08x (len = %d)\n", event, len);
01546 
01547    /* Figure out what digit was pressed */
01548    if (event < 10) {
01549       resp = '0' + event;
01550    } else if (event < 11) {
01551       resp = '*';
01552    } else if (event < 12) {
01553       resp = '#';
01554    } else if (event < 16) {
01555       resp = 'A' + (event - 12);
01556    } else if (event < 17) {        /* Event 16: Hook flash */
01557       resp = 'X';
01558    } else {
01559       /* Not a supported event */
01560       ast_log(LOG_DEBUG, "Ignoring RTP 2833 Event: %08x. Not a DTMF Digit.\n", event);
01561       return;
01562    }
01563 
01564    if (ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE)) {
01565       if ((rtp->last_end_timestamp != timestamp) || (rtp->resp && rtp->resp != resp)) {
01566          rtp->resp = resp;
01567          rtp->dtmf_timeout = 0;
01568          f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_DTMF_COMPENSATE)));
01569          f->len = 0;
01570          rtp->last_end_timestamp = timestamp;
01571          AST_LIST_INSERT_TAIL(frames, f, frame_list);
01572       }
01573    } else {
01574       /*  The duration parameter measures the complete
01575           duration of the event (from the beginning) - RFC2833.
01576           Account for the fact that duration is only 16 bits long
01577           (about 8 seconds at 8000 Hz) and can wrap is digit
01578           is hold for too long. */
01579       unsigned int new_duration = rtp->dtmf_duration;
01580       unsigned int last_duration = new_duration & 0xFFFF;
01581 
01582       if (last_duration > 64000 && samples < last_duration) {
01583          new_duration += 0xFFFF + 1;
01584       }
01585       new_duration = (new_duration & ~0xFFFF) | samples;
01586 
01587       if (event_end & 0x80) {
01588          /* End event */
01589          if ((rtp->last_seqno != seqno) && (timestamp > rtp->last_end_timestamp)) {
01590             rtp->last_end_timestamp = timestamp;
01591             rtp->dtmf_duration = new_duration;
01592             rtp->resp = resp;
01593             f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0));
01594             f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass.codec)), ast_tv(0, 0));
01595             rtp->resp = 0;
01596             rtp->dtmf_duration = rtp->dtmf_timeout = 0;
01597             AST_LIST_INSERT_TAIL(frames, f, frame_list);
01598          } else if (rtpdebug) {
01599             ast_debug(1, "Dropping duplicate or out of order DTMF END frame (seqno: %d, ts %d, digit %c)\n",
01600                seqno, timestamp, resp);
01601          }
01602       } else {
01603          /* Begin/continuation */
01604 
01605          /* The second portion of the seqno check is to not mistakenly
01606           * stop accepting DTMF if the seqno rolls over beyond
01607           * 65535.
01608           */
01609          if ((rtp->last_seqno > seqno && rtp->last_seqno - seqno < 50)
01610             || timestamp <= rtp->last_end_timestamp) {
01611             /* Out of order frame. Processing this can cause us to
01612              * improperly duplicate incoming DTMF, so just drop
01613              * this.
01614              */
01615             if (rtpdebug) {
01616                ast_debug(1, "Dropping out of order DTMF frame (seqno %d, ts %d, digit %c)\n",
01617                   seqno, timestamp, resp);
01618             }
01619             return;
01620          }
01621 
01622          if (rtp->resp && rtp->resp != resp) {
01623             /* Another digit already began. End it */
01624             f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_END, 0));
01625             f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass.codec)), ast_tv(0, 0));
01626             rtp->resp = 0;
01627             rtp->dtmf_duration = rtp->dtmf_timeout = 0;
01628             AST_LIST_INSERT_TAIL(frames, f, frame_list);
01629          }
01630 
01631          if (rtp->resp) {
01632             /* Digit continues */
01633             rtp->dtmf_duration = new_duration;
01634          } else {
01635             /* New digit began */
01636             rtp->resp = resp;
01637             f = ast_frdup(create_dtmf_frame(instance, AST_FRAME_DTMF_BEGIN, 0));
01638             rtp->dtmf_duration = samples;
01639             AST_LIST_INSERT_TAIL(frames, f, frame_list);
01640          }
01641 
01642          rtp->dtmf_timeout = timestamp + rtp->dtmf_duration + dtmftimeout;
01643       }
01644 
01645       rtp->last_seqno = seqno;
01646    }
01647 
01648    rtp->dtmfsamples = samples;
01649 
01650    return;
01651 }

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

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

01278                                                               {
01279    unsigned char *data = red->t140red.data.ptr;
01280    int len = 0;
01281    int i;
01282 
01283    /* replace most aged generation */
01284    if (red->len[0]) {
01285       for (i = 1; i < red->num_gen+1; i++)
01286          len += red->len[i];
01287 
01288       memmove(&data[red->hdrlen], &data[red->hdrlen+red->len[0]], len);
01289    }
01290 
01291    /* Store length of each generation and primary data length*/
01292    for (i = 0; i < red->num_gen; i++)
01293       red->len[i] = red->len[i+1];
01294    red->len[i] = red->t140.datalen;
01295 
01296    /* write each generation length in red header */
01297    len = red->hdrlen;
01298    for (i = 0; i < red->num_gen; i++)
01299       len += data[i*4+3] = red->len[i];
01300 
01301    /* add primary data to buffer */
01302    memcpy(&data[len], red->t140.data.ptr, red->t140.datalen);
01303    red->t140red.datalen = len + red->t140.datalen;
01304 
01305    /* no primary data and no generations to send */
01306    if (len == red->hdrlen && !red->t140.datalen)
01307       return NULL;
01308 
01309    /* reset t.140 buffer */
01310    red->t140.datalen = 0;
01311 
01312    return &red->t140red;
01313 }

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

Write t140 redundacy frame.

Parameters:
data primary data to be buffered

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

02610 {
02611    struct ast_rtp_instance *instance = (struct ast_rtp_instance*) data;
02612    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02613 
02614    ast_rtp_write(instance, &rtp->red->t140);
02615 
02616    return 1;
02617 }

static int reload_module ( void   )  [static]

Definition at line 3037 of file res_rtp_asterisk.c.

References rtp_reload().

03038 {
03039    rtp_reload(1);
03040    return 0;
03041 }

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

Definition at line 342 of file res_rtp_asterisk.c.

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

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

00343 {
00344    if (!rtcpdebug) {
00345       return 0;
00346    }
00347    if (!ast_sockaddr_isnull(&rtcpdebugaddr)) {
00348       if (rtcpdebugport) {
00349          return (ast_sockaddr_cmp(&rtcpdebugaddr, addr) == 0); /* look for RTCP packets from IP+Port */
00350       } else {
00351          return (ast_sockaddr_cmp_addr(&rtcpdebugaddr, addr) == 0); /* only look for RTCP packets from IP */
00352       }
00353    }
00354 
00355    return 1;
00356 }

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

Definition at line 2845 of file res_rtp_asterisk.c.

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

Referenced by handle_cli_rtcp_set_debug().

02846 {
02847    char *arg = ast_strdupa(a->argv[4]);
02848    char *debughost = NULL;
02849    char *debugport = NULL;
02850 
02851    if (!ast_sockaddr_parse(&rtcpdebugaddr, arg, 0) || !ast_sockaddr_split_hostport(arg, &debughost, &debugport, 0)) {
02852       ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
02853       return CLI_FAILURE;
02854    }
02855    rtcpdebugport = (!ast_strlen_zero(debugport) && debugport[0] != '0');
02856    ast_cli(a->fd, "RTCP Debugging Enabled for address: %s\n",
02857       ast_sockaddr_stringify(&rtcpdebugaddr));
02858    rtcpdebug = 1;
02859    return CLI_SUCCESS;
02860 }

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

Definition at line 375 of file res_rtp_asterisk.c.

References __rtp_recvfrom().

Referenced by ast_rtcp_read().

00376 {
00377    return __rtp_recvfrom(instance, buf, size, flags, sa, 1);
00378 }

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

Definition at line 399 of file res_rtp_asterisk.c.

References __rtp_sendto().

Referenced by ast_rtcp_write_rr(), and ast_rtcp_write_sr().

00400 {
00401    return __rtp_sendto(instance, buf, size, flags, sa, 1);
00402 }

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

Definition at line 326 of file res_rtp_asterisk.c.

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

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

00327 {
00328    if (!rtpdebug) {
00329       return 0;
00330    }
00331    if (!ast_sockaddr_isnull(&rtpdebugaddr)) {
00332       if (rtpdebugport) {
00333          return (ast_sockaddr_cmp(&rtpdebugaddr, addr) == 0); /* look for RTP packets from IP+Port */
00334       } else {
00335          return (ast_sockaddr_cmp_addr(&rtpdebugaddr, addr) == 0); /* only look for RTP packets from IP */
00336       }
00337    }
00338 
00339    return 1;
00340 }

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

Definition at line 2828 of file res_rtp_asterisk.c.

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

Referenced by handle_cli_rtp_set_debug().

02829 {
02830    char *arg = ast_strdupa(a->argv[4]);
02831    char *debughost = NULL;
02832    char *debugport = NULL;
02833 
02834    if (!ast_sockaddr_parse(&rtpdebugaddr, arg, 0) || !ast_sockaddr_split_hostport(arg, &debughost, &debugport, 0)) {
02835       ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
02836       return CLI_FAILURE;
02837    }
02838    rtpdebugport = (!ast_strlen_zero(debugport) && debugport[0] != '0');
02839    ast_cli(a->fd, "RTP Debugging Enabled for address: %s\n",
02840       ast_sockaddr_stringify(&rtpdebugaddr));
02841    rtpdebug = 1;
02842    return CLI_SUCCESS;
02843 }

static int rtp_get_rate ( format_t  subclass  )  [static]

Definition at line 409 of file res_rtp_asterisk.c.

References AST_FORMAT_G722, and ast_format_rate().

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

00410 {
00411    return (subclass == AST_FORMAT_G722) ? 8000 : ast_format_rate(subclass);
00412 }

static int rtp_learning_rtp_seq_update ( struct ast_rtp rtp,
uint16_t  seq 
) [static]

Definition at line 497 of file res_rtp_asterisk.c.

References ast_debug, and ast_srtp::rtp.

Referenced by ast_rtp_read().

00498 {
00499    int probation = 1;
00500 
00501    ast_debug(1, "%p -- probation = %d, seq = %d\n", rtp, rtp->learning_probation, seq);
00502 
00503    if (seq == rtp->learning_max_seq + 1) {
00504       /* packet is in sequence */
00505       rtp->learning_probation--;
00506       rtp->learning_max_seq = seq;
00507       if (rtp->learning_probation == 0) {
00508          probation = 0;
00509       }
00510    } else {
00511       rtp->learning_probation = learning_min_sequential - 1;
00512       rtp->learning_max_seq = seq;
00513    }
00514 
00515    return probation;
00516 }

static void rtp_learning_seq_init ( struct ast_rtp rtp,
uint16_t  seq 
) [static]

Definition at line 482 of file res_rtp_asterisk.c.

References ast_srtp::rtp.

Referenced by ast_rtp_new(), and ast_rtp_remote_address_set().

00483 {
00484    rtp->learning_max_seq = seq - 1;
00485    rtp->learning_probation = learning_min_sequential;
00486 }

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

Definition at line 380 of file res_rtp_asterisk.c.

References __rtp_recvfrom().

Referenced by ast_rtp_read().

00381 {
00382    return __rtp_recvfrom(instance, buf, size, flags, sa, 0);
00383 }

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

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

02655 {
02656    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02657 
02658    if (frame->datalen > -1) {
02659       struct rtp_red *red = rtp->red;
02660       memcpy(&red->buf_data[red->t140.datalen], frame->data.ptr, frame->datalen);
02661       red->t140.datalen += frame->datalen;
02662       red->t140.ts = frame->ts;
02663    }
02664 
02665    return 0;
02666 }

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

Definition at line 2619 of file res_rtp_asterisk.c.

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

02620 {
02621    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02622    int x;
02623 
02624    if (!(rtp->red = ast_calloc(1, sizeof(*rtp->red)))) {
02625       return -1;
02626    }
02627 
02628    rtp->red->t140.frametype = AST_FRAME_TEXT;
02629    rtp->red->t140.subclass.codec = AST_FORMAT_T140RED;
02630    rtp->red->t140.data.ptr = &rtp->red->buf_data;
02631 
02632    rtp->red->t140.ts = 0;
02633    rtp->red->t140red = rtp->red->t140;
02634    rtp->red->t140red.data.ptr = &rtp->red->t140red_data;
02635    rtp->red->t140red.datalen = 0;
02636    rtp->red->ti = buffer_time;
02637    rtp->red->num_gen = generations;
02638    rtp->red->hdrlen = generations * 4 + 1;
02639    rtp->red->prev_ts = 0;
02640 
02641    for (x = 0; x < generations; x++) {
02642       rtp->red->pt[x] = payloads[x];
02643       rtp->red->pt[x] |= 1 << 7; /* mark redundant generations pt */
02644       rtp->red->t140red_data[x*4] = rtp->red->pt[x];
02645    }
02646    rtp->red->t140red_data[x*4] = rtp->red->pt[x] = payloads[x]; /* primary pt */
02647    rtp->red->schedid = ast_sched_add(rtp->sched, generations, red_write, instance);
02648 
02649    rtp->red->t140.datalen = 0;
02650 
02651    return 0;
02652 }

static int rtp_reload ( int  reload  )  [static]

Definition at line 2961 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_LEARNING_MIN_SEQUENTIAL, DEFAULT_RTP_END, DEFAULT_RTP_START, dtmftimeout, learning_min_sequential, LOG_WARNING, MAXIMUM_RTP_PORT, MINIMUM_RTP_PORT, RTCP_MAX_INTERVALMS, RTCP_MIN_INTERVALMS, rtcpinterval, rtpend, rtpstart, STRICT_RTP_OPEN, and strictrtp.

Referenced by load_module(), and reload_module().

02962 {
02963    struct ast_config *cfg;
02964    const char *s;
02965    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
02966 
02967    cfg = ast_config_load2("rtp.conf", "rtp", config_flags);
02968    if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
02969       return 0;
02970    }
02971 
02972    rtpstart = DEFAULT_RTP_START;
02973    rtpend = DEFAULT_RTP_END;
02974    dtmftimeout = DEFAULT_DTMF_TIMEOUT;
02975    strictrtp = STRICT_RTP_OPEN;
02976    learning_min_sequential = DEFAULT_LEARNING_MIN_SEQUENTIAL;
02977    if (cfg) {
02978       if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
02979          rtpstart = atoi(s);
02980          if (rtpstart < MINIMUM_RTP_PORT)
02981             rtpstart = MINIMUM_RTP_PORT;
02982          if (rtpstart > MAXIMUM_RTP_PORT)
02983             rtpstart = MAXIMUM_RTP_PORT;
02984       }
02985       if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
02986          rtpend = atoi(s);
02987          if (rtpend < MINIMUM_RTP_PORT)
02988             rtpend = MINIMUM_RTP_PORT;
02989          if (rtpend > MAXIMUM_RTP_PORT)
02990             rtpend = MAXIMUM_RTP_PORT;
02991       }
02992       if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
02993          rtcpinterval = atoi(s);
02994          if (rtcpinterval == 0)
02995             rtcpinterval = 0; /* Just so we're clear... it's zero */
02996          if (rtcpinterval < RTCP_MIN_INTERVALMS)
02997             rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
02998          if (rtcpinterval > RTCP_MAX_INTERVALMS)
02999             rtcpinterval = RTCP_MAX_INTERVALMS;
03000       }
03001       if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
03002 #ifdef SO_NO_CHECK
03003          nochecksums = ast_false(s) ? 1 : 0;
03004 #else
03005          if (ast_false(s))
03006             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
03007 #endif
03008       }
03009       if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
03010          dtmftimeout = atoi(s);
03011          if ((dtmftimeout < 0) || (dtmftimeout > 64000)) {
03012             ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
03013                dtmftimeout, DEFAULT_DTMF_TIMEOUT);
03014             dtmftimeout = DEFAULT_DTMF_TIMEOUT;
03015          };
03016       }
03017       if ((s = ast_variable_retrieve(cfg, "general", "strictrtp"))) {
03018          strictrtp = ast_true(s);
03019       }
03020       if ((s = ast_variable_retrieve(cfg, "general", "probation"))) {
03021          if ((sscanf(s, "%d", &learning_min_sequential) <= 0) || learning_min_sequential <= 0) {
03022             ast_log(LOG_WARNING, "Value for 'probation' could not be read, using default of '%d' instead\n",
03023                DEFAULT_LEARNING_MIN_SEQUENTIAL);
03024          }
03025       }
03026       ast_config_destroy(cfg);
03027    }
03028    if (rtpstart >= rtpend) {
03029       ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
03030       rtpstart = DEFAULT_RTP_START;
03031       rtpend = DEFAULT_RTP_END;
03032    }
03033    ast_verb(2, "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
03034    return 0;
03035 }

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

Definition at line 404 of file res_rtp_asterisk.c.

References __rtp_sendto().

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

00405 {
00406    return __rtp_sendto(instance, buf, size, flags, sa, 0);
00407 }

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

Definition at line 432 of file res_rtp_asterisk.c.

References SQUARE.

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

00433 {
00434 /*
00435       for the formula check http://www.cs.umd.edu/~austinjp/constSD.pdf
00436       return sqrt( (sample_count*pow(stddev,2) + sample_count*pow((sample-normdev)/(sample_count+1),2) + pow(sample-normdev_curent,2)) / (sample_count+1));
00437       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
00438       optimized formula
00439 */
00440 #define SQUARE(x) ((x) * (x))
00441 
00442    stddev = sample_count * stddev;
00443    sample_count++;
00444 
00445    return stddev +
00446       ( sample_count * SQUARE( (sample - normdev) / sample_count ) ) +
00447       ( SQUARE(sample - normdev_curent) / sample_count );
00448 
00449 #undef SQUARE
00450 }

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

Definition at line 879 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

00880 {
00881    unsigned int sec, usec, frac;
00882    sec = tv.tv_sec + 2208988800u; /* Sec between 1900 and 1970 */
00883    usec = tv.tv_usec;
00884    frac = (usec << 12) + (usec << 8) - ((usec * 3650) >> 6);
00885    *msw = sec;
00886    *lsw = frac;
00887 }

static int unload_module ( void   )  [static]

Definition at line 3059 of file res_rtp_asterisk.c.

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

03060 {
03061    ast_rtp_engine_unregister(&asterisk_rtp_engine);
03062    ast_cli_unregister_multiple(cli_rtp, ARRAY_LEN(cli_rtp));
03063 
03064    return 0;
03065 }


Variable Documentation

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

Definition at line 3072 of file res_rtp_asterisk.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 3072 of file res_rtp_asterisk.c.

struct ast_rtp_engine asterisk_rtp_engine [static]

Definition at line 298 of file res_rtp_asterisk.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_rtp[] [static]

Initial value:

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

Definition at line 2955 of file res_rtp_asterisk.c.

Referenced by load_module(), and unload_module().

int dtmftimeout = DEFAULT_DTMF_TIMEOUT [static]

Definition at line 86 of file res_rtp_asterisk.c.

Referenced by process_dtmf_rfc2833(), and rtp_reload().

int learning_min_sequential [static]

Definition at line 102 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

struct ast_srtp_res* res_srtp

Definition at line 48 of file rtp_engine.c.

int rtcpdebug [static]

Are we debugging RTCP?

Definition at line 91 of file res_rtp_asterisk.c.

Referenced by handle_cli_rtcp_set_debug(), and rtcp_do_debug_ip().

struct ast_sockaddr rtcpdebugaddr [static]

Debug RTCP packets to/from this host

Definition at line 95 of file res_rtp_asterisk.c.

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

int rtcpdebugport [static]

Definition at line 97 of file res_rtp_asterisk.c.

Referenced by rtcp_do_debug_ip().

int rtcpinterval = RTCP_DEFAULT_INTERVALMS [static]

Time between rtcp reports in millisecs

Definition at line 93 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

int rtcpstats [static]

Are we debugging RTCP?

Definition at line 92 of file res_rtp_asterisk.c.

Referenced by handle_cli_rtcp_set_stats().

int rtpdebug [static]

Are we debugging?

Definition at line 90 of file res_rtp_asterisk.c.

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

struct ast_sockaddr rtpdebugaddr [static]

Debug packets to/from this host

Definition at line 94 of file res_rtp_asterisk.c.

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

int rtpdebugport [static]

Definition at line 96 of file res_rtp_asterisk.c.

Referenced by rtp_do_debug_ip().

int rtpend = DEFAULT_RTP_END [static]

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

Definition at line 89 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

int rtpstart = DEFAULT_RTP_START [static]

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

Definition at line 88 of file res_rtp_asterisk.c.

Referenced by rtp_reload().

int strictrtp [static]

Definition at line 101 of file res_rtp_asterisk.c.

Referenced by ast_rtp_remote_address_set(), and rtp_reload().


Generated on Mon Oct 8 12:39:28 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7