Sat Feb 11 06:36:35 2012

Asterisk developer's documentation


res_rtp_asterisk.c File Reference

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

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

Include dependency graph for res_rtp_asterisk.c:

Go to the source code of this file.

Data Structures

struct  ast_rtcp
 Structure defining an RTCP session. More...
struct  ast_rtp
 RTP session description. More...
struct  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 ast_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 (struct ast_format *format)
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 = AST_BUILDOPT_SUM, .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 3053 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 357 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().

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

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

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

static void __unreg_module ( void   )  [static]

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

Referenced by ast_rtp_raw_write(), and ast_rtp_read().

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

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

Definition at line 1760 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_WARNING, ast_frame::mallocd, manager_event, ast_rtcp::maxrtt, ast_rtcp::minrtt, normdev_compute(), ast_rtcp::normdevrtt, 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().

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

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

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

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

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

Referenced by ast_rtcp_write().

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

static int ast_rtcp_write_sr ( struct ast_rtp_instance instance  )  [static]

Send RTCP sender's report.

Definition at line 989 of file res_rtp_asterisk.c.

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

Referenced by ast_rtcp_write().

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

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

Definition at line 2575 of file res_rtp_asterisk.c.

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

02576 {
02577    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02578 
02579    /* No need to futz with rtp->rtcp here because ast_rtcp_read is already able to adjust if receiving
02580     * RTCP from an "unexpected" source
02581     */
02582    ast_sockaddr_copy(&rtp->alt_rtp_address, addr);
02583 
02584    return;
02585 }

static void ast_rtp_change_source ( struct ast_rtp_instance instance  )  [static]

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

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

static int ast_rtp_destroy ( struct ast_rtp_instance instance  )  [static]

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

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

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

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

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

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

02707 {
02708    /* If both sides are not using the same method of DTMF transmission
02709     * (ie: one is RFC2833, other is INFO... then we can not do direct media.
02710     * --------------------------------------------------
02711     * | DTMF Mode |  HAS_DTMF  |  Accepts Begin Frames |
02712     * |-----------|------------|-----------------------|
02713     * | Inband    | False      | True                  |
02714     * | RFC2833   | True       | True                  |
02715     * | SIP INFO  | False      | False                 |
02716     * --------------------------------------------------
02717     */
02718    return (((ast_rtp_instance_get_prop(instance0, AST_RTP_PROPERTY_DTMF) != ast_rtp_instance_get_prop(instance1, AST_RTP_PROPERTY_DTMF)) ||
02719        (!chan0->tech->send_digit_begin != !chan1->tech->send_digit_begin)) ? 0 : 1);
02720 }

static int ast_rtp_dtmf_continuation ( struct ast_rtp_instance instance  )  [static]

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

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

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

Definition at line 815 of file res_rtp_asterisk.c.

References ast_rtp_dtmf_end_with_duration().

00816 {
00817    return ast_rtp_dtmf_end_with_duration(instance, digit, 0);
00818 }

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

Definition at line 745 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_rtp::dtmfmute, errno, ast_rtp::f, ast_frame_subclass::format, 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().

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

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

Definition at line 626 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data(), and ast_rtp::dtmfmode.

00627 {
00628    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00629    return rtp->dtmfmode;
00630 }

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

Definition at line 619 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data(), and ast_rtp::dtmfmode.

00620 {
00621    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
00622    rtp->dtmfmode = dtmf_mode;
00623    return 0;
00624 }

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

Definition at line 2545 of file res_rtp_asterisk.c.

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

02546 {
02547    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02548 
02549    return rtcp ? (rtp->rtcp ? rtp->rtcp->s : -1) : rtp->s;
02550 }

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

02659 {
02660    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02661 
02662    if (!rtp->rtcp) {
02663       return -1;
02664    }
02665 
02666    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_TXCOUNT, -1, stats->txcount, rtp->txcount);
02667    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_RXCOUNT, -1, stats->rxcount, rtp->rxcount);
02668 
02669    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_TXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->txploss, rtp->rtcp->reported_lost);
02670    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);
02671    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MAXRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_maxrxploss, rtp->rtcp->reported_maxlost);
02672    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MINRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_minrxploss, rtp->rtcp->reported_minlost);
02673    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_normdevrxploss, rtp->rtcp->reported_normdev_lost);
02674    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_STDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->remote_stdevrxploss, rtp->rtcp->reported_stdev_lost);
02675    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MAXRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_maxrxploss, rtp->rtcp->maxrxlost);
02676    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MINRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_minrxploss, rtp->rtcp->minrxlost);
02677    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_normdevrxploss, rtp->rtcp->normdev_rxlost);
02678    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_STDEVRXPLOSS, AST_RTP_INSTANCE_STAT_COMBINED_LOSS, stats->local_stdevrxploss, rtp->rtcp->stdev_rxlost);
02679    AST_RTP_STAT_TERMINATOR(AST_RTP_INSTANCE_STAT_COMBINED_LOSS);
02680 
02681    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_TXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->txjitter, rtp->rxjitter);
02682    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);
02683    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MAXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_maxjitter, rtp->rtcp->reported_maxjitter);
02684    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_MINJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_minjitter, rtp->rtcp->reported_minjitter);
02685    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_NORMDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_normdevjitter, rtp->rtcp->reported_normdev_jitter);
02686    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_STDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->remote_stdevjitter, rtp->rtcp->reported_stdev_jitter);
02687    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MAXJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_maxjitter, rtp->rtcp->maxrxjitter);
02688    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_MINJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_minjitter, rtp->rtcp->minrxjitter);
02689    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_NORMDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_normdevjitter, rtp->rtcp->normdev_rxjitter);
02690    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_STDEVJITTER, AST_RTP_INSTANCE_STAT_COMBINED_JITTER, stats->local_stdevjitter, rtp->rtcp->stdev_rxjitter);
02691    AST_RTP_STAT_TERMINATOR(AST_RTP_INSTANCE_STAT_COMBINED_JITTER);
02692 
02693    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_RTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->rtt, rtp->rtcp->rtt);
02694    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_MAX_RTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->maxrtt, rtp->rtcp->maxrtt);
02695    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_MIN_RTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->minrtt, rtp->rtcp->minrtt);
02696    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_NORMDEVRTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->normdevrtt, rtp->rtcp->normdevrtt);
02697    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_STDEVRTT, AST_RTP_INSTANCE_STAT_COMBINED_RTT, stats->stdevrtt, rtp->rtcp->stdevrtt);
02698    AST_RTP_STAT_TERMINATOR(AST_RTP_INSTANCE_STAT_COMBINED_RTT);
02699 
02700    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_LOCAL_SSRC, -1, stats->local_ssrc, rtp->ssrc);
02701    AST_RTP_STAT_SET(AST_RTP_INSTANCE_STAT_REMOTE_SSRC, -1, stats->remote_ssrc, rtp->themssrc);
02702 
02703    return 0;
02704 }

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

Definition at line 2649 of file res_rtp_asterisk.c.

References ast_rtp_instance_get_data(), ast_set_flag, and FLAG_NEED_MARKER_BIT.

02650 {
02651    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance0);
02652 
02653    ast_set_flag(rtp, FLAG_NEED_MARKER_BIT);
02654 
02655    return 0;
02656 }

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

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

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

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

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

02477 {
02478    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02479 
02480    if (property == AST_RTP_PROPERTY_RTCP) {
02481       if (value) {
02482          if (rtp->rtcp) {
02483             ast_debug(1, "Ignoring duplicate RTCP property on RTP instance '%p'\n", instance);
02484             return;
02485          }
02486          /* Setup RTCP to be activated on the next RTP write */
02487          if (!(rtp->rtcp = ast_calloc(1, sizeof(*rtp->rtcp)))) {
02488             return;
02489          }
02490 
02491          /* Grab the IP address and port we are going to use */
02492          ast_rtp_instance_get_local_address(instance, &rtp->rtcp->us);
02493          ast_sockaddr_set_port(&rtp->rtcp->us,
02494                      ast_sockaddr_port(&rtp->rtcp->us) + 1);
02495 
02496          if ((rtp->rtcp->s =
02497               create_new_socket("RTCP",
02498                       ast_sockaddr_is_ipv4(&rtp->rtcp->us) ?
02499                       AF_INET :
02500                       ast_sockaddr_is_ipv6(&rtp->rtcp->us) ?
02501                       AF_INET6 : -1)) < 0) {
02502             ast_debug(1, "Failed to create a new socket for RTCP on instance '%p'\n", instance);
02503             ast_free(rtp->rtcp);
02504             rtp->rtcp = NULL;
02505             return;
02506          }
02507 
02508          /* 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 */
02509          if (ast_bind(rtp->rtcp->s, &rtp->rtcp->us)) {
02510             ast_debug(1, "Failed to setup RTCP on RTP instance '%p'\n", instance);
02511             close(rtp->rtcp->s);
02512             ast_free(rtp->rtcp);
02513             rtp->rtcp = NULL;
02514             return;
02515          }
02516 
02517          ast_debug(1, "Setup RTCP on RTP instance '%p'\n", instance);
02518          rtp->rtcp->schedid = -1;
02519 
02520          return;
02521       } else {
02522          if (rtp->rtcp) {
02523             if (rtp->rtcp->schedid > 0) {
02524                if (!ast_sched_del(rtp->sched, rtp->rtcp->schedid)) {
02525                   /* Successfully cancelled scheduler entry. */
02526                   ao2_ref(instance, -1);
02527                } else {
02528                   /* Unable to cancel scheduler entry */
02529                   ast_debug(1, "Failed to tear down RTCP on RTP instance '%p'\n", instance);
02530                   return;
02531                }
02532                rtp->rtcp->schedid = -1;
02533             }
02534             close(rtp->rtcp->s);
02535             ast_free(rtp->rtcp);
02536             rtp->rtcp = NULL;
02537          }
02538          return;
02539       }
02540    }
02541 
02542    return;
02543 }

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

Definition at line 2759 of file res_rtp_asterisk.c.

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

02760 {
02761    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02762 
02763    return ast_set_qos(rtp->s, tos, cos, desc);
02764 }

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

Definition at line 1147 of file res_rtp_asterisk.c.

References ao2_ref, ast_clear_flag, ast_debug, AST_FORMAT_G722, ast_format_get_video_mark(), 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::data, ast_frame::datalen, ast_frame::delivery, errno, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, FLAG_NEED_MARKER_BIT, ast_frame_subclass::format, ast_frame::frametype, ast_format::id, ast_rtp::lastdigitts, ast_rtp::lastotexttimestamp, ast_rtp::lastovidtimestamp, ast_rtp::lastts, LOG_WARNING, MAX_TIMESTAMP_SKEW, 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().

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

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

Definition at line 2101 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_copy(), AST_FORMAT_GET_TYPE, ast_format_is_slinear(), ast_format_rate(), ast_format_set(), ast_format_set_video_mark(), AST_FORMAT_T140, AST_FORMAT_T140RED, AST_FORMAT_TYPE_AUDIO, AST_FORMAT_TYPE_VIDEO, 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(), 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_subclass::format, ast_rtp_payload_type::format, ast_frame::frametype, ast_format::id, 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, ast_rtp_payload_type::rtp_code, 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.

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

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

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

02553 {
02554    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02555 
02556    if (rtp->rtcp) {
02557       ast_debug(1, "Setting RTCP address on RTP instance '%p'\n", instance);
02558       ast_sockaddr_copy(&rtp->rtcp->them, addr);
02559       if (!ast_sockaddr_isnull(addr)) {
02560          ast_sockaddr_set_port(&rtp->rtcp->them,
02561                      ast_sockaddr_port(addr) + 1);
02562       }
02563    }
02564 
02565    rtp->rxseqno = 0;
02566 
02567    if (strictrtp) {
02568       rtp->strict_rtp_state = STRICT_RTP_LEARN;
02569       rtp_learning_seq_init(rtp, rtp->seqno);
02570    }
02571 
02572    return;
02573 }

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

generate comfort noice (CNG)

Definition at line 2767 of file res_rtp_asterisk.c.

References ast_log(), AST_RTP_CN, ast_rtp_codecs_payload_code(), 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::data, 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.

02768 {
02769    unsigned int *rtpheader;
02770    int hdrlen = 12;
02771    int res;
02772    int payload;
02773    char data[256];
02774    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02775    struct ast_sockaddr remote_address = { {0,} };
02776 
02777    ast_rtp_instance_get_remote_address(instance, &remote_address);
02778 
02779    if (ast_sockaddr_isnull(&remote_address)) {
02780       return -1;
02781    }
02782 
02783    payload = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 0, NULL, AST_RTP_CN);
02784 
02785    level = 127 - (level & 0x7f);
02786    
02787    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
02788 
02789    /* Get a pointer to the header */
02790    rtpheader = (unsigned int *)data;
02791    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
02792    rtpheader[1] = htonl(rtp->lastts);
02793    rtpheader[2] = htonl(rtp->ssrc); 
02794    data[12] = level;
02795 
02796    res = rtp_sendto(instance, (void *) rtpheader, hdrlen + 1, 0, &remote_address);
02797 
02798    if (res < 0) {
02799       ast_log(LOG_ERROR, "RTP Comfort Noise Transmission error to %s: %s\n", ast_sockaddr_stringify(&remote_address), strerror(errno));
02800    } else if (rtp_debug_test_addr(&remote_address)) {
02801       ast_verbose("Sent Comfort Noise RTP packet to %s (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02802             ast_sockaddr_stringify(&remote_address),
02803             AST_RTP_CN, rtp->seqno, rtp->lastdigitts, res - hdrlen);
02804    }
02805 
02806    return res;
02807 }

static void ast_rtp_stop ( struct ast_rtp_instance instance  )  [static]

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

02733 {
02734    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02735    struct ast_sockaddr addr = { {0,} };
02736 
02737    if (rtp->rtcp && rtp->rtcp->schedid > 0) {
02738       if (!ast_sched_del(rtp->sched, rtp->rtcp->schedid)) {
02739          /* successfully cancelled scheduler entry. */
02740          ao2_ref(instance, -1);
02741       }
02742       rtp->rtcp->schedid = -1;
02743    }
02744 
02745    if (rtp->red) {
02746       AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
02747       free(rtp->red);
02748       rtp->red = NULL;
02749    }
02750 
02751    ast_rtp_instance_set_remote_address(instance, &addr);
02752    if (rtp->rtcp) {
02753       ast_sockaddr_setnull(&rtp->rtcp->them);
02754    }
02755 
02756    ast_set_flag(rtp, FLAG_NEED_MARKER_BIT);
02757 }

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

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

02723 {
02724    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02725    struct sockaddr_in suggestion_tmp;
02726 
02727    ast_sockaddr_to_sin(suggestion, &suggestion_tmp);
02728    ast_stun_request(rtp->s, &suggestion_tmp, username, NULL);
02729    ast_sockaddr_from_sin(suggestion, &suggestion_tmp);
02730 }

static void ast_rtp_update_source ( struct ast_rtp_instance instance  )  [static]

Definition at line 820 of file res_rtp_asterisk.c.

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

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

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

Definition at line 1312 of file res_rtp_asterisk.c.

References ast_codec_pref_getsize(), ast_debug, AST_FORMAT_CELT, ast_format_cmp(), AST_FORMAT_CMP_NOT_EQUAL, ast_format_copy(), AST_FORMAT_G719, AST_FORMAT_G723_1, AST_FORMAT_SILK, AST_FORMAT_SIREN14, AST_FORMAT_SIREN7, AST_FORMAT_SPEEX, AST_FORMAT_SPEEX16, AST_FORMAT_SPEEX32, 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_format_list::cur_ms, ast_frame::data, ast_frame::datalen, f, ast_format_list::flags, ast_frame_subclass::format, ast_format_list::fr_len, ast_frame::frametype, ast_format::id, 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().

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

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

Definition at line 2030 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, errno, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, FLAG_NEED_MARKER_BIT, ast_rtp_payload_type::format, LOG_WARNING, option_debug, reconstruct(), ast_rtp_payload_type::rtp_code, rtp_debug_test_addr(), and rtp_sendto().

Referenced by ast_rtp_read().

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

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

Definition at line 1429 of file res_rtp_asterisk.c.

References ast_samp2tv(), ast_tvadd(), ast_tvsub(), ast_rtp::drxcore, ast_rtp::f, ast_frame_subclass::format, 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.

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

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

Definition at line 857 of file res_rtp_asterisk.c.

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

Referenced by ast_rtp_raw_write().

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

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

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

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

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

Definition at line 451 of file res_rtp_asterisk.c.

References ast_log(), errno, and LOG_WARNING.

Referenced by ast_rtp_new(), and ast_rtp_prop_set().

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

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

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

02877 {
02878    switch (cmd) {
02879    case CLI_INIT:
02880       e->command = "rtcp set debug {on|off|ip}";
02881       e->usage =
02882          "Usage: rtcp set debug {on|off|ip host[:port]}\n"
02883          "       Enable/Disable dumping of all RTCP packets. If 'ip' is\n"
02884          "       specified, limit the dumped packets to those to and from\n"
02885          "       the specified 'host' with optional port.\n";
02886       return NULL;
02887    case CLI_GENERATE:
02888       return NULL;
02889    }
02890 
02891    if (a->argc == e->args) { /* set on or off */
02892       if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
02893          rtcpdebug = 1;
02894          memset(&rtcpdebugaddr, 0, sizeof(rtcpdebugaddr));
02895          ast_cli(a->fd, "RTCP Debugging Enabled\n");
02896          return CLI_SUCCESS;
02897       } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
02898          rtcpdebug = 0;
02899          ast_cli(a->fd, "RTCP Debugging Disabled\n");
02900          return CLI_SUCCESS;
02901       }
02902    } else if (a->argc == e->args +1) { /* ip */
02903       return rtcp_do_debug_ip(a);
02904    }
02905 
02906    return CLI_SHOWUSAGE;   /* default, failure */
02907 }

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

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

02910 {
02911    switch (cmd) {
02912    case CLI_INIT:
02913       e->command = "rtcp set stats {on|off}";
02914       e->usage =
02915          "Usage: rtcp set stats {on|off}\n"
02916          "       Enable/Disable dumping of RTCP stats.\n";
02917       return NULL;
02918    case CLI_GENERATE:
02919       return NULL;
02920    }
02921 
02922    if (a->argc != e->args)
02923       return CLI_SHOWUSAGE;
02924 
02925    if (!strncasecmp(a->argv[e->args-1], "on", 2))
02926       rtcpstats = 1;
02927    else if (!strncasecmp(a->argv[e->args-1], "off", 3))
02928       rtcpstats = 0;
02929    else
02930       return CLI_SHOWUSAGE;
02931 
02932    ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled");
02933    return CLI_SUCCESS;
02934 }

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

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

02844 {
02845    switch (cmd) {
02846    case CLI_INIT:
02847       e->command = "rtp set debug {on|off|ip}";
02848       e->usage =
02849          "Usage: rtp set debug {on|off|ip host[:port]}\n"
02850          "       Enable/Disable dumping of all RTP packets. If 'ip' is\n"
02851          "       specified, limit the dumped packets to those to and from\n"
02852          "       the specified 'host' with optional port.\n";
02853       return NULL;
02854    case CLI_GENERATE:
02855       return NULL;
02856    }
02857 
02858    if (a->argc == e->args) { /* set on or off */
02859       if (!strncasecmp(a->argv[e->args-1], "on", 2)) {
02860          rtpdebug = 1;
02861          memset(&rtpdebugaddr, 0, sizeof(rtpdebugaddr));
02862          ast_cli(a->fd, "RTP Debugging Enabled\n");
02863          return CLI_SUCCESS;
02864       } else if (!strncasecmp(a->argv[e->args-1], "off", 3)) {
02865          rtpdebug = 0;
02866          ast_cli(a->fd, "RTP Debugging Disabled\n");
02867          return CLI_SUCCESS;
02868       }
02869    } else if (a->argc == e->args +1) { /* ip */
02870       return rtp_do_debug_ip(a);
02871    }
02872 
02873    return CLI_SHOWUSAGE;   /* default, failure */
02874 }

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

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

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

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 1719 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_format::id, 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().

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

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 1640 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_format::id, ast_rtp::lastrxformat, ast_rtp::resp, rtp_get_rate(), ast_frame::samples, and seq.

Referenced by ast_rtp_read().

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

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

References ast_debug, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_frdup(), AST_LIST_INSERT_TAIL, ast_rtp_instance_get_data(), ast_rtp_instance_get_prop(), ast_rtp_instance_get_remote_address(), AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_samp2tv(), ast_sockaddr_stringify(), ast_tv(), ast_tvdiff_ms(), ast_verbose, create_dtmf_frame(), ast_rtp::dtmf_duration, ast_rtp::dtmf_timeout, ast_rtp::dtmfsamples, f, ast_frame_subclass::format, ast_rtp::lastevent, ast_frame::len, ast_rtp::resp, rtp_debug_test_addr(), rtp_get_rate(), and ast_frame::subclass.

Referenced by ast_rtp_read().

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

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

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

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

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

Write t140 redundacy frame.

Parameters:
data primary data to be buffered

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

02591 {
02592    struct ast_rtp_instance *instance = (struct ast_rtp_instance*) data;
02593    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02594 
02595    ast_rtp_write(instance, &rtp->red->t140);
02596 
02597    return 1;
02598 }

static int reload_module ( void   )  [static]

Definition at line 3018 of file res_rtp_asterisk.c.

References rtp_reload().

03019 {
03020    rtp_reload(1);
03021    return 0;
03022 }

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

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

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

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

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

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

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

Definition at line 374 of file res_rtp_asterisk.c.

References __rtp_recvfrom().

Referenced by ast_rtcp_read().

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

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

Definition at line 398 of file res_rtp_asterisk.c.

References __rtp_sendto().

Referenced by ast_rtcp_write_rr(), and ast_rtcp_write_sr().

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

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

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

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

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

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

02810 {
02811    char *arg = ast_strdupa(a->argv[4]);
02812    char *debughost = NULL;
02813    char *debugport = NULL;
02814 
02815    if (!ast_sockaddr_parse(&rtpdebugaddr, arg, 0) || !ast_sockaddr_split_hostport(arg, &debughost, &debugport, 0)) {
02816       ast_cli(a->fd, "Lookup failed for '%s'\n", arg);
02817       return CLI_FAILURE;
02818    }
02819    rtpdebugport = (!ast_strlen_zero(debugport) && debugport[0] != '0');
02820    ast_cli(a->fd, "RTP Debugging Enabled for address: %s\n",
02821       ast_sockaddr_stringify(&rtpdebugaddr));
02822    rtpdebug = 1;
02823    return CLI_SUCCESS;
02824 }

static int rtp_get_rate ( struct ast_format format  )  [static]

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

Definition at line 496 of file res_rtp_asterisk.c.

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

Referenced by ast_rtp_read().

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

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

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

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

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

Definition at line 379 of file res_rtp_asterisk.c.

References __rtp_recvfrom().

Referenced by ast_rtp_read().

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

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

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

02636 {
02637    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02638 
02639    if (frame->datalen > -1) {
02640       struct rtp_red *red = rtp->red;
02641       memcpy(&red->buf_data[red->t140.datalen], frame->data.ptr, frame->datalen);
02642       red->t140.datalen += frame->datalen;
02643       red->t140.ts = frame->ts;
02644    }
02645 
02646    return 0;
02647 }

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

Definition at line 2600 of file res_rtp_asterisk.c.

References ast_calloc, ast_format_set(), AST_FORMAT_T140RED, AST_FRAME_TEXT, ast_rtp_instance_get_data(), ast_sched_add(), rtp_red::buf_data, ast_frame::data, ast_frame::datalen, ast_frame_subclass::format, 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.

02601 {
02602    struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
02603    int x;
02604 
02605    if (!(rtp->red = ast_calloc(1, sizeof(*rtp->red)))) {
02606       return -1;
02607    }
02608 
02609    rtp->red->t140.frametype = AST_FRAME_TEXT;
02610    ast_format_set(&rtp->red->t140.subclass.format, AST_FORMAT_T140RED, 0);
02611    rtp->red->t140.data.ptr = &rtp->red->buf_data;
02612 
02613    rtp->red->t140.ts = 0;
02614    rtp->red->t140red = rtp->red->t140;
02615    rtp->red->t140red.data.ptr = &rtp->red->t140red_data;
02616    rtp->red->t140red.datalen = 0;
02617    rtp->red->ti = buffer_time;
02618    rtp->red->num_gen = generations;
02619    rtp->red->hdrlen = generations * 4 + 1;
02620    rtp->red->prev_ts = 0;
02621 
02622    for (x = 0; x < generations; x++) {
02623       rtp->red->pt[x] = payloads[x];
02624       rtp->red->pt[x] |= 1 << 7; /* mark redundant generations pt */
02625       rtp->red->t140red_data[x*4] = rtp->red->pt[x];
02626    }
02627    rtp->red->t140red_data[x*4] = rtp->red->pt[x] = payloads[x]; /* primary pt */
02628    rtp->red->schedid = ast_sched_add(rtp->sched, generations, red_write, instance);
02629 
02630    rtp->red->t140.datalen = 0;
02631 
02632    return 0;
02633 }

static int rtp_reload ( int  reload  )  [static]

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

Referenced by load_module(), and reload_module().

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

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

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

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

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

Definition at line 431 of file res_rtp_asterisk.c.

References SQUARE.

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

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

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

Definition at line 876 of file res_rtp_asterisk.c.

Referenced by ast_rtcp_read(), and ast_rtcp_write_sr().

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

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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } [static]

Definition at line 3053 of file res_rtp_asterisk.c.

Definition at line 3053 of file res_rtp_asterisk.c.

Definition at line 297 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 2936 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 45 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 Sat Feb 11 06:36:35 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6