Sat Sep 16 05:48:06 2006

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"

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

00913 {
00914    struct ast_rtcp *rtcp;
00915    rtcp = malloc(sizeof(struct ast_rtcp));
00916    if (!rtcp)
00917       return NULL;
00918    memset(rtcp, 0, sizeof(struct ast_rtcp));
00919    rtcp->s = rtp_socket();
00920    rtcp->us.sin_family = AF_INET;
00921    if (rtcp->s < 0) {
00922       free(rtcp);
00923       ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
00924       return NULL;
00925    }
00926    return rtcp;
00927 }

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 != EAGAIN)
00390          ast_log(LOG_WARNING, "RTP Read error: %s\n", strerror(errno));
00391       if (errno == EBADF)
00392          CRASH;
00393       return &null_frame;
00394    }
00395 
00396    if (res < hdrlen) {
00397       ast_log(LOG_WARNING, "RTP Read too short\n");
00398       return &null_frame;
00399    }
00400 
00401    if (rtp->nat) {
00402       /* Send to whoever sent to us */
00403       if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
00404           (rtp->rtcp->them.sin_port != sin.sin_port)) {
00405          memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
00406          if (option_debug || rtpdebug)
00407             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));
00408       }
00409    }
00410    if (option_debug)
00411       ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res);
00412    return &null_frame;
00413 }

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

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

void ast_rtp_destroy ( struct ast_rtp rtp  ) 

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

01093 {
01094    if (rtp->smoother)
01095       ast_smoother_free(rtp->smoother);
01096    if (rtp->ioid)
01097       ast_io_remove(rtp->io, rtp->ioid);
01098    if (rtp->s > -1)
01099       close(rtp->s);
01100    if (rtp->rtcp) {
01101       close(rtp->rtcp->s);
01102       free(rtp->rtcp);
01103    }
01104    free(rtp);
01105 }

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 771 of file rtp.c.

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

Referenced by process_sdp().

00772                                                    {
00773    int pt;
00774 
00775    *astFormats = *nonAstFormats = 0;
00776    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
00777       if (rtp->current_RTP_PT[pt].isAstFormat) {
00778          *astFormats |= rtp->current_RTP_PT[pt].code;
00779       } else {
00780          *nonAstFormats |= rtp->current_RTP_PT[pt].code;
00781       }
00782    }
00783 }

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

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

01045 {
01046    if ((them->sin_family != AF_INET) ||
01047        (them->sin_port != rtp->them.sin_port) ||
01048        (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
01049       them->sin_family = AF_INET;
01050       them->sin_port = rtp->them.sin_port;
01051       them->sin_addr = rtp->them.sin_addr;
01052       return 1;
01053    }
01054    return 0;
01055 }

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

Definition at line 1057 of file rtp.c.

References ast_rtp::us.

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

01058 {
01059    memcpy(us, &rtp->us, sizeof(rtp->us));
01060 }

void ast_rtp_init ( void   ) 

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

00811                                                                                     {
00812 
00813    int pt;
00814 
00815    if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
00816       code == rtp->rtp_lookup_code_cache_code) {
00817 
00818       /* Use our cached mapping, to avoid the overhead of the loop below */
00819       return rtp->rtp_lookup_code_cache_result;
00820    }
00821 
00822    /* Check the dynamic list first */
00823    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
00824       if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
00825          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
00826          rtp->rtp_lookup_code_cache_code = code;
00827          rtp->rtp_lookup_code_cache_result = pt;
00828          return pt;
00829       }
00830    }
00831 
00832    /* Then the static list */
00833    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
00834       if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) {
00835          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
00836          rtp->rtp_lookup_code_cache_code = code;
00837          rtp->rtp_lookup_code_cache_result = pt;
00838          return pt;
00839       }
00840    }
00841    return -1;
00842 }

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

Definition at line 856 of file rtp.c.

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

Referenced by process_sdp().

00857 {
00858    int format;
00859    unsigned len;
00860    char *end = buf;
00861    char *start = buf;
00862 
00863    if (!buf || !size)
00864       return NULL;
00865 
00866    snprintf(end, size, "0x%x (", capability);
00867 
00868    len = strlen(end);
00869    end += len;
00870    size -= len;
00871    start = end;
00872 
00873    for (format = 1; format < AST_RTP_MAX; format <<= 1) {
00874       if (capability & format) {
00875          const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format);
00876          snprintf(end, size, "%s|", name);
00877          len = strlen(end);
00878          end += len;
00879          size -= len;
00880       }
00881    }
00882 
00883    if (start == end)
00884       snprintf(start, size, "nothing)"); 
00885    else if (size > 1)
00886       *(end -1) = ')';
00887    
00888    return buf;
00889 }

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

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

00844                                                                          {
00845 
00846    int i;
00847 
00848    for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) {
00849    if (mimeTypes[i].payloadType.code == code && mimeTypes[i].payloadType.isAstFormat == isAstFormat) {
00850             return mimeTypes[i].subtype;
00851       }
00852    }
00853    return "";
00854 }

struct rtpPayloadType ast_rtp_lookup_pt ( struct ast_rtp rtp,
int  pt 
)

Definition at line 792 of file rtp.c.

References MAX_RTP_PT, result, and static_RTP_PT.

Referenced by ast_rtp_read(), and setup_rtp_connection().

00793 {
00794    struct rtpPayloadType result;
00795 
00796    result.isAstFormat = result.code = 0;
00797    if (pt < 0 || pt > MAX_RTP_PT) 
00798       return result; /* bogus payload type */
00799 
00800    /* Start with the negotiated codecs */
00801    if (!rtp->rtp_offered_from_local)
00802       result = rtp->current_RTP_PT[pt];
00803 
00804    /* If it doesn't exist, check our static RTP type list, just in case */
00805    if (!result.code) 
00806       result = static_RTP_PT[pt];
00807    return result;
00808 }

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 1016 of file rtp.c.

References ast_rtp_new_with_bindaddr(), io, and sched.

Referenced by start_rtp().

01017 {
01018    struct in_addr ia;
01019 
01020    memset(&ia, 0, sizeof(ia));
01021    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
01022 }

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

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

void ast_rtp_offered_from_local ( struct ast_rtp rtp,
int  local 
)

Definition at line 785 of file rtp.c.

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

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

00785                                                                 {
00786    if (rtp)
00787       rtp->rtp_offered_from_local = local;
00788    else
00789       ast_log(LOG_WARNING, "rtp structure is null\n");
00790 }

int ast_rtp_proto_register ( struct ast_rtp_protocol proto  ) 

Definition at line 1490 of file rtp.c.

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

Referenced by load_module(), and unload_module().

01491 {
01492    struct ast_rtp_protocol *cur;
01493    cur = protos;
01494    while(cur) {
01495       if (cur->type == proto->type) {
01496          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
01497          return -1;
01498       }
01499       cur = cur->next;
01500    }
01501    proto->next = protos;
01502    protos = proto;
01503    return 0;
01504 }

void ast_rtp_proto_unregister ( struct ast_rtp_protocol proto  ) 

Definition at line 1470 of file rtp.c.

References ast_rtp_protocol::next, and protos.

Referenced by unload_module().

01471 {
01472    struct ast_rtp_protocol *cur, *prev;
01473 
01474    cur = protos;
01475    prev = NULL;
01476    while(cur) {
01477       if (cur == proto) {
01478          if (prev)
01479             prev->next = proto->next;
01480          else
01481             protos = proto->next;
01482          return;
01483       }
01484       prev = cur;
01485       cur = cur->next;
01486    }
01487 }

void ast_rtp_pt_clear ( struct ast_rtp rtp  ) 

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

00709 {
00710    int i;
00711    if (!rtp)
00712       return;
00713 
00714    for (i = 0; i < MAX_RTP_PT; ++i) {
00715       rtp->current_RTP_PT[i].isAstFormat = 0;
00716       rtp->current_RTP_PT[i].code = 0;
00717    }
00718 
00719    rtp->rtp_lookup_code_cache_isAstFormat = 0;
00720    rtp->rtp_lookup_code_cache_code = 0;
00721    rtp->rtp_lookup_code_cache_result = 0;
00722 }

void ast_rtp_pt_default ( struct ast_rtp rtp  ) 

Definition at line 724 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, ast_rtp::rtp_lookup_code_cache_result, and static_RTP_PT.

Referenced by ast_rtp_new_with_bindaddr().

00725 {
00726    int i;
00727 
00728    /* Initialize to default payload types */
00729    for (i = 0; i < MAX_RTP_PT; ++i) {
00730       rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
00731       rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
00732    }
00733 
00734    rtp->rtp_lookup_code_cache_isAstFormat = 0;
00735    rtp->rtp_lookup_code_cache_code = 0;
00736    rtp->rtp_lookup_code_cache_result = 0;
00737 }

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

Definition at line 1243 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(), rtpdebug, ast_rtp::s, ast_frame::samples, ast_rtp::seqno, ast_rtp::ssrc, ast_frame::subclass, and ast_rtp::them.

Referenced by ast_rtp_write().

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

struct ast_frame* ast_rtp_read ( struct ast_rtp rtp  ) 

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

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

void ast_rtp_reload ( void   ) 

Definition at line 1831 of file rtp.c.

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

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

01832 {
01833    struct ast_config *cfg;
01834    char *s;
01835 
01836    rtpstart = 5000;
01837    rtpend = 31000;
01838    dtmftimeout = DEFAULT_DTMF_TIMEOUT;
01839    cfg = ast_config_load("rtp.conf");
01840    if (cfg) {
01841       if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
01842          rtpstart = atoi(s);
01843          if (rtpstart < 1024)
01844             rtpstart = 1024;
01845          if (rtpstart > 65535)
01846             rtpstart = 65535;
01847       }
01848       if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
01849          rtpend = atoi(s);
01850          if (rtpend < 1024)
01851             rtpend = 1024;
01852          if (rtpend > 65535)
01853             rtpend = 65535;
01854       }
01855       if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
01856 #ifdef SO_NO_CHECK
01857          if (ast_false(s))
01858             nochecksums = 1;
01859          else
01860             nochecksums = 0;
01861 #else
01862          if (ast_false(s))
01863             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
01864 #endif
01865       }
01866       if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
01867          dtmftimeout = atoi(s);
01868          if ((dtmftimeout < 0) || (dtmftimeout > 20000)) {
01869             ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
01870                dtmftimeout, DEFAULT_DTMF_TIMEOUT);
01871             dtmftimeout = DEFAULT_DTMF_TIMEOUT;
01872          };
01873       }
01874       ast_config_destroy(cfg);
01875    }
01876    if (rtpstart >= rtpend) {
01877       ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
01878       rtpstart = 5000;
01879       rtpend = 31000;
01880    }
01881    if (option_verbose > 1)
01882       ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
01883    
01884 }

void ast_rtp_reset ( struct ast_rtp rtp  ) 

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

01073 {
01074    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
01075    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
01076    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
01077    rtp->lastts = 0;
01078    rtp->lastdigitts = 0;
01079    rtp->lastrxts = 0;
01080    rtp->lastividtimestamp = 0;
01081    rtp->lastovidtimestamp = 0;
01082    rtp->lasteventseqn = 0;
01083    rtp->lasteventendseqn = 0;
01084    rtp->lasttxformat = 0;
01085    rtp->lastrxformat = 0;
01086    rtp->dtmfcount = 0;
01087    rtp->dtmfduration = 0;
01088    rtp->seqno = 0;
01089    rtp->rxseqno = 0;
01090 }

int ast_rtp_sendcng ( struct ast_rtp rtp,
int  level 
)

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

01209 {
01210    unsigned int *rtpheader;
01211    int hdrlen = 12;
01212    int res;
01213    int payload;
01214    char data[256];
01215    char iabuf[INET_ADDRSTRLEN];
01216    level = 127 - (level & 0x7f);
01217    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN);
01218 
01219    /* If we have no peer, return immediately */ 
01220    if (!rtp->them.sin_addr.s_addr)
01221       return 0;
01222 
01223    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
01224 
01225    /* Get a pointer to the header */
01226    rtpheader = (unsigned int *)data;
01227    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
01228    rtpheader[1] = htonl(rtp->lastts);
01229    rtpheader[2] = htonl(rtp->ssrc); 
01230    data[12] = level;
01231    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
01232       res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
01233       if (res <0) 
01234          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));
01235       if(rtp_debug_test_addr(&rtp->them))
01236          ast_verbose("Sent Comfort Noise RTP packet to %s:%d (type %d, seq %d, ts %d, len %d)\n"
01237                , ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen);        
01238          
01239    }
01240    return 0;
01241 }

int ast_rtp_senddigit ( struct ast_rtp rtp,
char  digit 
)

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

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

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 742 of file rtp.c.

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

Referenced by process_sdp().

00742                                                      {
00743    if (pt < 0 || pt > MAX_RTP_PT) 
00744       return; /* bogus payload type */
00745 
00746    if (static_RTP_PT[pt].code != 0) {
00747       rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
00748    }
00749 } 

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

Definition at line 1033 of file rtp.c.

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

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

01034 {
01035    rtp->them.sin_port = them->sin_port;
01036    rtp->them.sin_addr = them->sin_addr;
01037    if (rtp->rtcp) {
01038       rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1);
01039       rtp->rtcp->them.sin_addr = them->sin_addr;
01040    }
01041    rtp->rxseqno = 0;
01042 }

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

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

00754                                              {
00755    int i;
00756 
00757    if (pt < 0 || pt > MAX_RTP_PT) 
00758          return; /* bogus payload type */
00759 
00760    for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) {
00761       if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
00762            strcasecmp(mimeType, mimeTypes[i].type) == 0) {
00763          rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
00764       return;
00765       }
00766    }
00767 } 

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 1024 of file rtp.c.

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

Referenced by oh323_alloc(), and sip_alloc().

01025 {
01026    int res;
01027 
01028    if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 
01029       ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
01030    return res;
01031 }

void ast_rtp_stop ( struct ast_rtp rtp  ) 

Definition at line 1062 of file rtp.c.

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

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

01063 {
01064    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
01065    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
01066    if (rtp->rtcp) {
01067       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
01068       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->them.sin_port));
01069    }
01070 }

int ast_rtp_write ( struct ast_rtp rtp,
struct ast_frame _f 
)

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

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

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

Definition at line 415 of file rtp.c.

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

Referenced by ast_rtp_read(), and schedule_delivery().

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

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

Definition at line 1107 of file rtp.c.

References ast_rtp::txcore.

Referenced by ast_rtp_raw_write().

01108 {
01109    struct timeval t;
01110    long ms;
01111    if (ast_tvzero(rtp->txcore)) {
01112       rtp->txcore = ast_tvnow();
01113       /* Round to 20ms for nice, pretty timestamps */
01114       rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
01115    }
01116    /* Use previous txcore if available */
01117    t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
01118    ms = ast_tvdiff_ms(t, rtp->txcore);
01119    if (ms < 0)
01120       ms = 0;
01121    /* Use what we just got for next time */
01122    rtp->txcore = t;
01123    return (unsigned int) ms;
01124 }

static struct ast_rtp_protocol* get_proto ( struct ast_channel chan  )  [static]

Definition at line 1507 of file rtp.c.

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

Referenced by ast_rtp_bridge().

01508 {
01509    struct ast_rtp_protocol *cur;
01510 
01511    cur = protos;
01512    while(cur) {
01513       if (cur->type == chan->type) {
01514          return cur;
01515       }
01516       cur = cur->next;
01517    }
01518    return NULL;
01519 }

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

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]

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]

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.

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 1792 of file rtp.c.

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

01793 {
01794    if(argc != 2) {
01795       if(argc != 4)
01796          return RESULT_SHOWUSAGE;
01797       return rtp_do_debug_ip(fd, argc, argv);
01798    }
01799    rtpdebug = 1;
01800    memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr));
01801    ast_cli(fd, "RTP Debugging Enabled\n");
01802    return RESULT_SUCCESS;
01803 }

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

Definition at line 1761 of file rtp.c.

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

Referenced by rtp_do_debug().

01762 {
01763    struct hostent *hp;
01764    struct ast_hostent ahp;
01765    char iabuf[INET_ADDRSTRLEN];
01766    int port = 0;
01767    char *p, *arg;
01768 
01769    if (argc != 4)
01770       return RESULT_SHOWUSAGE;
01771    arg = argv[3];
01772    p = strstr(arg, ":");
01773    if (p) {
01774       *p = '\0';
01775       p++;
01776       port = atoi(p);
01777    }
01778    hp = ast_gethostbyname(arg, &ahp);
01779    if (hp == NULL)
01780       return RESULT_SHOWUSAGE;
01781    rtpdebugaddr.sin_family = AF_INET;
01782    memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr));
01783    rtpdebugaddr.sin_port = htons(port);
01784    if (port == 0)
01785       ast_cli(fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtpdebugaddr.sin_addr));
01786    else
01787       ast_cli(fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtpdebugaddr.sin_addr), port);
01788    rtpdebug = 1;
01789    return RESULT_SUCCESS;
01790 }

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

Definition at line 1805 of file rtp.c.

References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and rtpdebug.

01806 {
01807    if(argc !=3)
01808       return RESULT_SHOWUSAGE;
01809    rtpdebug = 0;
01810    ast_cli(fd,"RTP Debugging Disabled\n");
01811    return RESULT_SUCCESS;
01812 }

static int rtp_socket ( void   )  [static]

Definition at line 891 of file rtp.c.

References s.

Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().

00892 {
00893    int s;
00894    long flags;
00895    s = socket(AF_INET, SOCK_DGRAM, 0);
00896    if (s > -1) {
00897       flags = fcntl(s, F_GETFL);
00898       fcntl(s, F_SETFL, flags | O_NONBLOCK);
00899 #ifdef SO_NO_CHECK
00900       if (nochecksums)
00901          setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
00902 #endif
00903    }
00904    return s;
00905 }

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_frame::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]

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 1825 of file rtp.c.

Referenced by ast_rtp_init(), load_module(), and unload_module().

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 1822 of file rtp.c.

Referenced by ast_rtp_init().

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 1828 of file rtp.c.

Referenced by ast_rtp_init(), load_module(), and unload_module().

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 1814 of file rtp.c.

int dtmftimeout = DEFAULT_DTMF_TIMEOUT [static]

Definition at line 63 of file rtp.c.

Referenced by ast_rtp_reload().

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

Referenced by ast_rtp_lookup_mime_subtype(), and ast_rtp_set_rtpmap_type().

char no_debug_usage[] [static]

Initial value:

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

Definition at line 1818 of file rtp.c.

struct rtpPayloadType payloadType

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

Referenced by ast_rtp_proto_register(), ast_rtp_proto_unregister(), and get_proto().

int rtpdebug = 0 [static]

Definition at line 67 of file rtp.c.

Referenced by ast_rtp_raw_write(), rtp_do_debug(), rtp_do_debug_ip(), and rtp_no_debug().

struct sockaddr_in rtpdebugaddr [static]

Definition at line 68 of file rtp.c.

Referenced by rtp_do_debug(), and rtp_do_debug_ip().

int rtpend = 0 [static]

Definition at line 66 of file rtp.c.

Referenced by ast_rtp_new_with_bindaddr(), and ast_rtp_reload().

int rtpstart = 0 [static]

Definition at line 65 of file rtp.c.

Referenced by ast_rtp_new_with_bindaddr(), and ast_rtp_reload().

struct rtpPayloadType static_RTP_PT[MAX_RTP_PT] [static]

Definition at line 679 of file rtp.c.

Referenced by ast_rtp_lookup_pt(), ast_rtp_pt_default(), and ast_rtp_set_m_type().

char* subtype

Definition at line 653 of file rtp.c.

Referenced by ast_rtp_set_rtpmap_type().

char* type

Definition at line 652 of file rtp.c.

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


Generated on Sat Sep 16 05:48:06 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.7