Tue Aug 20 16:35:14 2013

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
struct 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)
#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

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 3077 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(), ast_rtp::rtcp, ast_rtp::s, ast_rtcp::s, 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    char *in = buf;
00364 
00365    if ((len = ast_recvfrom(rtcp ? rtp->rtcp->s : rtp->s, buf, size, flags, sa)) < 0) {
00366       return len;
00367    }
00368 
00369    if ((*in & 0xC0) && res_srtp && srtp && res_srtp->unprotect(srtp, buf, &len, rtcp) < 0) {
00370       return -1;
00371    }
00372 
00373    return len;
00374 }

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

References ast_rtp_instance_get_data(), ast_rtp_instance_get_srtp(), ast_sendto(), len(), ast_srtp_res::protect, ast_rtp::rtcp, ast_rtp::s, and ast_rtcp::s.

Referenced by rtcp_sendto(), and rtp_sendto().

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

static void __unreg_module ( void   )  [static]

Definition at line 3077 of file res_rtp_asterisk.c.

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

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

Definition at line 415 of file res_rtp_asterisk.c.

Referenced by ast_rtp_raw_write(), and ast_rtp_read().

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

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

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

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

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 1125 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().

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

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 893 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, and ast_rtp::themssrc.

Referenced by ast_rtcp_write().

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

static int ast_rtcp_write_sr ( struct ast_rtp_instance instance  )  [static]

Send RTCP sender's report.

Definition at line 995 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, timeval2ntp(), ast_rtp::txcount, ast_rtcp::txlsr, and ast_rtp::txoctetcount.

Referenced by ast_rtcp_write().

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

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

Definition at line 2599 of file res_rtp_asterisk.c.

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

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

static void ast_rtp_change_source ( struct ast_rtp_instance instance  )  [static]

Definition at line 837 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, ast_rtp::lastts, and ast_rtp::ssrc.

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

static int ast_rtp_destroy ( struct ast_rtp_instance instance  )  [static]

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

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

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

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

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

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

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

static int ast_rtp_dtmf_continuation ( struct ast_rtp_instance instance  )  [static]

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

00707 {
00708    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00709    struct ast_sockaddr remote_address = { {0,} };
00710    int hdrlen = 12, res = 0;
00711    char data[256];
00712    unsigned int *rtpheader = (unsigned int*)data;
00713 
00714    ast_rtp_instance_get_remote_address(instance, &remote_address);
00715 
00716    /* Make sure we know where the other side is so we can send them the packet */
00717    if (ast_sockaddr_isnull(&remote_address)) {
00718       return -1;
00719    }
00720 
00721    /* Actually create the packet we will be sending */
00722    rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
00723    rtpheader[1] = htonl(rtp->lastdigitts);
00724    rtpheader[2] = htonl(rtp->ssrc);
00725    rtpheader[3] = htonl((rtp->send_digit << 24) | (0xa << 16) | (rtp->send_duration));
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 821 of file res_rtp_asterisk.c.

References ast_rtp_dtmf_end_with_duration().

00822 {
00823    return ast_rtp_dtmf_end_with_duration(instance, digit, 0);
00824 }

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[1] = htonl(rtp->lastdigitts);
00789    rtpheader[2] = htonl(rtp->ssrc);
00790    rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
00791    rtpheader[3] |= htonl((1 << 23));
00792 
00793    /* Send it 3 times, that's the magical number */
00794    for (i = 0; i < 3; i++) {
00795 
00796       rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
00797 
00798       res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 4, 0, &remote_address);
00799       if (res < 0) {
00800          ast_log(LOG_ERROR, "RTP Transmission error to %s: %s\n",
00801             ast_sockaddr_stringify(&remote_address),
00802             strerror(errno));
00803       }
00804       if (rtp_debug_test_addr(&remote_address)) {
00805          ast_verbose("Sent RTP DTMF packet to %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
00806                 ast_sockaddr_stringify(&remote_address),
00807                 rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
00808       }
00809 
00810       rtp->seqno++;
00811    }
00812 
00813    /* Oh and we can't forget to turn off the stuff that says we are sending DTMF */
00814    rtp->lastts += rtp->send_duration;
00815    rtp->sending_digit = 0;
00816    rtp->send_digit = 0;
00817 
00818    return 0;
00819 }

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

Definition at line 630 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data(), and ast_rtp::dtmfmode.

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

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

Definition at line 623 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data(), and ast_rtp::dtmfmode.

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

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

Definition at line 2569 of file res_rtp_asterisk.c.

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

02570 {
02571    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02572 
02573    return rtcp ? (rtp->rtcp ? rtp->rtcp->s : -1) : rtp->s;
02574 }

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

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

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

Definition at line 2673 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data(), ast_set_flag, and FLAG_NEED_MARKER_BIT.

02674 {
02675    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance0);
02676 
02677    ast_set_flag(rtp, FLAG_NEED_MARKER_BIT);
02678 
02679    return 0;
02680 }

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

Definition at line 519 of file res_rtp_asterisk.c.

References ast_bind(), ast_calloc, ast_debug, ast_free, ast_log(), ast_random(), ast_rtp_instance_set_data(), 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(), ast_rtp::s, ast_rtp::sched, ast_rtp::seqno, ast_rtp::ssrc, STRICT_RTP_LEARN, STRICT_RTP_OPEN, and ast_rtp::strict_rtp_state.

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

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

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

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

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

Definition at line 2783 of file res_rtp_asterisk.c.

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

02784 {
02785    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02786 
02787    return ast_set_qos(rtp->s, tos, cos, desc);
02788 }

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

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

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

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

Definition at line 2120 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_rate(), 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_FRFLAG_HAS_TIMING_INFO, 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(), calc_rxstamp(), ast_rtp_payload_type::code, ast_frame_subclass::codec, create_dtmf_frame(), ast_rtp::cycles, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp::dtmf_duration, ast_rtp::dtmf_timeout, errno, ext, ast_rtp::f, f, FLAG_NAT_ACTIVE, ast_frame::frametype, ast_rtp::last_end_timestamp, ast_rtp::last_seqno, ast_rtp::lastitexttimestamp, ast_rtp::lastividtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxseqno, ast_rtp::lastrxts, len(), ast_frame::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, 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, ast_frame::ts, and version.

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

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

Definition at line 2576 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, and ast_rtcp::them.

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

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

generate comfort noice (CNG)

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

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

static void ast_rtp_stop ( struct ast_rtp_instance instance  )  [static]

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

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

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

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

02747 {
02748    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02749    struct sockaddr_in suggestion_tmp;
02750 
02751    ast_sockaddr_to_sin(suggestion, &suggestion_tmp);
02752    ast_stun_request(rtp->s, &suggestion_tmp, username, NULL);
02753    ast_sockaddr_from_sin(suggestion, &suggestion_tmp);
02754 }

static void ast_rtp_update_source ( struct ast_rtp_instance instance  )  [static]

Definition at line 826 of file res_rtp_asterisk.c.

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

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

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

Definition at line 1318 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::data, ast_frame::datalen, f, ast_format_list::flags, ast_format_list::fr_len, ast_frame::frametype, ast_format_list::inc_ms, ast_rtp::lasttxformat, LOG_WARNING, ast_frame::offset, ast_frame::ptr, ast_rtp::red, red_t140_to_red(), ast_rtp::smoother, and ast_frame::subclass.

Referenced by red_write().

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

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

Definition at line 2045 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(), and rtp_sendto().

Referenced by ast_rtp_read().

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

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

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

Referenced by ast_rtp_read().

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

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

Definition at line 863 of file res_rtp_asterisk.c.

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

Referenced by ast_rtp_raw_write().

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

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

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

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

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

Definition at line 453 of file res_rtp_asterisk.c.

References ast_log(), errno, and LOG_WARNING.

Referenced by ast_rtp_new(), and ast_rtp_prop_set().

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

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

Definition at line 2900 of file res_rtp_asterisk.c.

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

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

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

Definition at line 2933 of file res_rtp_asterisk.c.

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

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

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

Definition at line 2867 of file res_rtp_asterisk.c.

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

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

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

Calculate normal deviation.

Definition at line 425 of file res_rtp_asterisk.c.

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

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

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, read]

Definition at line 1734 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, ast_frame::samples, and ast_frame::subclass.

Referenced by ast_rtp_read().

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

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, read]

Definition at line 1655 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(), ast_frame::samples, and seq.

Referenced by ast_rtp_read().

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

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 1521 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, ast_frame_subclass::codec, create_dtmf_frame(), ast_rtp::dtmf_duration, ast_rtp::dtmf_timeout, ast_rtp::dtmfsamples, f, ast_rtp::last_end_timestamp, ast_rtp::last_seqno, ast_frame::len, LOG_DEBUG, option_debug, ast_rtp::resp, rtp_debug_test_addr(), rtp_get_rate(), and ast_frame::subclass.

Referenced by ast_rtp_read().

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

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

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

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

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

Write t140 redundacy frame.

Parameters:
data primary data to be buffered

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

02615 {
02616    struct ast_rtp_instance *instance = (struct ast_rtp_instance*) data;
02617    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02618 
02619    ast_rtp_write(instance, &rtp->red->t140);
02620 
02621    return 1;
02622 }

static int reload_module ( void   )  [static]

Definition at line 3042 of file res_rtp_asterisk.c.

References rtp_reload().

03043 {
03044    rtp_reload(1);
03045    return 0;
03046 }

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 2850 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, and rtcpdebugaddr.

Referenced by handle_cli_rtcp_set_debug().

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

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

Definition at line 376 of file res_rtp_asterisk.c.

References __rtp_recvfrom().

Referenced by ast_rtcp_read().

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

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

Definition at line 400 of file res_rtp_asterisk.c.

References __rtp_sendto().

Referenced by ast_rtcp_write_rr(), and ast_rtcp_write_sr().

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

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 2833 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, and rtpdebugaddr.

Referenced by handle_cli_rtp_set_debug().

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

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

Definition at line 498 of file res_rtp_asterisk.c.

References ast_debug, ast_rtp::learning_max_seq, and ast_rtp::learning_probation.

Referenced by ast_rtp_read().

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

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

Definition at line 483 of file res_rtp_asterisk.c.

References ast_rtp::learning_max_seq, and ast_rtp::learning_probation.

Referenced by ast_rtp_new(), and ast_rtp_remote_address_set().

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

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

Definition at line 381 of file res_rtp_asterisk.c.

References __rtp_recvfrom().

Referenced by ast_rtp_read().

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

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

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

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

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

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

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

static int rtp_reload ( int  reload  )  [static]

Definition at line 2966 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, LOG_WARNING, MAXIMUM_RTP_PORT, MINIMUM_RTP_PORT, RTCP_MAX_INTERVALMS, RTCP_MIN_INTERVALMS, and STRICT_RTP_OPEN.

Referenced by load_module(), and reload_module().

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

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

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

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

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

Definition at line 433 of file res_rtp_asterisk.c.

References SQUARE.

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

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

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

Definition at line 882 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

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

static int unload_module ( void   )  [static]

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

Definition at line 3077 of file res_rtp_asterisk.c.

Definition at line 298 of file res_rtp_asterisk.c.

struct ast_cli_entry cli_rtp[] [static]
Initial value:
 {
   AST_CLI_DEFINE(handle_cli_rtp_set_debug,  "Enable/Disable RTP debugging"),
   AST_CLI_DEFINE(handle_cli_rtcp_set_debug, "Enable/Disable RTCP debugging"),
   AST_CLI_DEFINE(handle_cli_rtcp_set_stats, "Enable/Disable RTCP stats"),
}

Definition at line 2960 of file res_rtp_asterisk.c.

int dtmftimeout = DEFAULT_DTMF_TIMEOUT [static]

Definition at line 86 of file res_rtp_asterisk.c.

Definition at line 102 of file res_rtp_asterisk.c.

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.

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.

int rtcpinterval = RTCP_DEFAULT_INTERVALMS [static]

Time between rtcp reports in millisecs

Definition at line 93 of file res_rtp_asterisk.c.

int rtcpstats [static]

Are we debugging RTCP?

Definition at line 92 of file res_rtp_asterisk.c.

int rtpdebug [static]

Are we debugging?

Definition at line 90 of file res_rtp_asterisk.c.

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.

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.

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.

int strictrtp [static]

Definition at line 101 of file res_rtp_asterisk.c.


Generated on 20 Aug 2013 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1