Sat Nov 1 06:31:12 2008

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_rtcpast_rtcp_new (void)
 Initialize a new RTCP session.
ast_frameast_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)
rtpPayloadType ast_rtp_lookup_pt (struct ast_rtp *rtp, int pt)
ast_rtpast_rtp_new (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode)
 Initializate a RTP session.
ast_rtpast_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)
ast_frameast_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_protocolget_proto (struct ast_channel *chan)
static struct ast_frameprocess_cisco_dtmf (struct ast_rtp *rtp, unsigned char *data, int len)
static struct ast_frameprocess_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_frameprocess_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_framesend_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 {
   rtpPayloadType   payloadType
   char *   subtype
   char *   type
mimeTypes []
static char no_debug_usage []
static struct ast_rtp_protocolprotos = 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]

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  ) 

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_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_RETRY, ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_rtp_get_peer(), ast_test_flag, FLAG_NAT_ACTIVE, ast_rtp_protocol::get_codec, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_vrtp_info, ast_channel::lock, LOG_DEBUG, LOG_WARNING, ast_channel::masq, ast_channel::masqr, ast_channel::name, option_debug, ast_rtp_protocol::set_rtp_peer, 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_rtp::s, ast_rtcp::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(), ast_rtp_reload(), cli_debug, cli_debug_ip, and cli_no_debug.

Referenced by main().

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 
)

Definition at line 803 of file rtp.c.

References MAX_RTP_PT, result, and static_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 
)

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(), io, and sched.

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 
)

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, io, ast_rtp::io, ast_rtp::ioid, LOG_ERROR, malloc, ast_rtp::rtcp, rtp_socket(), rtpend, rtpread(), rtpstart, ast_rtp::s, ast_rtcp::s, sched, ast_rtp::sched, ast_rtp::seqno, ast_rtp::ssrc, ast_rtp::them, ast_rtp::us, and ast_rtcp::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->