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_rtcpast_rtcp_new (void)
 Initialize a new RTCP session.
struct 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)
struct rtpPayloadType ast_rtp_lookup_pt (struct ast_rtp *rtp, int pt)
struct ast_rtpast_rtp_new (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode)
 Initializate a RTP session.
struct 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)
struct 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 {
   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

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

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]

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.

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


Generated on Wed Oct 28 15:49:17 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6