Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:49:17 2009

## Asterisk developer's documentation

# rtp.c File Reference

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

`#include <stdio.h>`
`#include <stdlib.h>`
`#include <string.h>`
`#include <sys/time.h>`
`#include <signal.h>`
`#include <errno.h>`
`#include <unistd.h>`
`#include <netinet/in.h>`
`#include <sys/socket.h>`
`#include <arpa/inet.h>`
`#include <fcntl.h>`
`#include "asterisk.h"`
`#include "asterisk/rtp.h"`
`#include "asterisk/frame.h"`
`#include "asterisk/logger.h"`
`#include "asterisk/options.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/unaligned.h"`

Include dependency graph for rtp.c:

Go to the source code of this file.

## Data Structures

struct | ast_rtcp
| Structure defining an RTCP session. More...
struct | ast_rtp
struct | rtpPayloadType

## Defines

#define | DEFAULT_DTMF_TIMEOUT 3000
#define | FLAG_3389_WARNING (1 << 0)
#define | FLAG_NAT_ACTIVE (3 << 1)
#define | FLAG_NAT_INACTIVE (0 << 1)
#define | FLAG_NAT_INACTIVE_NOWARN (1 << 1)
#define | MAX_RTP_PT 256
#define | MAX_TIMESTAMP_SKEW 640
#define | RTP_MTU 1200

## Functions

int | ast_rtcp_fd (struct ast_rtp *rtp)
static struct ast_rtcp * | ast_rtcp_new (void)
| Initialize a new RTCP session.
struct ast_frame * | ast_rtcp_read (struct ast_rtp *rtp)
enum ast_bridge_result | ast_rtp_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
void | ast_rtp_destroy (struct ast_rtp *rtp)
int | ast_rtp_fd (struct ast_rtp *rtp)
void | ast_rtp_get_current_formats (struct ast_rtp *rtp, int *astFormats, int *nonAstFormats)
int | ast_rtp_get_peer (struct ast_rtp *rtp, struct sockaddr_in *them)
void | ast_rtp_get_us (struct ast_rtp *rtp, struct sockaddr_in *us)
void | ast_rtp_init (void)
int | ast_rtp_lookup_code (struct ast_rtp *rtp, const int isAstFormat, const int code)
char * | ast_rtp_lookup_mime_multiple (char *buf, int size, const int capability, const int isAstFormat)
char * | ast_rtp_lookup_mime_subtype (const int isAstFormat, const int code)
struct rtpPayloadType | ast_rtp_lookup_pt (struct ast_rtp *rtp, int pt)
struct ast_rtp * | ast_rtp_new (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode)
| Initializate a RTP session.
struct ast_rtp * | ast_rtp_new_with_bindaddr (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode, struct in_addr addr)
| Initializate a RTP session using an in_addr structure.
void | ast_rtp_offered_from_local (struct ast_rtp *rtp, int local)
int | ast_rtp_proto_register (struct ast_rtp_protocol *proto)
void | ast_rtp_proto_unregister (struct ast_rtp_protocol *proto)
void | ast_rtp_pt_clear (struct ast_rtp *rtp)
void | ast_rtp_pt_default (struct ast_rtp *rtp)
static int | ast_rtp_raw_write (struct ast_rtp *rtp, struct ast_frame *f, int codec)
struct ast_frame * | ast_rtp_read (struct ast_rtp *rtp)
void | ast_rtp_reload (void)
void | ast_rtp_reset (struct ast_rtp *rtp)
int | ast_rtp_sendcng (struct ast_rtp *rtp, int level)
int | ast_rtp_senddigit (struct ast_rtp *rtp, char digit)
void | ast_rtp_set_callback (struct ast_rtp *rtp, ast_rtp_callback callback)
void | ast_rtp_set_data (struct ast_rtp *rtp, void *data)
void | ast_rtp_set_m_type (struct ast_rtp *rtp, int pt)
void | ast_rtp_set_peer (struct ast_rtp *rtp, struct sockaddr_in *them)
void | ast_rtp_set_rtpmap_type (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype)
void | ast_rtp_setnat (struct ast_rtp *rtp, int nat)
int | ast_rtp_settos (struct ast_rtp *rtp, int tos)
void | ast_rtp_stop (struct ast_rtp *rtp)
int | ast_rtp_write (struct ast_rtp *rtp, struct ast_frame *_f)
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_rtp_protocol * | get_proto (struct ast_channel *chan)
static struct ast_frame * | process_cisco_dtmf (struct ast_rtp *rtp, unsigned char *data, int len)
static struct ast_frame * | process_rfc2833 (struct ast_rtp *rtp, unsigned char *data, int len, unsigned int seqno)
| Process RTP DTMF and events according to RFC 2833.
static struct ast_frame * | process_rfc3389 (struct ast_rtp *rtp, unsigned char *data, int len)
| Process Comfort Noise RTP.
static int | rtp_debug_test_addr (struct sockaddr_in *addr)
static int | rtp_do_debug (int fd, int argc, char *argv[])
static int | rtp_do_debug_ip (int fd, int argc, char *argv[])
static int | rtp_no_debug (int fd, int argc, char *argv[])
static int | rtp_socket (void)
static int | rtpread (int *id, int fd, short events, void *cbdata)
static struct ast_frame * | send_dtmf (struct ast_rtp *rtp)

## Variables

static struct ast_cli_entry | cli_debug
static struct ast_cli_entry | cli_debug_ip
static struct ast_cli_entry | cli_no_debug
static char | debug_usage []
static int | dtmftimeout = DEFAULT_DTMF_TIMEOUT
struct {
struct rtpPayloadType payloadType
char * subtype
char * type
} | mimeTypes []
static char | no_debug_usage []
static struct ast_rtp_protocol * | protos = NULL
static int | rtpdebug = 0
static struct sockaddr_in | rtpdebugaddr
static int | rtpend = 0
static int | rtpstart = 0
static struct rtpPayloadType | static_RTP_PT [MAX_RTP_PT]

## Detailed Description

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

RTP is deffined in RFC 3550.

Definition in file rtp.c.

## Define Documentation

#define DEFAULT_DTMF_TIMEOUT 3000

Definition at line 61 of file rtp.c.

Referenced by ast_rtp_reload().

#define FLAG_3389_WARNING (1 << 0)

Definition at line 81 of file rtp.c.

Referenced by process_rfc3389().

#define FLAG_NAT_ACTIVE (3 << 1)

Definition at line 82 of file rtp.c.

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

#define FLAG_NAT_INACTIVE (0 << 1)

Definition at line 83 of file rtp.c.

Referenced by ast_rtp_raw_write().

#define FLAG_NAT_INACTIVE_NOWARN (1 << 1)

Definition at line 84 of file rtp.c.

Referenced by ast_rtp_raw_write().

#define MAX_RTP_PT 256

Definition at line 79 of file rtp.c.

Referenced by ast_rtp_get_current_formats(), ast_rtp_lookup_code(), ast_rtp_lookup_pt(), ast_rtp_pt_clear(), ast_rtp_pt_default(), ast_rtp_set_m_type(), and ast_rtp_set_rtpmap_type().

#define MAX_TIMESTAMP_SKEW 640

Definition at line 57 of file rtp.c.

Referenced by ast_rtp_raw_write(), calc_timestamp(), and calc_txpeerstamp().

#define RTP_MTU 1200

Definition at line 59 of file rtp.c.

## Function Documentation

int ast_rtcp_fd | ( | struct ast_rtp * | rtp | ) |

Definition at line 158 of file rtp.c.

References ast_rtp::rtcp, and ast_rtcp::s.

Referenced by sip_new().

    00159 {
    00160    if (rtp->rtcp)
    00161       return rtp->rtcp->s;
    00162    return -1;
    00163 }

static struct ast_rtcp* ast_rtcp_new | ( | void |  | ) | `[static, read]`

Initialize a new RTCP session.

Returns:
  The newly initialized RTCP session.

Definition at line 923 of file rtp.c.

References ast_log(), free, LOG_WARNING, malloc, rtp_socket(), ast_rtcp::s, and ast_rtcp::us.

Referenced by ast_rtp_new_with_bindaddr().

    00924 {
    00925    struct ast_rtcp *rtcp;
    00926    rtcp = malloc(sizeof(struct ast_rtcp));
    00927    if (!rtcp)
    00928       return NULL;
    00929    memset(rtcp, 0, sizeof(struct ast_rtcp));
    00930    rtcp->s = rtp_socket();
    00931    rtcp->us.sin_family = AF_INET;
    00932    if (rtcp->s < 0) {
    00933       free(rtcp);
    00934       ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
    00935       return NULL;
    00936    }
    00937    return rtcp;
    00938 }

struct ast_frame* ast_rtcp_read | ( | struct ast_rtp * | rtp | ) | `[read]`

Definition at line 370 of file rtp.c.

References AST_FRAME_NULL, ast_inet_ntoa(), ast_log(), CRASH, LOG_DEBUG, LOG_WARNING, ast_rtp::nat, option_debug, ast_rtp::rtcp, ast_rtcp::s, and ast_rtcp::them.

Referenced by sip_rtp_read().

    00371 {
    00372    static struct ast_frame null_frame = { AST_FRAME_NULL, };
    00373    socklen_t len;
    00374    int hdrlen = 8;
    00375    int res;
    00376    struct sockaddr_in sin;
    00377    unsigned int rtcpdata[1024];
    00378    char iabuf[INET_ADDRSTRLEN];
    00379
    00380    if (!rtp || !rtp->rtcp)
    00381       return &null_frame;
    00382
    00383    len = sizeof(sin);
    00384
    00385    res = recvfrom(rtp->rtcp->s, rtcpdata, sizeof(rtcpdata),
    00386                0, (struct sockaddr *)&sin, &len);
    00387
    00388    if (res < 0) {
    00389       if (errno == EBADF)
    00390          CRASH;
    00391       if (errno != EAGAIN) {
    00392          ast_log(LOG_WARNING, "RTP Read error: %s.  Hanging up now.\n", strerror(errno));
    00393          return NULL;
    00394       }
    00395       return &null_frame;
    00396    }
    00397
    00398    if (res < hdrlen) {
    00399       ast_log(LOG_WARNING, "RTP Read too short\n");
    00400       return &null_frame;
    00401    }
    00402
    00403    if (rtp->nat) {
    00404       /* Send to whoever sent to us */
    00405       if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
    00406           (rtp->rtcp->them.sin_port != sin.sin_port)) {
    00407          memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
    00408          if (option_debug || rtpdebug)
    00409             ast_log(LOG_DEBUG, "RTCP NAT: Got RTCP from other end. Now sending to address %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
    00410       }
    00411    }
    00412    if (option_debug)
    00413       ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res);
    00414    return &null_frame;
    00415 }

enum ast_bridge_result ast_rtp_bridge | ( | struct ast_channel * | c0,
|  | struct ast_channel * | c1,
|  | int | flags,
|  | struct ast_frame ** | fo,
|  | struct ast_channel ** | rc,
|  | int | timeoutms |
| ) |  |  |

Definition at line 1539 of file rtp.c.

References ast_channel::_softhangup, AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_IGNORE_SIGS, AST_BRIDGE_RETRY, ast_check_hangup(), AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree(), ast_indicate(), ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_read(), ast_rtp_get_peer(), ast_test_flag, ast_waitfor_n(), ast_write(), FLAG_NAT_ACTIVE, ast_frame::frametype, ast_rtp_protocol::get_codec, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_vrtp_info, inaddrcmp(), ast_channel::lock, LOG_DEBUG, LOG_WARNING, ast_channel::masq, ast_channel::masqr, ast_channel::name, option_debug, ast_rtp_protocol::set_rtp_peer, ast_frame::subclass, and ast_channel::tech_pvt.

    01540 {
    01541    struct ast_frame *f;
    01542    struct ast_channel *who, *cs[3];
    01543    struct ast_rtp *p0, *p1;      /* Audio RTP Channels */
    01544    struct ast_rtp *vp0, *vp1;    /* Video RTP channels */
    01545    struct ast_rtp_protocol *pr0, *pr1;
    01546    struct sockaddr_in ac0, ac1;
    01547    struct sockaddr_in vac0, vac1;
    01548    struct sockaddr_in t0, t1;
    01549    struct sockaddr_in vt0, vt1;
    01550    char iabuf[INET_ADDRSTRLEN];
    01551
    01552    void *pvt0, *pvt1;
    01553    int codec0,codec1, oldcodec0, oldcodec1;
    01554
    01555    memset(&vt0, 0, sizeof(vt0));
    01556    memset(&vt1, 0, sizeof(vt1));
    01557    memset(&vac0, 0, sizeof(vac0));
    01558    memset(&vac1, 0, sizeof(vac1));
    01559
    01560    /* if need DTMF, cant native bridge */
    01561    if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1))
    01562       return AST_BRIDGE_FAILED_NOWARN;
    01563
    01564    /* Lock channels */
    01565    ast_mutex_lock(&c0->lock);
    01566    while(ast_mutex_trylock(&c1->lock)) {
    01567       ast_mutex_unlock(&c0->lock);
    01568       usleep(1);
    01569       ast_mutex_lock(&c0->lock);
    01570    }
    01571
    01572    /* Find channel driver interfaces */
    01573    pr0 = get_proto(c0);
    01574    pr1 = get_proto(c1);
    01575    if (!pr0) {
    01576       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
    01577       ast_mutex_unlock(&c0->lock);
    01578       ast_mutex_unlock(&c1->lock);
    01579       return AST_BRIDGE_FAILED;
    01580    }
    01581    if (!pr1) {
    01582       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
    01583       ast_mutex_unlock(&c0->lock);
    01584       ast_mutex_unlock(&c1->lock);
    01585       return AST_BRIDGE_FAILED;
    01586    }
    01587
    01588    /* Get channel specific interface structures */
    01589    pvt0 = c0->tech_pvt;
    01590    pvt1 = c1->tech_pvt;
    01591
    01592    /* Get audio and video interface (if native bridge is possible) */
    01593    p0 = pr0->get_rtp_info(c0);
    01594    if (pr0->get_vrtp_info)
    01595       vp0 = pr0->get_vrtp_info(c0);
    01596    else
    01597       vp0 = NULL;
    01598    p1 = pr1->get_rtp_info(c1);
    01599    if (pr1->get_vrtp_info)
    01600       vp1 = pr1->get_vrtp_info(c1);
    01601    else
    01602       vp1 = NULL;
    01603
    01604    /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
    01605    if (!p0 || !p1) {
    01606       /* Somebody doesn't want to play... */
    01607       ast_mutex_unlock(&c0->lock);
    01608       ast_mutex_unlock(&c1->lock);
    01609       return AST_BRIDGE_FAILED_NOWARN;
    01610    }
    01611    /* Get codecs from both sides */
    01612    if (pr0->get_codec)
    01613       codec0 = pr0->get_codec(c0);
    01614    else
    01615       codec0 = 0;
    01616    if (pr1->get_codec)
    01617       codec1 = pr1->get_codec(c1);
    01618    else
    01619       codec1 = 0;
    01620    if (pr0->get_codec && pr1->get_codec) {
    01621       /* Hey, we can't do reinvite if both parties speak different codecs */
    01622       if (!(codec0 & codec1)) {
    01623          if (option_debug)
    01624             ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1);
    01625          ast_mutex_unlock(&c0->lock);
    01626          ast_mutex_unlock(&c1->lock);
    01627          return AST_BRIDGE_FAILED_NOWARN;
    01628       }
    01629    }
    01630
    01631    /* Ok, we should be able to redirect the media. Start with one channel */
    01632    if (pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))
    01633       ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
    01634    else {
    01635       /* Store RTP peer */
    01636       ast_rtp_get_peer(p1, &ac1);
    01637       if (vp1)
    01638          ast_rtp_get_peer(vp1, &vac1);
    01639    }
    01640    /* Then test the other channel */
    01641    if (pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))
    01642       ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name);
    01643    else {
    01644       /* Store RTP peer */
    01645       ast_rtp_get_peer(p0, &ac0);
    01646       if (vp0)
    01647          ast_rtp_get_peer(vp0, &vac0);
    01648    }
    01649    ast_mutex_unlock(&c0->lock);
    01650    ast_mutex_unlock(&c1->lock);
    01651    /* External RTP Bridge up, now loop and see if something happes that force us to take the
    01652       media back to Asterisk */
    01653    cs[0] = c0;
    01654    cs[1] = c1;
    01655    cs[2] = NULL;
    01656    oldcodec0 = codec0;
    01657    oldcodec1 = codec1;
    01658    for (;;) {
    01659       /* Check if something changed... */
    01660       if ((c0->tech_pvt != pvt0)  ||
    01661          (c1->tech_pvt != pvt1) ||
    01662          (c0->masq || c0->masqr || c1->masq || c1->masqr)) {
    01663             ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
    01664             if (c0->tech_pvt == pvt0) {
    01665                if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
    01666                   ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
    01667             }
    01668             if (c1->tech_pvt == pvt1) {
    01669                if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
    01670                   ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
    01671             }
    01672             return AST_BRIDGE_RETRY;
    01673       }
    01674       /* Now check if they have changed address */
    01675       ast_rtp_get_peer(p1, &t1);
    01676       ast_rtp_get_peer(p0, &t0);
    01677       if (pr0->get_codec)
    01678          codec0 = pr0->get_codec(c0);
    01679       if (pr1->get_codec)
    01680          codec1 = pr1->get_codec(c1);
    01681       if (vp1)
    01682          ast_rtp_get_peer(vp1, &vt1);
    01683       if (vp0)
    01684          ast_rtp_get_peer(vp0, &vt0);
    01685       if (inaddrcmp(&t1, &ac1) || (vp1 && inaddrcmp(&vt1, &vac1)) || (codec1 != oldcodec1)) {
    01686          if (option_debug > 1) {
    01687             ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
    01688                c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), t1.sin_addr), ntohs(t1.sin_port), codec1);
    01689             ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n",
    01690                c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), vt1.sin_addr), ntohs(vt1.sin_port), codec1);
    01691             ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
    01692                c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1);
    01693             ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
    01694                c1->name, ast_inet_ntoa(iabuf, sizeof(iabuf), vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1);
    01695          }
    01696          if (pr0->set_rtp_peer(c0, t1.sin_addr.s_addr ? p1 : NULL, vt1.sin_addr.s_addr ? vp1 : NULL, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))
    01697             ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name);
    01698          memcpy(&ac1, &t1, sizeof(ac1));
    01699          memcpy(&vac1, &vt1, sizeof(vac1));
    01700          oldcodec1 = codec1;
    01701       }
    01702       if (inaddrcmp(&t0, &ac0) || (vp0 && inaddrcmp(&vt0, &vac0))) {
    01703          if (option_debug) {
    01704             ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
    01705                c0->name, ast_inet_ntoa(iabuf, sizeof(iabuf), t0.sin_addr), ntohs(t0.sin_port), codec0);
    01706             ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
    01707                c0->name, ast_inet_ntoa(iabuf, sizeof(iabuf), ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0);
    01708          }
    01709          if (pr1->set_rtp_peer(c1, t0.sin_addr.s_addr ? p0 : NULL, vt0.sin_addr.s_addr ? vp0 : NULL, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))
    01710             ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name);
    01711          memcpy(&ac0, &t0, sizeof(ac0));
    01712          memcpy(&vac0, &vt0, sizeof(vac0));
    01713          oldcodec0 = codec0;
    01714       }
    01715       who = ast_waitfor_n(cs, 2, &timeoutms);
    01716       if (!who) {
    01717          if (!timeoutms) {
    01718             if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
    01719                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
    01720             if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
    01721                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
    01722             return AST_BRIDGE_RETRY;
    01723          }
    01724          if (option_debug)
    01725             ast_log(LOG_DEBUG, "Ooh, empty read...\n");
    01726          /* check for hangup / whentohangup */
    01727          if (ast_check_hangup(c0) || ast_check_hangup(c1))
    01728             break;
    01729          continue;
    01730       }
    01731       f = ast_read(who);
    01732       if (!f || ((f->frametype == AST_FRAME_DTMF) &&
    01733                (((who == c0) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) ||
    01734                 ((who == c1) && (flags & AST_BRIDGE_DTMF_CHANNEL_1))))) {
    01735          *fo = f;
    01736          *rc = who;
    01737          if (option_debug)
    01738             ast_log(LOG_DEBUG, "Oooh, got a %s\n", f ? "digit" : "hangup");
    01739          if ((c0->tech_pvt == pvt0) && (!c0->_softhangup)) {
    01740             if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
    01741                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
    01742          }
    01743          if ((c1->tech_pvt == pvt1) && (!c1->_softhangup)) {
    01744             if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
    01745                ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
    01746          }
    01747          return AST_BRIDGE_COMPLETE;
    01748       } else if ((f->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
    01749          if ((f->subclass == AST_CONTROL_HOLD) || (f->subclass == AST_CONTROL_UNHOLD) ||
    01750              (f->subclass == AST_CONTROL_VIDUPDATE)) {
    01751             ast_indicate(who == c0 ? c1 : c0, f->subclass);
    01752             ast_frfree(f);
    01753          } else {
    01754             *fo = f;
    01755             *rc = who;
    01756             ast_log(LOG_DEBUG, "Got a FRAME_CONTROL (%d) frame on channel %s\n", f->subclass, who->name);
    01757             return AST_BRIDGE_COMPLETE;
    01758          }
    01759       } else {
    01760          if ((f->frametype == AST_FRAME_DTMF) ||
    01761             (f->frametype == AST_FRAME_VOICE) ||
    01762             (f->frametype == AST_FRAME_VIDEO)) {
    01763             /* Forward voice or DTMF frames if they happen upon us */
    01764             if (who == c0) {
    01765                ast_write(c1, f);
    01766             } else if (who == c1) {
    01767                ast_write(c0, f);
    01768             }
    01769          }
    01770          ast_frfree(f);
    01771       }
    01772       /* Swap priority not that it's a big deal at this point */
    01773       cs[2] = cs[0];
    01774       cs[0] = cs[1];
    01775       cs[1] = cs[2];
    01776
    01777    }
    01778
    01779    if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
    01780       ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
    01781    if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
    01782       ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
    01783
    01784    return AST_BRIDGE_FAILED;
    01785 }

void ast_rtp_destroy | ( | struct ast_rtp * | rtp | ) |

Definition at line 1105 of file rtp.c.

References ast_io_remove(), ast_smoother_free(), free, ast_rtp::io, ast_rtp::ioid, ast_rtp::rtcp, ast_rtcp::s, ast_rtp::s, and ast_rtp::smoother.

Referenced by __oh323_destroy(), __sip_destroy(), cleanup_connection(), destroy_endpoint(), mgcp_hangup(), skinny_hangup(), start_rtp(), and unalloc_sub().

    01106 {
    01107    if (rtp->smoother)
    01108       ast_smoother_free(rtp->smoother);
    01109    if (rtp->ioid)
    01110       ast_io_remove(rtp->io, rtp->ioid);
    01111    if (rtp->s > -1)
    01112       close(rtp->s);
    01113    if (rtp->rtcp) {
    01114       close(rtp->rtcp->s);
    01115       free(rtp->rtcp);
    01116    }
    01117    free(rtp);
    01118 }

int ast_rtp_fd | ( | struct ast_rtp * | rtp | ) |

Definition at line 153 of file rtp.c.

References ast_rtp::s.

Referenced by __oh323_new(), mgcp_new(), sip_new(), skinny_new(), and start_rtp().

    00154 {
    00155    return rtp->s;
    00156 }

void ast_rtp_get_current_formats | ( | struct ast_rtp * | rtp,
|  | int * | astFormats,
|  | int * | nonAstFormats |
| ) |  |  |

Definition at line 782 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, and MAX_RTP_PT.

Referenced by process_sdp().

    00783                                                    {
    00784    int pt;
    00785
    00786    *astFormats = *nonAstFormats = 0;
    00787    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
    00788       if (rtp->current_RTP_PT[pt].isAstFormat) {
    00789          *astFormats |= rtp->current_RTP_PT[pt].code;
    00790       } else {
    00791          *nonAstFormats |= rtp->current_RTP_PT[pt].code;
    00792       }
    00793    }
    00794 }

int ast_rtp_get_peer | ( | struct ast_rtp * | rtp,
|  | struct sockaddr_in * | them |
| ) |  |  |

Definition at line 1057 of file rtp.c.

References ast_rtp::them.

Referenced by add_sdp(), ast_rtp_bridge(), do_monitor(), oh323_set_rtp_peer(), sip_set_rtp_peer(), and transmit_modify_with_sdp().

    01058 {
    01059    if ((them->sin_family != AF_INET) ||
    01060        (them->sin_port != rtp->them.sin_port) ||
    01061        (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
    01062       them->sin_family = AF_INET;
    01063       them->sin_port = rtp->them.sin_port;
    01064       them->sin_addr = rtp->them.sin_addr;
    01065       return 1;
    01066    }
    01067    return 0;
    01068 }

void ast_rtp_get_us | ( | struct ast_rtp * | rtp,
|  | struct sockaddr_in * | us |
| ) |  |  |

Definition at line 1070 of file rtp.c.

References ast_rtp::us.

Referenced by add_sdp(), external_rtp_create(), handle_message(), and oh323_set_rtp_peer().

    01071 {
    01072    memcpy(us, &rtp->us, sizeof(rtp->us));
    01073 }

void ast_rtp_init | ( | void |  | ) |

Definition at line 1913 of file rtp.c.

References ast_cli_register(), and ast_rtp_reload().

Referenced by main().

    01914 {
    01915    ast_cli_register(&cli_debug);
    01916    ast_cli_register(&cli_debug_ip);
    01917    ast_cli_register(&cli_no_debug);
    01918    ast_rtp_reload();
    01919 }

int ast_rtp_lookup_code | ( | struct ast_rtp * | rtp,
|  | const int | isAstFormat,
|  | const int | code |
| ) |  |  |

Definition at line 822 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.

Referenced by add_codec_to_sdp(), add_noncodec_to_sdp(), add_sdp(), ast_rtp_sendcng(), ast_rtp_senddigit(), and ast_rtp_write().

    00822                                                                                     {
    00823
    00824    int pt;
    00825
    00826    if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
    00827       code == rtp->rtp_lookup_code_cache_code) {
    00828
    00829       /* Use our cached mapping, to avoid the overhead of the loop below */
    00830       return rtp->rtp_lookup_code_cache_result;
    00831    }
    00832
    00833    /* Check the dynamic list first */
    00834    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
    00835       if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
    00836          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
    00837          rtp->rtp_lookup_code_cache_code = code;
    00838          rtp->rtp_lookup_code_cache_result = pt;
    00839          return pt;
    00840       }
    00841    }
    00842
    00843    /* Then the static list */
    00844    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
    00845       if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) {
    00846          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
    00847          rtp->rtp_lookup_code_cache_code = code;
    00848          rtp->rtp_lookup_code_cache_result = pt;
    00849          return pt;
    00850       }
    00851    }
    00852    return -1;
    00853 }

char* ast_rtp_lookup_mime_multiple | ( | char * | buf,
|  | int | size,
|  | const int | capability,
|  | const int | isAstFormat |
| ) |  |  |

Definition at line 867 of file rtp.c.

References ast_rtp_lookup_mime_subtype(), AST_RTP_MAX, format, and name.

Referenced by process_sdp().

    00868 {
    00869    int format;
    00870    unsigned len;
    00871    char *end = buf;
    00872    char *start = buf;
    00873
    00874    if (!buf || !size)
    00875       return NULL;
    00876
    00877    snprintf(end, size, "0x%x (", capability);
    00878
    00879    len = strlen(end);
    00880    end += len;
    00881    size -= len;
    00882    start = end;
    00883
    00884    for (format = 1; format < AST_RTP_MAX; format <<= 1) {
    00885       if (capability & format) {
    00886          const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format);
    00887          snprintf(end, size, "%s|", name);
    00888          len = strlen(end);
    00889          end += len;
    00890          size -= len;
    00891       }
    00892    }
    00893
    00894    if (start == end)
    00895       snprintf(start, size, "nothing)");
    00896    else if (size > 1)
    00897       *(end -1) = ')';
    00898
    00899    return buf;
    00900 }

char* ast_rtp_lookup_mime_subtype | ( | const int | isAstFormat,
|  | const int | code |
| ) |  |  |

Definition at line 855 of file rtp.c.

References rtpPayloadType::code, mimeTypes, and payloadType.

Referenced by add_codec_to_sdp(), add_noncodec_to_sdp(), add_sdp(), ast_rtp_lookup_mime_multiple(), transmit_connect_with_sdp(), and transmit_modify_with_sdp().

    00855                                                                          {
    00856
    00857    int i;
    00858
    00859    for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) {
    00860    if (mimeTypes[i].payloadType.code == code && mimeTypes[i].payloadType.isAstFormat == isAstFormat) {
    00861             return mimeTypes[i].subtype;
    00862       }
    00863    }
    00864    return "";
    00865 }

struct rtpPayloadType ast_rtp_lookup_pt | ( | struct ast_rtp * | rtp,
|  | int | pt |
| ) |  |  | `[read]`

Definition at line 803 of file rtp.c.

References rtpPayloadType::code, rtpPayloadType::isAstFormat, and MAX_RTP_PT.

Referenced by ast_rtp_read(), and setup_rtp_connection().

    00804 {
    00805    struct rtpPayloadType result;
    00806
    00807    result.isAstFormat = result.code = 0;
    00808    if (pt < 0 || pt > MAX_RTP_PT)
    00809       return result; /* bogus payload type */
    00810
    00811    /* Start with the negotiated codecs */
    00812    if (!rtp->rtp_offered_from_local)
    00813       result = rtp->current_RTP_PT[pt];
    00814
    00815    /* If it doesn't exist, check our static RTP type list, just in case */
    00816    if (!result.code)
    00817       result = static_RTP_PT[pt];
    00818    return result;
    00819 }

struct ast_rtp* ast_rtp_new | ( | struct sched_context * | sched,
|  | struct io_context * | io,
|  | int | rtcpenable,
|  | int | callbackmode |
| ) |  |  | `[read]`

Initializate a RTP session.

Parameters:

  | sched |
  | io |
  | rtcpenable |
  | callbackmode |

Returns:
  A representation (structure) of an RTP session.

Definition at line 1029 of file rtp.c.

References ast_rtp_new_with_bindaddr().

Referenced by start_rtp().

    01030 {
    01031    struct in_addr ia;
    01032
    01033    memset(&ia, 0, sizeof(ia));
    01034    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
    01035 }

struct ast_rtp* ast_rtp_new_with_bindaddr | ( | struct sched_context * | sched,
|  | struct io_context * | io,
|  | int | rtcpenable,
|  | int | callbackmode,
|  | struct in_addr | in |
| ) |  |  | `[read]`

Initializate a RTP session using an in_addr structure.

This fuction gets called by ast_rtp_new().

Parameters:

  | sched |
  | io |
  | rtcpenable |
  | callbackmode |
  | in |

Returns:
  A representation (structure) of an RTP session.

Definition at line 940 of file rtp.c.

References ast_io_add(), AST_IO_IN, ast_log(), ast_rtcp_new(), ast_rtp_pt_default(), free, ast_rtp::io, ast_rtp::ioid, LOG_ERROR, malloc, ast_rtp::rtcp, rtp_socket(), rtpread(), ast_rtcp::s, ast_rtp::s, ast_rtp::sched, ast_rtp::seqno, ast_rtp::ssrc, ast_rtp::them, ast_rtcp::us, and ast_rtp::us.

Referenced by ast_rtp_new(), oh323_alloc(), sip_alloc(), and start_rtp().

    00941 {
    00942    struct ast_rtp *rtp;
    00943    int x;
    00944    int first;
    00945    int startplace;
    00946    rtp = malloc(sizeof(struct ast_rtp));
    00947    if (!rtp)
    00948       return NULL;
    00949    memset(rtp, 0, sizeof(struct ast_rtp));
    00950    rtp->them.sin_family = AF_INET;
    00951    rtp->us.sin_family = AF_INET;
    00952    rtp->s = rtp_socket();
    00953    rtp->ssrc = rand();
    00954    rtp->seqno = rand() & 0xffff;
    00955    if (rtp->s < 0) {
    00956       free(rtp);
    00957       ast_log(LOG_ERROR, "Unable to allocate socket: %s\n", strerror(errno));
    00958       return NULL;
    00959    }
    00960    if (sched && rtcpenable) {
    00961       rtp->sched = sched;
    00962       rtp->rtcp = ast_rtcp_new();
    00963    }
    00964
    00965    /* Select a random port number in the range of possible RTP */
    00966    x = (rand() % (rtpend-rtpstart)) + rtpstart;
    00967    x = x & ~1;
    00968    /* Save it for future references. */
    00969    startplace = x;
    00970    /* Iterate tring to bind that port and incrementing it otherwise untill a port was found or no ports are available. */
    00971    for (;;) {
    00972       /* Must be an even port number by RTP spec */
    00973       rtp->us.sin_port = htons(x);
    00974       rtp->us.sin_addr = addr;
    00975       /* If there's rtcp, initialize it as well. */
    00976       if (rtp->rtcp) {
    00977          rtp->rtcp->us.sin_addr = addr;
    00978          rtp->rtcp->us.sin_port = htons(x + 1);
    00979       }
    00980       /* Try to bind it/them. */
    00981       if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) &&
    00982          (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us))))
    00983          break;
    00984       if (!first) {
    00985          /* Primary bind succeeded! Gotta recreate it */
    00986          close(rtp->s);
    00987          rtp->s = rtp_socket();
    00988       }
    00989       if (errno != EADDRINUSE) {
    00990          /* We got an error that wasn't expected, abort! */
    00991          ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno));
    00992          close(rtp->s);
    00993          if (rtp->rtcp) {
    00994             close(rtp->rtcp->s);
    00995             free(rtp->rtcp);
    00996          }
    00997          free(rtp);
    00998          return NULL;
    00999       }
    01000       /* The port was used, increment it (by two). */
    01001       x += 2;
    01002       /* Did we go over the limit ? */
    01003       if (x > rtpend)
    01004          /* then, start from the begingig. */
    01005          x = (rtpstart + 1) & ~1;
    01006       /* Check if we reached the place were we started. */
    01007       if (x == startplace) {
    01008          /* If so, there's no ports available. */
    01009          ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n");
    01010          close(rtp->s);
    01011          if (rtp->rtcp) {
    01012             close(rtp->rtcp->s);
    01013             free(rtp->rtcp);
    01014          }
    01015          free(rtp);
    01016          return NULL;
    01017       }
    01018    }
    01019    if (io && sched && callbackmode) {
    01020       /* Operate this one in a callback mode */
    01021       rtp->sched = sched;
    01022       rtp->io = io;
    01023       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
    01024    }
    01025    ast_rtp_pt_default(rtp);
    01026    return rtp;
    01027 }

void ast_rtp_offered_from_local | ( | struct ast_rtp * | rtp,
|  | int | local |
| ) |  |  |

Definition at line 796 of file rtp.c.

References ast_log(), LOG_WARNING, and ast_rtp::rtp_offered_from_local.

Referenced by transmit_connect_with_sdp(), transmit_invite(), transmit_modify_with_sdp(), transmit_reinvite_with_sdp(), and transmit_response_with_sdp().

    00796                                                                 {
    00797    if (rtp)
    00798       rtp->rtp_offered_from_local = local;
    00799    else
    00800       ast_log(LOG_WARNING, "rtp structure is null\n");
    00801 }

int ast_rtp_proto_register | ( | struct ast_rtp_protocol * | proto | ) |

Definition at line 1505 of file rtp.c.

References ast_log(), LOG_WARNING, ast_rtp_protocol::next, and ast_rtp_protocol::type.

Referenced by load_module(), and unload_module().

    01506 {
    01507    struct ast_rtp_protocol *cur;
    01508    cur = protos;
    01509    while(cur) {
    01510       if (cur->type == proto->type) {
    01511          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
    01512          return -1;
    01513       }
    01514       cur = cur->next;
    01515    }
    01516    proto->next = protos;
    01517    protos = proto;
    01518    return 0;
    01519 }

void ast_rtp_proto_unregister | ( | struct ast_rtp_protocol * | proto | ) |

Definition at line 1485 of file rtp.c.

References ast_rtp_protocol::next.

Referenced by unload_module().

    01486 {
    01487    struct ast_rtp_protocol *cur, *prev;
    01488
    01489    cur = protos;
    01490    prev = NULL;
    01491    while(cur) {
    01492       if (cur == proto) {
    01493          if (prev)
    01494             prev->next = proto->next;
    01495          else
    01496             protos = proto->next;
    01497          return;
    01498       }
    01499       prev = cur;
    01500       cur = cur->next;
    01501    }
    01502 }

void ast_rtp_pt_clear | ( | struct ast_rtp * | rtp | ) |

Definition at line 719 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.

Referenced by process_sdp().

    00720 {
    00721    int i;
    00722    if (!rtp)
    00723       return;
    00724
    00725    for (i = 0; i < MAX_RTP_PT; ++i) {
    00726       rtp->current_RTP_PT[i].isAstFormat = 0;
    00727       rtp->current_RTP_PT[i].code = 0;
    00728    }
    00729
    00730    rtp->rtp_lookup_code_cache_isAstFormat = 0;
    00731    rtp->rtp_lookup_code_cache_code = 0;
    00732    rtp->rtp_lookup_code_cache_result = 0;
    00733 }

void ast_rtp_pt_default | ( | struct ast_rtp * | rtp | ) |

Definition at line 735 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.

Referenced by ast_rtp_new_with_bindaddr().

    00736 {
    00737    int i;
    00738
    00739    /* Initialize to default payload types */
    00740    for (i = 0; i < MAX_RTP_PT; ++i) {
    00741       rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
    00742       rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
    00743    }
    00744
    00745    rtp->rtp_lookup_code_cache_isAstFormat = 0;
    00746    rtp->rtp_lookup_code_cache_code = 0;
    00747    rtp->rtp_lookup_code_cache_result = 0;
    00748 }

static int ast_rtp_raw_write | ( | struct ast_rtp * | rtp,
|  | struct ast_frame * | f,
|  | int | codec |
| ) |  |  | `[static]`

Definition at line 1256 of file rtp.c.

References AST_FORMAT_MAX_AUDIO, ast_inet_ntoa(), ast_log(), ast_set_flag, ast_test_flag, ast_verbose(), calc_txstamp(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, FLAG_NAT_ACTIVE, FLAG_NAT_INACTIVE, FLAG_NAT_INACTIVE_NOWARN, ast_rtp::lastdigitts, ast_rtp::lastovidtimestamp, ast_rtp::lastts, LOG_DEBUG, MAX_TIMESTAMP_SKEW, ast_rtp::nat, option_debug, put_unaligned_uint32(), rtp_debug_test_addr(), ast_rtp::s, ast_frame::samples, ast_rtp::seqno, ast_rtp::ssrc, ast_frame::subclass, and ast_rtp::them.

Referenced by ast_rtp_write().

    01257 {
    01258    unsigned char *rtpheader;
    01259    char iabuf[INET_ADDRSTRLEN];
    01260    int hdrlen = 12;
    01261    int res;
    01262    unsigned int ms;
    01263    int pred;
    01264    int mark = 0;
    01265
    01266    ms = calc_txstamp(rtp, &f->delivery);
    01267    /* Default prediction */
    01268    if (f->subclass < AST_FORMAT_MAX_AUDIO) {
    01269       pred = rtp->lastts + f->samples;
    01270
    01271       /* Re-calculate last TS */
    01272       rtp->lastts = rtp->lastts + ms * 8;
    01273       if (ast_tvzero(f->delivery)) {
    01274          /* If this isn't an absolute delivery time, Check if it is close to our prediction,
    01275             and if so, go with our prediction */
    01276          if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW)
    01277             rtp->lastts = pred;
    01278          else {
    01279             if (option_debug > 2)
    01280                ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms);
    01281             mark = 1;
    01282          }
    01283       }
    01284    } else {
    01285       mark = f->subclass & 0x1;
    01286       pred = rtp->lastovidtimestamp + f->samples;
    01287       /* Re-calculate last TS */
    01288       rtp->lastts = rtp->lastts + ms * 90;
    01289       /* If it's close to our prediction, go for it */
    01290       if (ast_tvzero(f->delivery)) {
    01291          if (abs(rtp->lastts - pred) < 7200) {
    01292             rtp->lastts = pred;
    01293             rtp->lastovidtimestamp += f->samples;
    01294          } else {
    01295             if (option_debug > 2)
    01296                ast_log(LOG_DEBUG, "Difference is %d, ms is %d (%d), pred/ts/samples %d/%d/%d\n", abs(rtp->lastts - pred), ms, ms * 90, rtp->lastts, pred, f->samples);
    01297             rtp->lastovidtimestamp = rtp->lastts;
    01298          }
    01299       }
    01300    }
    01301    /* If the timestamp for non-digit packets has moved beyond the timestamp
    01302       for digits, update the digit timestamp.
    01303    */
    01304    if (rtp->lastts > rtp->lastdigitts)
    01305       rtp->lastdigitts = rtp->lastts;
    01306
    01307    /* Get a pointer to the header */
    01308    rtpheader = (unsigned char *)(f->data - hdrlen);
    01309
    01310    put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (rtp->seqno) | (mark << 23)));
    01311    put_unaligned_uint32(rtpheader + 4, htonl(rtp->lastts));
    01312    put_unaligned_uint32(rtpheader + 8, htonl(rtp->ssrc));
    01313
    01314    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
    01315       res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
    01316       if (res <0) {
    01317          if (!rtp->nat || (rtp->nat && (ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_ACTIVE))) {
    01318             ast_log(LOG_DEBUG, "RTP Transmission error of packet %d to %s:%d: %s\n", rtp->seqno, ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno));
    01319          } else if ((ast_test_flag(rtp, FLAG_NAT_ACTIVE) == FLAG_NAT_INACTIVE) || rtpdebug) {
    01320             /* Only give this error message once if we are not RTP debugging */
    01321             if (option_debug || rtpdebug)
    01322                ast_log(LOG_DEBUG, "RTP NAT: Can't write RTP to private address %s:%d, waiting for other end to send audio...\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port));
    01323             ast_set_flag(rtp, FLAG_NAT_INACTIVE_NOWARN);
    01324          }
    01325       }
    01326
    01327       if(rtp_debug_test_addr(&rtp->them))
    01328          ast_verbose("Sent RTP packet to %s:%d (type %d, seq %u, ts %u, len %u)\n"
    01329                , ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port), codec, rtp->seqno, rtp->lastts,res - hdrlen);
    01330    }
    01331
    01332    rtp->seqno++;
    01333
    01334    return 0;
    01335 }

struct ast_frame* ast_rtp_read | ( | struct ast_rtp * | rtp | ) | `[read]`

Definition at line 428 of file rtp.c.

References ast_codec_get_samples(), AST_FORMAT_MAX_AUDIO, AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_NULL, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), AST_RTP_CISCO_DTMF, AST_RTP_CN, AST_RTP_DTMF, ast_rtp_lookup_pt(), ast_set_flag, ast_verbose(), calc_rxstamp(), rtpPayloadType::code, CRASH, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp::dtmfcount, ast_rtp::f, FLAG_NAT_ACTIVE, ast_frame::frametype, rtpPayloadType::isAstFormat, ast_rtp::lasteventseqn, ast_rtp::lastividtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxts, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, ast_rtp::nat, ast_frame::offset, option_debug, process_cisco_dtmf(), process_rfc2833(), process_rfc3389(), ast_rtp::rawdata, ast_rtp::resp, rtp_debug_test_addr(), ast_rtp::rxseqno, ast_rtp::rxssrc, ast_rtp::s, ast_frame::samples, send_dtmf(), ast_frame::src, ast_frame::subclass, and ast_rtp::them.

Referenced by mgcp_rtp_read(), oh323_rtp_read(), rtpread(), sip_rtp_read(), and skinny_rtp_read().

    00429 {
    00430    int res;
    00431    struct sockaddr_in sin;
    00432    socklen_t len;
    00433    unsigned int seqno;
    00434    int version;
    00435    int payloadtype;
    00436    int hdrlen = 12;
    00437    int padding;
    00438    int mark;
    00439    int ext;
    00440    int cc;
    00441    int x;
    00442    char iabuf[INET_ADDRSTRLEN];
    00443    unsigned int ssrc;
    00444    unsigned int timestamp;
    00445    unsigned int *rtpheader;
    00446    struct ast_frame *f;
    00447    static struct ast_frame null_frame = { AST_FRAME_NULL, };
    00448    struct rtpPayloadType rtpPT;
    00449
    00450    len = sizeof(sin);
    00451
    00452    /* Cache where the header will go */
    00453    res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,
    00454                0, (struct sockaddr *)&sin, &len);
    00455
    00456
    00457    rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET);
    00458    if (res < 0) {
    00459       if (errno == EBADF)
    00460          CRASH;
    00461       if (errno != EAGAIN) {
    00462          ast_log(LOG_WARNING, "RTP Read error: %s.  Hanging up now.\n", strerror(errno));
    00463          return NULL;
    00464       }
    00465       return &null_frame;
    00466    }
    00467    if (res < hdrlen) {
    00468       ast_log(LOG_WARNING, "RTP Read too short\n");
    00469       return &null_frame;
    00470    }
    00471
    00472    /* Ignore if the other side hasn't been given an address
    00473       yet.  */
    00474    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
    00475       return &null_frame;
    00476
    00477    if (rtp->nat) {
    00478       /* Send to whoever sent to us */
    00479       if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
    00480           (rtp->them.sin_port != sin.sin_port)) {
    00481          memcpy(&rtp->them, &sin, sizeof(rtp->them));
    00482          rtp->rxseqno = 0;
    00483          ast_set_flag(rtp, FLAG_NAT_ACTIVE);
    00484          if (option_debug || rtpdebug)
    00485             ast_log(LOG_DEBUG, "RTP NAT: Got audio from other end. Now sending to address %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port));
    00486       }
    00487    }
    00488
    00489    /* Get fields */
    00490    seqno = ntohl(rtpheader[0]);
    00491
    00492    /* Check RTP version */
    00493    version = (seqno & 0xC0000000) >> 30;
    00494    if (version != 2)
    00495       return &null_frame;
    00496
    00497    payloadtype = (seqno & 0x7f0000) >> 16;
    00498    padding = seqno & (1 << 29);
    00499    mark = seqno & (1 << 23);
    00500    ext = seqno & (1 << 28);
    00501    cc = (seqno & 0xF000000) >> 24;
    00502    seqno &= 0xffff;
    00503    timestamp = ntohl(rtpheader[1]);
    00504    ssrc = ntohl(rtpheader[2]);
    00505
    00506    if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) {
    00507       if (option_debug || rtpdebug)
    00508          ast_log(LOG_DEBUG, "Forcing Marker bit, because SSRC has changed\n");
    00509       mark = 1;
    00510    }
    00511
    00512    rtp->rxssrc = ssrc;
    00513
    00514    if (padding) {
    00515       /* Remove padding bytes */
    00516       res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1];
    00517    }
    00518
    00519    if (cc) {
    00520       /* CSRC fields present */
    00521       hdrlen += cc*4;
    00522    }
    00523
    00524    if (ext) {
    00525       /* RTP Extension present */
    00526       hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2;
    00527       hdrlen += 4;
    00528    }
    00529
    00530    if (res < hdrlen) {
    00531       ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen);
    00532       return &null_frame;
    00533    }
    00534
    00535    if(rtp_debug_test_addr(&sin))
    00536       ast_verbose("Got RTP packet from %s:%u (type %d, seq %u, ts %u, len %d)\n"
    00537          , ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen);
    00538
    00539    rtpPT = ast_rtp_lookup_pt(rtp, payloadtype);
    00540    if (!rtpPT.isAstFormat) {
    00541       /* This is special in-band data that's not one of our codecs */
    00542       if (rtpPT.code == AST_RTP_DTMF) {
    00543          /* It's special -- rfc2833 process it */
    00544          if(rtp_debug_test_addr(&sin)) {
    00545             unsigned char *data;
    00546             unsigned int event;
    00547             unsigned int event_end;
    00548             unsigned int duration;
    00549             data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen;
    00550             event = ntohl(*((unsigned int *)(data)));
    00551             event >>= 24;
    00552             event_end = ntohl(*((unsigned int *)(data)));
    00553             event_end <<= 8;
    00554             event_end >>= 24;
    00555             duration = ntohl(*((unsigned int *)(data)));
    00556             duration &= 0xFFFF;
    00557             ast_verbose("Got rfc2833 RTP packet from %s:%d (type %d, seq %d, ts %d, len %d, mark %d, event %08x, end %d, duration %d) \n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp, res - hdrlen, (mark?1:0), event, ((event_end & 0x80)?1:0), duration);
    00558          }
    00559          if (rtp->lasteventseqn <= seqno || rtp->resp == 0 || (rtp->lasteventseqn >= 65530 && seqno <= 6)) {
    00560             f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno);
    00561             rtp->lasteventseqn = seqno;
    00562          } else
    00563             f = NULL;
    00564          if (f)
    00565             return f;
    00566          else
    00567             return &null_frame;
    00568       } else if (rtpPT.code == AST_RTP_CISCO_DTMF) {
    00569          /* It's really special -- process it the Cisco way */
    00570          if (rtp->lasteventseqn <= seqno || rtp->resp == 0 || (rtp->lasteventseqn >= 65530 && seqno <= 6)) {
    00571             f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
    00572             rtp->lasteventseqn = seqno;
    00573          } else
    00574             f = NULL;
    00575             if (f)
    00576             return f;
    00577          else
    00578             return &null_frame;
    00579       } else if (rtpPT.code == AST_RTP_CN) {
    00580          /* Comfort Noise */
    00581          f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
    00582          if (f)
    00583             return f;
    00584          else
    00585             return &null_frame;
    00586       } else {
    00587          ast_log(LOG_NOTICE, "Unknown RTP codec %d received\n", payloadtype);
    00588          return &null_frame;
    00589       }
    00590    }
    00591    rtp->f.subclass = rtpPT.code;
    00592    if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO)
    00593       rtp->f.frametype = AST_FRAME_VOICE;
    00594    else
    00595       rtp->f.frametype = AST_FRAME_VIDEO;
    00596    rtp->lastrxformat = rtp->f.subclass;
    00597
    00598    if (!rtp->lastrxts)
    00599       rtp->lastrxts = timestamp;
    00600
    00601    if (rtp->rxseqno) {
    00602       for (x=rtp->rxseqno + 1; x < seqno; x++) {
    00603          /* Queue empty frames */
    00604          rtp->f.mallocd = 0;
    00605          rtp->f.datalen = 0;
    00606          rtp->f.data = NULL;
    00607          rtp->f.offset = 0;
    00608          rtp->f.samples = 0;
    00609          rtp->f.src = "RTPMissedFrame";
    00610       }
    00611    }
    00612    rtp->rxseqno = seqno;
    00613
    00614    if (rtp->dtmfcount) {
    00615 #if 0
    00616       printf("dtmfcount was %d\n", rtp->dtmfcount);
    00617 #endif
    00618       rtp->dtmfcount -= (timestamp - rtp->lastrxts);
    00619       if (rtp->dtmfcount < 0)
    00620          rtp->dtmfcount = 0;
    00621 #if 0
    00622       if (dtmftimeout != rtp->dtmfcount)
    00623          printf("dtmfcount is %d\n", rtp->dtmfcount);
    00624 #endif
    00625    }
    00626    rtp->lastrxts = timestamp;
    00627
    00628    /* Send any pending DTMF */
    00629    if (rtp->resp && !rtp->dtmfcount) {
    00630       if (option_debug)
    00631          ast_log(LOG_DEBUG, "Sending pending DTMF\n");
    00632       return send_dtmf(rtp);
    00633    }
    00634    rtp->f.mallocd = 0;
    00635    rtp->f.datalen = res - hdrlen;
    00636    rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
    00637    rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
    00638    if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) {
    00639       rtp->f.samples = ast_codec_get_samples(&rtp->f);
    00640       if (rtp->f.subclass == AST_FORMAT_SLINEAR)
    00641          ast_frame_byteswap_be(&rtp->f);
    00642       calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
    00643    } else {
    00644       /* Video -- samples is # of samples vs. 90000 */
    00645       if (!rtp->lastividtimestamp)
    00646          rtp->lastividtimestamp = timestamp;
    00647       rtp->f.samples = timestamp - rtp->lastividtimestamp;
    00648       rtp->lastividtimestamp = timestamp;
    00649       rtp->f.delivery.tv_sec = 0;
    00650       rtp->f.delivery.tv_usec = 0;
    00651       if (mark)
    00652          rtp->f.subclass |= 0x1;
    00653
    00654    }
    00655    rtp->f.src = "RTP";
    00656    return &rtp->f;
    00657 }

void ast_rtp_reload | ( | void |  | ) |

Definition at line 1857 of file rtp.c.

References ast_config_destroy(), ast_config_load(), ast_false(), ast_log(), ast_variable_retrieve(), ast_verbose(), cfg, DEFAULT_DTMF_TIMEOUT, LOG_WARNING, option_verbose, s, and VERBOSE_PREFIX_2.

Referenced by ast_module_reload(), ast_rtp_init(), and main().

    01858 {
    01859    struct ast_config *cfg;
    01860    char *s;
    01861
    01862    rtpstart = 5000;
    01863    rtpend = 31000;
    01864    dtmftimeout = DEFAULT_DTMF_TIMEOUT;
    01865    cfg = ast_config_load("rtp.conf");
    01866    if (cfg) {
    01867       if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
    01868          rtpstart = atoi(s);
    01869          if (rtpstart < 1024)
    01870             rtpstart = 1024;
    01871          if (rtpstart > 65535)
    01872             rtpstart = 65535;
    01873       }
    01874       if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
    01875          rtpend = atoi(s);
    01876          if (rtpend < 1024)
    01877             rtpend = 1024;
    01878          if (rtpend > 65535)
    01879             rtpend = 65535;
    01880       }
    01881       if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
    01882 #ifdef SO_NO_CHECK
    01883          if (ast_false(s))
    01884             nochecksums = 1;
    01885          else
    01886             nochecksums = 0;
    01887 #else
    01888          if (ast_false(s))
    01889             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
    01890 #endif
    01891       }
    01892       if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
    01893          dtmftimeout = atoi(s);
    01894          if ((dtmftimeout < 0) || (dtmftimeout > 20000)) {
    01895             ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
    01896                dtmftimeout, DEFAULT_DTMF_TIMEOUT);
    01897             dtmftimeout = DEFAULT_DTMF_TIMEOUT;
    01898          };
    01899       }
    01900       ast_config_destroy(cfg);
    01901    }
    01902    if (rtpstart >= rtpend) {
    01903       ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
    01904       rtpstart = 5000;
    01905       rtpend = 31000;
    01906    }
    01907    if (option_verbose > 1)
    01908       ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
    01909
    01910 }

void ast_rtp_reset | ( | struct ast_rtp * | rtp | ) |

Definition at line 1085 of file rtp.c.

References ast_rtp::dtmfcount, ast_rtp::dtmfduration, ast_rtp::dtmfmute, ast_rtp::lastdigitts, ast_rtp::lasteventendseqn, ast_rtp::lasteventseqn, ast_rtp::lastividtimestamp, ast_rtp::lastovidtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxts, ast_rtp::lastts, ast_rtp::lasttxformat, ast_rtp::rxcore, ast_rtp::rxseqno, ast_rtp::seqno, and ast_rtp::txcore.

    01086 {
    01087    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
    01088    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
    01089    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
    01090    rtp->lastts = 0;
    01091    rtp->lastdigitts = 0;
    01092    rtp->lastrxts = 0;
    01093    rtp->lastividtimestamp = 0;
    01094    rtp->lastovidtimestamp = 0;
    01095    rtp->lasteventseqn = 0;
    01096    rtp->lasteventendseqn = 0;
    01097    rtp->lasttxformat = 0;
    01098    rtp->lastrxformat = 0;
    01099    rtp->dtmfcount = 0;
    01100    rtp->dtmfduration = 0;
    01101    rtp->seqno = 0;
    01102    rtp->rxseqno = 0;
    01103 }

int ast_rtp_sendcng | ( | struct ast_rtp * | rtp,
|  | int | level |
| ) |  |  |

Definition at line 1221 of file rtp.c.

References ast_inet_ntoa(), ast_log(), AST_RTP_CN, ast_rtp_lookup_code(), ast_tvadd(), ast_verbose(), ast_rtp::dtmfmute, ast_rtp::lastts, LOG_ERROR, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.

Referenced by do_monitor().

    01222 {
    01223    unsigned int *rtpheader;
    01224    int hdrlen = 12;
    01225    int res;
    01226    int payload;
    01227    char data[256];
    01228    char iabuf[INET_ADDRSTRLEN];
    01229    level = 127 - (level & 0x7f);
    01230    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN);
    01231
    01232    /* If we have no peer, return immediately */
    01233    if (!rtp->them.sin_addr.s_addr)
    01234       return 0;
    01235
    01236    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
    01237
    01238    /* Get a pointer to the header */
    01239    rtpheader = (unsigned int *)data;
    01240    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
    01241    rtpheader[1] = htonl(rtp->lastts);
    01242    rtpheader[2] = htonl(rtp->ssrc);
    01243    data[12] = level;
    01244    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
    01245       res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
    01246       if (res <0)
    01247          ast_log(LOG_ERROR, "RTP Comfort Noise Transmission error to %s:%d: %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno));
    01248       if(rtp_debug_test_addr(&rtp->them))
    01249          ast_verbose("Sent Comfort Noise RTP packet to %s:%d (type %d, seq %d, ts %d, len %d)\n"
    01250                , ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen);
    01251
    01252    }
    01253    return 0;
    01254 }

int ast_rtp_senddigit | ( | struct ast_rtp * | rtp,
|  | char | digit |
| ) |  |  |

Definition at line 1139 of file rtp.c.

References ast_inet_ntoa(), ast_log(), AST_RTP_DTMF, ast_rtp_lookup_code(), ast_tvadd(), ast_verbose(), ast_rtp::dtmfmute, ast_rtp::lastdigitts, LOG_ERROR, LOG_WARNING, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.

Referenced by oh323_digit(), and sip_senddigit().

    01140 {
    01141    unsigned int *rtpheader;
    01142    int hdrlen = 12;
    01143    int res;
    01144    int x;
    01145    int payload;
    01146    char data[256];
    01147    char iabuf[INET_ADDRSTRLEN];
    01148
    01149    if ((digit <= '9') && (digit >= '0'))
    01150       digit -= '0';
    01151    else if (digit == '*')
    01152       digit = 10;
    01153    else if (digit == '#')
    01154       digit = 11;
    01155    else if ((digit >= 'A') && (digit <= 'D'))
    01156       digit = digit - 'A' + 12;
    01157    else if ((digit >= 'a') && (digit <= 'd'))
    01158       digit = digit - 'a' + 12;
    01159    else {
    01160       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
    01161       return -1;
    01162    }
    01163    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF);
    01164
    01165    /* If we have no peer, return immediately */
    01166    if (!rtp->them.sin_addr.s_addr)
    01167       return 0;
    01168
    01169    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
    01170
    01171    /* Get a pointer to the header */
    01172    rtpheader = (unsigned int *)data;
    01173    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
    01174    rtpheader[1] = htonl(rtp->lastdigitts);
    01175    rtpheader[2] = htonl(rtp->ssrc);
    01176    rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (0));
    01177    for (x = 0; x < 6; x++) {
    01178       if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
    01179          res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
    01180          if (res < 0)
    01181             ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
    01182                ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr),
    01183                ntohs(rtp->them.sin_port), strerror(errno));
    01184          if (rtp_debug_test_addr(&rtp->them))
    01185             ast_verbose("Sent RTP packet to %s:%d (type %d, seq %u, ts %u, len %u)\n",
    01186                    ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr),
    01187                    ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
    01188       }
    01189       /* Sequence number of last two end packets does not get incremented */
    01190       if (x < 3)
    01191          rtp->seqno++;
    01192       /* Clear marker bit and set seqno */
    01193       rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
    01194       /* For the last three packets, set the duration and the end bit */
    01195       if (x == 2) {
    01196 #if 0
    01197          /* No, this is wrong...  Do not increment lastdigitts, that's not according
    01198             to the RFC, as best we can determine */
    01199          rtp->lastdigitts++; /* or else the SPA3000 will click instead of beeping... */
    01200          rtpheader[1] = htonl(rtp->lastdigitts);
    01201 #endif
    01202          /* Make duration 800 (100ms) */
    01203          rtpheader[3] |= htonl((800));
    01204          /* Set the End bit */
    01205          rtpheader[3] |= htonl((1 << 23));
    01206       }
    01207    }
    01208    /* Increment the digit timestamp by 120ms, to ensure that digits
    01209       sent sequentially with no intervening non-digit packets do not
    01210       get sent with the same timestamp, and that sequential digits
    01211       have some 'dead air' in between them
    01212    */
    01213    rtp->lastdigitts += 960;
    01214    /* Increment the sequence number to reflect the last packet
    01215       that was sent
    01216    */
    01217    rtp->seqno++;
    01218    return 0;
    01219 }

void ast_rtp_set_callback | ( | struct ast_rtp * | rtp,
|  | ast_rtp_callback | callback |
| ) |  |  |

Definition at line 170 of file rtp.c.

References ast_rtp::callback.

Referenced by start_rtp().

    00171 {
    00172    rtp->callback = callback;
    00173 }

void ast_rtp_set_data | ( | struct ast_rtp * | rtp,
|  | void * | data |
| ) |  |  |

Definition at line 165 of file rtp.c.

References ast_rtp::data.

Referenced by start_rtp().

    00166 {
    00167    rtp->data = data;
    00168 }

void ast_rtp_set_m_type | ( | struct ast_rtp * | rtp,
|  | int | pt |
| ) |  |  |

Definition at line 753 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, and MAX_RTP_PT.

Referenced by process_sdp().

    00753                                                      {
    00754    if (pt < 0 || pt > MAX_RTP_PT)
    00755       return; /* bogus payload type */
    00756
    00757    if (static_RTP_PT[pt].code != 0) {
    00758       rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
    00759    }
    00760 }

void ast_rtp_set_peer | ( | struct ast_rtp * | rtp,
|  | struct sockaddr_in * | them |
| ) |  |  |

Definition at line 1046 of file rtp.c.

References ast_rtp::rtcp, ast_rtp::rxseqno, ast_rtcp::them, and ast_rtp::them.

Referenced by handle_message(), process_sdp(), and setup_rtp_connection().

    01047 {
    01048    rtp->them.sin_port = them->sin_port;
    01049    rtp->them.sin_addr = them->sin_addr;
    01050    if (rtp->rtcp) {
    01051       rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1);
    01052       rtp->rtcp->them.sin_addr = them->sin_addr;
    01053    }
    01054    rtp->rxseqno = 0;
    01055 }

void ast_rtp_set_rtpmap_type | ( | struct ast_rtp * | rtp,
|  | int | pt,
|  | char * | mimeType,
|  | char * | mimeSubtype |
| ) |  |  |

Definition at line 764 of file rtp.c.

References ast_rtp::current_RTP_PT, MAX_RTP_PT, mimeTypes, subtype, and type.

Referenced by process_sdp(), and set_dtmf_payload().

    00765                                              {
    00766    int i;
    00767
    00768    if (pt < 0 || pt > MAX_RTP_PT)
    00769          return; /* bogus payload type */
    00770
    00771    for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) {
    00772       if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
    00773            strcasecmp(mimeType, mimeTypes[i].type) == 0) {
    00774          rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
    00775       return;
    00776       }
    00777    }
    00778 }

void ast_rtp_setnat | ( | struct ast_rtp * | rtp,
|  | int | nat |
| ) |  |  |

Definition at line 175 of file rtp.c.

References ast_rtp::nat.

Referenced by check_user_full(), create_addr(), create_addr_from_peer(), oh323_request(), oh323_rtp_read(), sip_alloc(), and start_rtp().

    00176 {
    00177    rtp->nat = nat;
    00178 }

int ast_rtp_settos | ( | struct ast_rtp * | rtp,
|  | int | tos |
| ) |  |  |

Definition at line 1037 of file rtp.c.

References ast_log(), LOG_WARNING, and ast_rtp::s.

Referenced by oh323_alloc(), and sip_alloc().

    01038 {
    01039    int res;
    01040
    01041    if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos))))
    01042       ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
    01043    return res;
    01044 }

void ast_rtp_stop | ( | struct ast_rtp * | rtp | ) |

Definition at line 1075 of file rtp.c.

References ast_rtp::rtcp, ast_rtcp::them, and ast_rtp::them.

Referenced by handle_request_bye(), handle_request_cancel(), handle_response(), and process_sdp().

    01076 {
    01077    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
    01078    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
    01079    if (rtp->rtcp) {
    01080       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
    01081       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->them.sin_port));
    01082    }
    01083 }

int ast_rtp_write | ( | struct ast_rtp * | rtp,
|  | struct ast_frame * | _f |
| ) |  |  |

Definition at line 1337 of file rtp.c.

References AST_FORMAT_ADPCM, AST_FORMAT_ALAW, AST_FORMAT_G723_1, AST_FORMAT_G726, AST_FORMAT_G729A, AST_FORMAT_GSM, AST_FORMAT_H261, AST_FORMAT_H263, AST_FORMAT_H263_PLUS, AST_FORMAT_ILBC, AST_FORMAT_LPC10, AST_FORMAT_SLINEAR, AST_FORMAT_SPEEX, AST_FORMAT_ULAW, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup(), ast_frfree(), ast_getformatname(), ast_log(), ast_rtp_lookup_code(), ast_rtp_raw_write(), ast_smoother_feed, ast_smoother_feed_be, AST_SMOOTHER_FLAG_G729, ast_smoother_free(), ast_smoother_new(), ast_smoother_read(), ast_smoother_set_flags(), ast_frame::datalen, ast_frame::frametype, ast_rtp::lasttxformat, LOG_DEBUG, LOG_WARNING, ast_frame::offset, option_debug, ast_rtp::smoother, ast_frame::subclass, and ast_rtp::them.

Referenced by mgcp_write(), oh323_write(), sip_write(), and skinny_write().

    01338 {
    01339    struct ast_frame *f;
    01340    int codec;
    01341    int hdrlen = 12;
    01342    int subclass;
    01343
    01344
    01345    /* If we have no peer, return immediately */
    01346    if (!rtp->them.sin_addr.s_addr)
    01347       return 0;
    01348
    01349    /* If there is no data length, return immediately */
    01350    if (!_f->datalen)
    01351       return 0;
    01352
    01353    /* Make sure we have enough space for RTP header */
    01354    if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) {
    01355       ast_log(LOG_WARNING, "RTP can only send voice\n");
    01356       return -1;
    01357    }
    01358
    01359    subclass = _f->subclass;
    01360    if (_f->frametype == AST_FRAME_VIDEO)
    01361       subclass &= ~0x1;
    01362
    01363    codec = ast_rtp_lookup_code(rtp, 1, subclass);
    01364    if (codec < 0) {
    01365       ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass));
    01366       return -1;
    01367    }
    01368
    01369    if (rtp->lasttxformat != subclass) {
    01370       /* New format, reset the smoother */
    01371       if (option_debug)
    01372          ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
    01373       rtp->lasttxformat = subclass;
    01374       if (rtp->smoother)
    01375          ast_smoother_free(rtp->smoother);
    01376       rtp->smoother = NULL;
    01377    }
    01378
    01379
    01380    switch(subclass) {
    01381    case AST_FORMAT_SLINEAR:
    01382       if (!rtp->smoother) {
    01383          rtp->smoother = ast_smoother_new(320);
    01384       }
    01385       if (!rtp->smoother) {
    01386          ast_log(LOG_WARNING, "Unable to create smoother :(\n");
    01387          return -1;
    01388       }
    01389       ast_smoother_feed_be(rtp->smoother, _f);
    01390
    01391       while((f = ast_smoother_read(rtp->smoother)))
    01392          ast_rtp_raw_write(rtp, f, codec);
    01393       break;
    01394    case AST_FORMAT_ULAW:
    01395    case AST_FORMAT_ALAW:
    01396       if (!rtp->smoother) {
    01397          rtp->smoother = ast_smoother_new(160);
    01398       }
    01399       if (!rtp->smoother) {
    01400          ast_log(LOG_WARNING, "Unable to create smoother :(\n");
    01401          return -1;
    01402       }
    01403       ast_smoother_feed(rtp->smoother, _f);
    01404
    01405       while((f = ast_smoother_read(rtp->smoother)))
    01406          ast_rtp_raw_write(rtp, f, codec);
    01407       break;
    01408    case AST_FORMAT_ADPCM:
    01409    case AST_FORMAT_G726:
    01410       if (!rtp->smoother) {
    01411          rtp->smoother = ast_smoother_new(80);
    01412       }
    01413       if (!rtp->smoother) {
    01414          ast_log(LOG_WARNING, "Unable to create smoother :(\n");
    01415          return -1;
    01416       }
    01417       ast_smoother_feed(rtp->smoother, _f);
    01418
    01419       while((f = ast_smoother_read(rtp->smoother)))
    01420          ast_rtp_raw_write(rtp, f, codec);
    01421       break;
    01422    case AST_FORMAT_G729A:
    01423       if (!rtp->smoother) {
    01424          rtp->smoother = ast_smoother_new(20);
    01425          if (rtp->smoother)
    01426             ast_smoother_set_flags(rtp->smoother, AST_SMOOTHER_FLAG_G729);
    01427       }
    01428       if (!rtp->smoother) {
    01429          ast_log(LOG_WARNING, "Unable to create g729 smoother :(\n");
    01430          return -1;
    01431       }
    01432       ast_smoother_feed(rtp->smoother, _f);
    01433
    01434       while((f = ast_smoother_read(rtp->smoother)))
    01435          ast_rtp_raw_write(rtp, f, codec);
    01436       break;
    01437    case AST_FORMAT_GSM:
    01438       if (!rtp->smoother) {
    01439          rtp->smoother = ast_smoother_new(33);
    01440       }
    01441       if (!rtp->smoother) {
    01442          ast_log(LOG_WARNING, "Unable to create GSM smoother :(\n");
    01443          return -1;
    01444       }
    01445       ast_smoother_feed(rtp->smoother, _f);
    01446       while((f = ast_smoother_read(rtp->smoother)))
    01447          ast_rtp_raw_write(rtp, f, codec);
    01448       break;
    01449    case AST_FORMAT_ILBC:
    01450       if (!rtp->smoother) {
    01451          rtp->smoother = ast_smoother_new(50);
    01452       }
    01453       if (!rtp->smoother) {
    01454          ast_log(LOG_WARNING, "Unable to create ILBC smoother :(\n");
    01455          return -1;
    01456       }
    01457       ast_smoother_feed(rtp->smoother, _f);
    01458       while((f = ast_smoother_read(rtp->smoother)))
    01459          ast_rtp_raw_write(rtp, f, codec);
    01460       break;
    01461    default:
    01462       ast_log(LOG_WARNING, "Not sure about sending format %s packets\n", ast_getformatname(subclass));
    01463       /* fall through to... */
    01464    case AST_FORMAT_H261:
    01465    case AST_FORMAT_H263:
    01466    case AST_FORMAT_H263_PLUS:
    01467    case AST_FORMAT_G723_1:
    01468    case AST_FORMAT_LPC10:
    01469    case AST_FORMAT_SPEEX:
    01470            /* Don't buffer outgoing frames; send them one-per-packet: */
    01471       if (_f->offset < hdrlen) {
    01472          f = ast_frdup(_f);
    01473       } else {
    01474          f = _f;
    01475       }
    01476       ast_rtp_raw_write(rtp, f, codec);
    01477       if (f != _f)
    01478          ast_frfree(f);
    01479    }
    01480
    01481    return 0;
    01482 }

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

Definition at line 417 of file rtp.c.

References ast_tvadd(), ast_tvsub(), and ast_rtp::rxcore.

Referenced by ast_rtp_read(), and schedule_delivery().

    00418 {
    00419    struct timeval ts = ast_samp2tv( timestamp, 8000);
    00420    if (ast_tvzero(rtp->rxcore) || mark) {
    00421       rtp->rxcore = ast_tvsub(ast_tvnow(), ts);
    00422       /* Round to 20ms for nice, pretty timestamps */
    00423       rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 20000;
    00424    }
    00425    *tv = ast_tvadd(rtp->rxcore, ts);
    00426 }

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

Definition at line 1120 of file rtp.c.

References ast_rtp::txcore.

Referenced by ast_rtp_raw_write().

    01121 {
    01122    struct timeval t;
    01123    long ms;
    01124    if (ast_tvzero(rtp->txcore)) {
    01125       rtp->txcore = ast_tvnow();
    01126       /* Round to 20ms for nice, pretty timestamps */
    01127       rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
    01128    }
    01129    /* Use previous txcore if available */
    01130    t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
    01131    ms = ast_tvdiff_ms(t, rtp->txcore);
    01132    if (ms < 0)
    01133       ms = 0;
    01134    /* Use what we just got for next time */
    01135    rtp->txcore = t;
    01136    return (unsigned int) ms;
    01137 }

static struct ast_rtp_protocol* get_proto | ( | struct ast_channel * | chan | ) | `[static, read]`

Definition at line 1522 of file rtp.c.

References ast_rtp_protocol::next, ast_channel::type, and ast_rtp_protocol::type.

Referenced by ast_rtp_bridge().

    01523 {
    01524    struct ast_rtp_protocol *cur;
    01525
    01526    cur = protos;
    01527    while(cur) {
    01528       if (cur->type == chan->type) {
    01529          return cur;
    01530       }
    01531       cur = cur->next;
    01532    }
    01533    return NULL;
    01534 }

static struct ast_frame* process_cisco_dtmf | ( | struct ast_rtp * | rtp,
|  | unsigned char * | data,
|  | int | len |
| ) |  |  | `[static, read]`

Definition at line 224 of file rtp.c.

References ast_rtp::dtmfcount, ast_rtp::resp, and send_dtmf().

Referenced by ast_rtp_read().

    00225 {
    00226    unsigned int event;
    00227    char resp = 0;
    00228    struct ast_frame *f = NULL;
    00229    event = ntohl(*((unsigned int *)(data)));
    00230    event &= 0x001F;
    00231 #if 0
    00232    printf("Cisco Digit: %08x (len = %d)\n", event, len);
    00233 #endif
    00234    if (event < 10) {
    00235       resp = '0' + event;
    00236    } else if (event < 11) {
    00237       resp = '*';
    00238    } else if (event < 12) {
    00239       resp = '#';
    00240    } else if (event < 16) {
    00241       resp = 'A' + (event - 12);
    00242    } else if (event < 17) {
    00243       resp = 'X';
    00244    }
    00245    if (rtp->resp && (rtp->resp != resp)) {
    00246       f = send_dtmf(rtp);
    00247    }
    00248    rtp->resp = resp;
    00249    rtp->dtmfcount = dtmftimeout;
    00250    return f;
    00251 }

static struct ast_frame* process_rfc2833 | ( | struct ast_rtp * | rtp,
|  | unsigned char * | data,
|  | int | len,
|  | unsigned int | seqno |
| ) |  |  | `[static, read]`

Process RTP DTMF and events according to RFC 2833.

RFC 2833 is "RTP Payload for DTMF Digits, Telephony Tones and Telephony Signals".

Parameters:

  | rtp |
  | data |
  | len |
  | seqno |

Returns:

Definition at line 264 of file rtp.c.

References ast_log(), ast_rtp::dtmfcount, ast_rtp::dtmfduration, ast_rtp::lasteventendseqn, LOG_DEBUG, ast_rtp::resp, and send_dtmf().

Referenced by ast_rtp_read().

    00265 {
    00266    unsigned int event;
    00267    unsigned int event_end;
    00268    unsigned int duration;
    00269    char resp = 0;
    00270    struct ast_frame *f = NULL;
    00271    event = ntohl(*((unsigned int *)(data)));
    00272    event >>= 24;
    00273    event_end = ntohl(*((unsigned int *)(data)));
    00274    event_end <<= 8;
    00275    event_end >>= 24;
    00276    duration = ntohl(*((unsigned int *)(data)));
    00277    duration &= 0xFFFF;
    00278    if (rtpdebug)
    00279       ast_log(LOG_DEBUG, "- RTP 2833 Event: %08x (len = %d)\n", event, len);
    00280    if (event < 10) {
    00281       resp = '0' + event;
    00282    } else if (event < 11) {
    00283       resp = '*';
    00284    } else if (event < 12) {
    00285       resp = '#';
    00286    } else if (event < 16) {
    00287       resp = 'A' + (event - 12);
    00288    } else if (event < 17) {   /* Event 16: Hook flash */
    00289       resp = 'X';
    00290    }
    00291    if (rtp->resp && (rtp->resp != resp)) {
    00292       f = send_dtmf(rtp);
    00293    } else if(event_end & 0x80) {
    00294       if (rtp->resp) {
    00295          if(rtp->lasteventendseqn != seqno) {
    00296             f = send_dtmf(rtp);
    00297             rtp->lasteventendseqn = seqno;
    00298          }
    00299          rtp->resp = 0;
    00300       }
    00301       resp = 0;
    00302       duration = 0;
    00303    } else if (rtp->resp && rtp->dtmfduration && (duration < rtp->dtmfduration)) {
    00304       f = send_dtmf(rtp);
    00305    }
    00306    if (!(event_end & 0x80))
    00307       rtp->resp = resp;
    00308    rtp->dtmfcount = dtmftimeout;
    00309    rtp->dtmfduration = duration;
    00310    return f;
    00311 }

static struct ast_frame* process_rfc3389 | ( | struct ast_rtp * | rtp,
|  | unsigned char * | data,
|  | int | len |
| ) |  |  | `[static, read]`

Process Comfort Noise RTP.

This is incomplete at the moment.

Definition at line 319 of file rtp.c.

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

Referenced by ast_rtp_read().

    00320 {
    00321    struct ast_frame *f = NULL;
    00322    /* Convert comfort noise into audio with various codecs.  Unfortunately this doesn't
    00323       totally help us out becuase we don't have an engine to keep it going and we are not
    00324       guaranteed to have it every 20ms or anything */
    00325    if (rtpdebug)
    00326       ast_log(LOG_DEBUG, "- RTP 3389 Comfort noise event: Level %d (len = %d)\n", rtp->lastrxformat, len);
    00327
    00328    if (!(ast_test_flag(rtp, FLAG_3389_WARNING))) {
    00329       char iabuf[INET_ADDRSTRLEN];
    00330
    00331       ast_log(LOG_NOTICE, "Comfort noise support incomplete in Asterisk (RFC 3389). Please turn off on client if possible. Client IP: %s\n",
    00332          ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr));
    00333       ast_set_flag(rtp, FLAG_3389_WARNING);
    00334    }
    00335
    00336    /* Must have at least one byte */
    00337    if (!len)
    00338       return NULL;
    00339    if (len < 24) {
    00340       rtp->f.data = rtp->rawdata + AST_FRIENDLY_OFFSET;
    00341       rtp->f.datalen = len - 1;
    00342       rtp->f.offset = AST_FRIENDLY_OFFSET;
    00343       memcpy(rtp->f.data, data + 1, len - 1);
    00344    } else {
    00345       rtp->f.data = NULL;
    00346       rtp->f.offset = 0;
    00347       rtp->f.datalen = 0;
    00348    }
    00349    rtp->f.frametype = AST_FRAME_CNG;
    00350    rtp->f.subclass = data[0] & 0x7f;
    00351    rtp->f.datalen = len - 1;
    00352    rtp->f.samples = 0;
    00353    rtp->f.delivery.tv_usec = rtp->f.delivery.tv_sec = 0;
    00354    f = &rtp->f;
    00355    return f;
    00356 }

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

Definition at line 211 of file rtp.c.

References rtpdebugaddr.

Referenced by ast_rtp_raw_write(), ast_rtp_read(), ast_rtp_sendcng(), and ast_rtp_senddigit().

    00212 {
    00213    if (rtpdebug == 0)
    00214       return 0;
    00215    if (rtpdebugaddr.sin_addr.s_addr) {
    00216       if (((ntohs(rtpdebugaddr.sin_port) != 0)
    00217          && (rtpdebugaddr.sin_port != addr->sin_port))
    00218          || (rtpdebugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
    00219       return 0;
    00220    }
    00221    return 1;
    00222 }

static int rtp_do_debug | ( | int | fd,
|  | int | argc,
|  | char * | argv[] |
| ) |  |  | `[static]`

Definition at line 1818 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, rtp_do_debug_ip(), and rtpdebugaddr.

    01819 {
    01820    if(argc != 2) {
    01821       if(argc != 4)
    01822          return RESULT_SHOWUSAGE;
    01823       return rtp_do_debug_ip(fd, argc, argv);
    01824    }
    01825    rtpdebug = 1;
    01826    memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr));
    01827    ast_cli(fd, "RTP Debugging Enabled\n");
    01828    return RESULT_SUCCESS;
    01829 }

static int rtp_do_debug_ip | ( | int | fd,
|  | int | argc,
|  | char * | argv[] |
| ) |  |  | `[static]`

Definition at line 1787 of file rtp.c.

References ast_cli(), ast_gethostbyname(), ast_inet_ntoa(), hp, RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtpdebugaddr.

Referenced by rtp_do_debug().

    01788 {
    01789    struct hostent *hp;
    01790    struct ast_hostent ahp;
    01791    char iabuf[INET_ADDRSTRLEN];
    01792    int port = 0;
    01793    char *p, *arg;
    01794
    01795    if (argc != 4)
    01796       return RESULT_SHOWUSAGE;
    01797    arg = argv[3];
    01798    p = strstr(arg, ":");
    01799    if (p) {
    01800       *p = '\0';
    01801       p++;
    01802       port = atoi(p);
    01803    }
    01804    hp = ast_gethostbyname(arg, &ahp);
    01805    if (hp == NULL)
    01806       return RESULT_SHOWUSAGE;
    01807    rtpdebugaddr.sin_family = AF_INET;
    01808    memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr));
    01809    rtpdebugaddr.sin_port = htons(port);
    01810    if (port == 0)
    01811       ast_cli(fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtpdebugaddr.sin_addr));
    01812    else
    01813       ast_cli(fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtpdebugaddr.sin_addr), port);
    01814    rtpdebug = 1;
    01815    return RESULT_SUCCESS;
    01816 }

static int rtp_no_debug | ( | int | fd,
|  | int | argc,
|  | char * | argv[] |
| ) |  |  | `[static]`

Definition at line 1831 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

    01832 {
    01833    if(argc !=3)
    01834       return RESULT_SHOWUSAGE;
    01835    rtpdebug = 0;
    01836    ast_cli(fd,"RTP Debugging Disabled\n");
    01837    return RESULT_SUCCESS;
    01838 }

static int rtp_socket | ( | void |  | ) | `[static]`

Definition at line 902 of file rtp.c.

References s.

Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().

    00903 {
    00904    int s;
    00905    long flags;
    00906    s = socket(AF_INET, SOCK_DGRAM, 0);
    00907    if (s > -1) {
    00908       flags = fcntl(s, F_GETFL);
    00909       fcntl(s, F_SETFL, flags | O_NONBLOCK);
    00910 #ifdef SO_NO_CHECK
    00911       if (nochecksums)
    00912          setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
    00913 #endif
    00914    }
    00915    return s;
    00916 }

static int rtpread | ( | int * | id,
|  | int | fd,
|  | short | events,
|  | void * | cbdata |
| ) |  |  | `[static]`

Definition at line 358 of file rtp.c.

References ast_rtp_read(), ast_rtp::callback, and ast_rtp::data.

Referenced by ast_rtp_new_with_bindaddr().

    00359 {
    00360    struct ast_rtp *rtp = cbdata;
    00361    struct ast_frame *f;
    00362    f = ast_rtp_read(rtp);
    00363    if (f) {
    00364       if (rtp->callback)
    00365          rtp->callback(rtp, f, rtp->data);
    00366    }
    00367    return 1;
    00368 }

static struct ast_frame* send_dtmf | ( | struct ast_rtp * | rtp | ) | `[static, read]`

Definition at line 180 of file rtp.c.

References AST_CONTROL_FLASH, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_NULL, ast_inet_ntoa(), ast_log(), ast_frame::datalen, ast_rtp::dtmfduration, ast_rtp::dtmfmute, ast_rtp::f, ast_frame::frametype, LOG_DEBUG, ast_frame::mallocd, option_debug, ast_rtp::resp, ast_frame::samples, ast_frame::src, ast_frame::subclass, and ast_rtp::them.

Referenced by ast_rtp_read(), process_cisco_dtmf(), and process_rfc2833().

    00181 {
    00182    static struct ast_frame null_frame = { AST_FRAME_NULL, };
    00183    char iabuf[INET_ADDRSTRLEN];
    00184
    00185    if (ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) {
    00186       if (option_debug)
    00187          ast_log(LOG_DEBUG, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr));
    00188       rtp->resp = 0;
    00189       rtp->dtmfduration = 0;
    00190       return &null_frame;
    00191    }
    00192    if (option_debug)
    00193       ast_log(LOG_DEBUG, "Sending dtmf: %d (%c), at %s\n", rtp->resp, rtp->resp, ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr));
    00194    if (rtp->resp == 'X') {
    00195       rtp->f.frametype = AST_FRAME_CONTROL;
    00196       rtp->f.subclass = AST_CONTROL_FLASH;
    00197    } else {
    00198       rtp->f.frametype = AST_FRAME_DTMF;
    00199       rtp->f.subclass = rtp->resp;
    00200    }
    00201    rtp->f.datalen = 0;
    00202    rtp->f.samples = 0;
    00203    rtp->f.mallocd = 0;
    00204    rtp->f.src = "RTP";
    00205    rtp->resp = 0;
    00206    rtp->dtmfduration = 0;
    00207    return &rtp->f;
    00208
    00209 }

## Variable Documentation

struct ast_cli_entry cli_debug`[static]`

Initial value:

    {{ "rtp", "debug", NULL } , rtp_do_debug, "Enable RTP debugging", debug_usage }

Definition at line 1851 of file rtp.c.

struct ast_cli_entry cli_debug_ip`[static]`

Initial value:

    {{ "rtp", "debug", "ip", NULL } , rtp_do_debug, "Enable RTP debugging on IP", debug_usage }

Definition at line 1848 of file rtp.c.

struct ast_cli_entry cli_no_debug`[static]`

Initial value:

    {{ "rtp", "no", "debug", NULL } , rtp_no_debug, "Disable RTP debugging", no_debug_usage }

Definition at line 1854 of file rtp.c.

char debug_usage[]`[static]`

Initial value:

      "Usage: rtp debug [ip host[:port]]\n"
      "       Enable dumping of all RTP packets to and from host.\n"

Definition at line 1840 of file rtp.c.

int dtmftimeout = DEFAULT_DTMF_TIMEOUT`[static]`

Definition at line 63 of file rtp.c.

struct { ... } mimeTypes[]`[static]`

Referenced by ast_rtp_lookup_mime_subtype(), and ast_rtp_set_rtpmap_type().

char no_debug_usage[]`[static]`

Initial value:

      "Usage: rtp no debug\n"
      "       Disable all RTP debugging\n"

Definition at line 1844 of file rtp.c.

struct rtpPayloadType payloadType

Definition at line 662 of file rtp.c.

Referenced by ast_rtp_lookup_mime_subtype().

struct ast_rtp_protocol* protos = NULL`[static]`

Definition at line 151 of file rtp.c.

int rtpdebug = 0`[static]`

Definition at line 67 of file rtp.c.

struct sockaddr_in rtpdebugaddr`[static]`

Definition at line 68 of file rtp.c.

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

int rtpend = 0`[static]`

Definition at line 66 of file rtp.c.

int rtpstart = 0`[static]`

Definition at line 65 of file rtp.c.

struct rtpPayloadType static_RTP_PT[MAX_RTP_PT]`[static]`

Definition at line 690 of file rtp.c.

char* subtype

Definition at line 664 of file rtp.c.

Referenced by ast_rtp_set_rtpmap_type().

char* type

Definition at line 663 of file rtp.c.

Referenced by _build_port_config(), _fill_defaults(), _free_port_cfg(), ast_rtp_set_rtpmap_type(), ast_writestream(), build_filename(), check_header(), do_chanreads(), find_subscription_type(), load_module(), misdn_cfg_get(), misdn_cfg_get_config_string(), schedule_delivery(), subscription_type2str(), vpb_new(), and yyparse().