Sun Aug 6 15:15:36 2006

Asterisk developer's documentation


Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

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.

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)
void 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.

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

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, rtpdebug, 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 1518 of file rtp.c.

References 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::name, option_debug, ast_rtp_protocol::set_rtp_peer, ast_frame::subclass, and ast_channel::tech_pvt.

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

void ast_rtp_destroy struct ast_rtp rtp  ) 
 

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

01087 {
01088    if (rtp->smoother)
01089       ast_smoother_free(rtp->smoother);
01090    if (rtp->ioid)
01091       ast_io_remove(rtp->io, rtp->ioid);
01092    if (rtp->s > -1)
01093       close(rtp->s);
01094    if (rtp->rtcp) {
01095       close(rtp->rtcp->s);
01096       free(rtp->rtcp);
01097    }
01098    free(rtp);
01099 }

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, and rtpPayloadType::isAstFormat.

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 }

void 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    them->sin_family = AF_INET;
01047    them->sin_port = rtp->them.sin_port;
01048    them->sin_addr = rtp->them.sin_addr;
01049 }

void ast_rtp_get_us struct ast_rtp rtp,
struct sockaddr_in *  us
 

Definition at line 1051 of file rtp.c.

References ast_rtp::us.

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

01052 {
01053    memcpy(us, &rtp->us, sizeof(rtp->us));
01054 }

void ast_rtp_init void   ) 
 

Definition at line 1881 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 811 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, 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 rtpPayloadType::code, and rtpPayloadType::isAstFormat.

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

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, LOG_ERROR, malloc, rtp_socket(), rtpend, rtpread(), and rtpstart.

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

Referenced by transmit_connect_with_sdp(), transmit_invite(), transmit_modify_with_sdp(), 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 1484 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().

01485 {
01486    struct ast_rtp_protocol *cur;
01487    cur = protos;
01488    while(cur) {
01489       if (cur->type == proto->type) {
01490          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
01491          return -1;
01492       }
01493       cur = cur->next;
01494    }
01495    proto->next = protos;
01496    protos = proto;
01497    return 0;
01498 }

void ast_rtp_proto_unregister struct ast_rtp_protocol proto  ) 
 

Definition at line 1464 of file rtp.c.

References ast_rtp_protocol::next.

Referenced by unload_module().

01465 {
01466    struct ast_rtp_protocol *cur, *prev;
01467 
01468    cur = protos;
01469    prev = NULL;
01470    while(cur) {
01471       if (cur == proto) {
01472          if (prev)
01473             prev->next = proto->next;
01474          else
01475             protos = proto->next;
01476          return;
01477       }
01478       prev = cur;
01479       cur = cur->next;
01480    }
01481 }

void ast_rtp_pt_clear struct ast_rtp rtp  ) 
 

Definition at line 708 of file rtp.c.

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, and rtpPayloadType::isAstFormat.

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

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

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, dtmftimeout, 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(), rtpdebug, 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 1825 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, LOG_WARNING, option_verbose, rtpend, rtpstart, s, and VERBOSE_PREFIX_2.

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

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

void ast_rtp_reset struct ast_rtp rtp  ) 
 

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

01067 {
01068    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
01069    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
01070    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
01071    rtp->lastts = 0;
01072    rtp->lastdigitts = 0;
01073    rtp->lastrxts = 0;
01074    rtp->lastividtimestamp = 0;
01075    rtp->lastovidtimestamp = 0;
01076    rtp->lasteventseqn = 0;
01077    rtp->lasteventendseqn = 0;
01078    rtp->lasttxformat = 0;
01079    rtp->lastrxformat = 0;
01080    rtp->dtmfcount = 0;
01081    rtp->dtmfduration = 0;
01082    rtp->seqno = 0;
01083    rtp->rxseqno = 0;
01084 }

int ast_rtp_sendcng struct ast_rtp rtp,
int  level
 

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

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

int ast_rtp_senddigit struct ast_rtp rtp,
char  digit
 

Definition at line 1120 of file rtp.c.

References ast_inet_ntoa(), ast_log(), AST_RTP_DTMF, ast_rtp_lookup_code(), ast_tvadd(), ast_verbose(), LOG_ERROR, LOG_WARNING, and rtp_debug_test_addr().

Referenced by oh323_digit(), and sip_senddigit().

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

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.

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, 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 1056 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().

01057 {
01058    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
01059    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
01060    if (rtp->rtcp) {
01061       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
01062       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->them.sin_port));
01063    }
01064 }

int ast_rtp_write struct ast_rtp rtp,
struct ast_frame _f
 

Definition at line 1318 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, LOG_DEBUG, LOG_WARNING, ast_frame::offset, option_debug, ast_frame::subclass, and ast_rtp::them.

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

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

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

References ast_rtp::txcore.

Referenced by ast_rtp_raw_write().

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

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

Definition at line 1501 of file rtp.c.

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

Referenced by ast_rtp_bridge().

01502 {
01503    struct ast_rtp_protocol *cur;
01504 
01505    cur = protos;
01506    while(cur) {
01507       if (cur->type == chan->type) {
01508          return cur;
01509       }
01510       cur = cur->next;
01511    }
01512    return NULL;
01513 }

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, dtmftimeout, 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, dtmftimeout, ast_rtp::lasteventendseqn, LOG_DEBUG, ast_rtp::resp, rtpdebug, 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, FLAG_3389_WARNING, LOG_DEBUG, LOG_NOTICE, and rtpdebug.

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 rtpdebug, and 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 1786 of file rtp.c.

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

01787 {
01788    if(argc != 2) {
01789       if(argc != 4)
01790          return RESULT_SHOWUSAGE;
01791       return rtp_do_debug_ip(fd, argc, argv);
01792    }
01793    rtpdebug = 1;
01794    memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr));
01795    ast_cli(fd, "RTP Debugging Enabled\n");
01796    return RESULT_SUCCESS;
01797 }

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

Definition at line 1755 of file rtp.c.

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

Referenced by rtp_do_debug().

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

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

Definition at line 1799 of file rtp.c.

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

01800 {
01801    if(argc !=3)
01802       return RESULT_SHOWUSAGE;
01803    rtpdebug = 0;
01804    ast_cli(fd,"RTP Debugging Disabled\n");
01805    return RESULT_SUCCESS;
01806 }

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

int dtmftimeout = DEFAULT_DTMF_TIMEOUT [static]
 

Definition at line 63 of file rtp.c.

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

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

int rtpdebug = 0 [static]
 

Definition at line 67 of file rtp.c.

Referenced by ast_rtcp_read(), ast_rtp_raw_write(), ast_rtp_read(), process_rfc2833(), process_rfc3389(), rtp_debug_test_addr(), 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_debug_test_addr(), 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.

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 __oh323_new(), alsa_new(), alsa_read(), ast_modem_new(), ast_rtp_set_rtpmap_type(), ast_writestream(), build_filename(), check_header(), features_new(), find_subscription_type(), load_module(), local_new(), mgcp_new(), misdn_new(), nbs_new(), nbs_xread(), oss_new(), oss_read(), phone_exception(), phone_new(), phone_read(), schedule_delivery(), skinny_new(), ss_thread(), subscription_type2str(), and zt_new().


Generated on Sun Aug 6 15:15:39 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.2