Sat Mar 24 23:30:11 2007

Asterisk developer's documentation


rtp.c File Reference

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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include "asterisk.h"
#include "asterisk/rtp.h"
#include "asterisk/frame.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/acl.h"
#include "asterisk/config.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
#include "asterisk/unaligned.h"

Include dependency graph for rtp.c:

Go to the source code of this file.

Data Structures

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

Defines

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

Functions

int ast_rtcp_fd (struct ast_rtp *rtp)
static struct ast_rtcpast_rtcp_new (void)
 Initialize a new RTCP session.
ast_frameast_rtcp_read (struct ast_rtp *rtp)
enum ast_bridge_result ast_rtp_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
void ast_rtp_destroy (struct ast_rtp *rtp)
int ast_rtp_fd (struct ast_rtp *rtp)
void ast_rtp_get_current_formats (struct ast_rtp *rtp, int *astFormats, int *nonAstFormats)
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 {
   int   alarm
   char *   description
   unsigned int   event_log:1
   enum queue_result   id
   char *   name
   char *   name
   char *   name
   rtpPayloadType   payloadType
   unsigned int   queue_log:1
   char *   subtype
   char *   text
   char *   type
   int   val
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_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 157 of file rtp.c.

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

Referenced by sip_new().

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

static struct ast_rtcp* ast_rtcp_new void   )  [static]
 

Initialize a new RTCP session.

Returns:
The newly initialized RTCP session.

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

00901 {
00902    struct ast_rtcp *rtcp;
00903    rtcp = malloc(sizeof(struct ast_rtcp));
00904    if (!rtcp)
00905       return NULL;
00906    memset(rtcp, 0, sizeof(struct ast_rtcp));
00907    rtcp->s = rtp_socket();
00908    rtcp->us.sin_family = AF_INET;
00909    if (rtcp->s < 0) {
00910       free(rtcp);
00911       ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
00912       return NULL;
00913    }
00914    return rtcp;
00915 }

struct ast_frame* ast_rtcp_read struct ast_rtp rtp  ) 
 

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

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

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

References AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, 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.

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

void ast_rtp_destroy struct ast_rtp rtp  ) 
 

Definition at line 1074 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(), mgcp_hangup(), skinny_hangup(), start_rtp(), and unalloc_sub().

01075 {
01076    if (rtp->smoother)
01077       ast_smoother_free(rtp->smoother);
01078    if (rtp->ioid)
01079       ast_io_remove(rtp->io, rtp->ioid);
01080    if (rtp->s > -1)
01081       close(rtp->s);
01082    if (rtp->rtcp) {
01083       close(rtp->rtcp->s);
01084       free(rtp->rtcp);
01085    }
01086    free(rtp);
01087 }

int ast_rtp_fd struct ast_rtp rtp  ) 
 

Definition at line 152 of file rtp.c.

References ast_rtp::s.

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

00153 {
00154    return rtp->s;
00155 }

void ast_rtp_get_current_formats struct ast_rtp rtp,
int *  astFormats,
int *  nonAstFormats
 

Definition at line 759 of file rtp.c.

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

Referenced by process_sdp().

00760                                                    {
00761    int pt;
00762 
00763    *astFormats = *nonAstFormats = 0;
00764    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
00765       if (rtp->current_RTP_PT[pt].isAstFormat) {
00766          *astFormats |= rtp->current_RTP_PT[pt].code;
00767       } else {
00768          *nonAstFormats |= rtp->current_RTP_PT[pt].code;
00769       }
00770    }
00771 }

void ast_rtp_get_peer struct ast_rtp rtp,
struct sockaddr_in *  them
 

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

01033 {
01034    them->sin_family = AF_INET;
01035    them->sin_port = rtp->them.sin_port;
01036    them->sin_addr = rtp->them.sin_addr;
01037 }

void ast_rtp_get_us struct ast_rtp rtp,
struct sockaddr_in *  us
 

Definition at line 1039 of file rtp.c.

References ast_rtp::us.

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

01040 {
01041    memcpy(us, &rtp->us, sizeof(rtp->us));
01042 }

void ast_rtp_init void   ) 
 

Definition at line 1869 of file rtp.c.

References ast_cli_register(), ast_rtp_reload(), cli_debug, cli_debug_ip, and cli_no_debug.

int ast_rtp_lookup_code struct ast_rtp rtp,
const int  isAstFormat,
const int  code
 

Definition at line 799 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(), ast_rtp_sendcng(), ast_rtp_senddigit(), and ast_rtp_write().

00799                                                                                     {
00800 
00801    int pt;
00802 
00803    if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
00804       code == rtp->rtp_lookup_code_cache_code) {
00805 
00806       /* Use our cached mapping, to avoid the overhead of the loop below */
00807       return rtp->rtp_lookup_code_cache_result;
00808    }
00809 
00810    /* Check the dynamic list first */
00811    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
00812       if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
00813          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
00814          rtp->rtp_lookup_code_cache_code = code;
00815          rtp->rtp_lookup_code_cache_result = pt;
00816          return pt;
00817       }
00818    }
00819 
00820    /* Then the static list */
00821    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
00822       if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) {
00823          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
00824          rtp->rtp_lookup_code_cache_code = code;
00825          rtp->rtp_lookup_code_cache_result = pt;
00826          return pt;
00827       }
00828    }
00829    return -1;
00830 }

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

Definition at line 844 of file rtp.c.

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

Referenced by process_sdp().

00845 {
00846    int format;
00847    unsigned len;
00848    char *end = buf;
00849    char *start = buf;
00850 
00851    if (!buf || !size)
00852       return NULL;
00853 
00854    snprintf(end, size, "0x%x (", capability);
00855 
00856    len = strlen(end);
00857    end += len;
00858    size -= len;
00859    start = end;
00860 
00861    for (format = 1; format < AST_RTP_MAX; format <<= 1) {
00862       if (capability & format) {
00863          const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format);
00864          snprintf(end, size, "%s|", name);
00865          len = strlen(end);
00866          end += len;
00867          size -= len;
00868       }
00869    }
00870 
00871    if (start == end)
00872       snprintf(start, size, "nothing)"); 
00873    else if (size > 1)
00874       *(end -1) = ')';
00875    
00876    return buf;
00877 }

char* ast_rtp_lookup_mime_subtype const int  isAstFormat,
const int  code
 

Definition at line 832 of file rtp.c.

References rtpPayloadType::code, mimeTypes, and payloadType.

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

00832                                                                          {
00833 
00834    int i;
00835 
00836    for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) {
00837    if (mimeTypes[i].payloadType.code == code && mimeTypes[i].payloadType.isAstFormat == isAstFormat) {
00838             return mimeTypes[i].subtype;
00839       }
00840    }
00841    return "";
00842 }

struct rtpPayloadType ast_rtp_lookup_pt struct ast_rtp rtp,
int  pt
 

Definition at line 780 of file rtp.c.

Referenced by ast_rtp_read(), and setup_rtp_connection().

00781 {
00782    struct rtpPayloadType result;
00783 
00784    result.isAstFormat = result.code = 0;
00785    if (pt < 0 || pt > MAX_RTP_PT) 
00786       return result; /* bogus payload type */
00787 
00788    /* Start with the negotiated codecs */
00789    if (!rtp->rtp_offered_from_local)
00790       result = rtp->current_RTP_PT[pt];
00791 
00792    /* If it doesn't exist, check our static RTP type list, just in case */
00793    if (!result.code) 
00794       result = static_RTP_PT[pt];
00795    return result;
00796 }

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

References ast_rtp_new_with_bindaddr(), io, and sched.

Referenced by start_rtp().

01005 {
01006    struct in_addr ia;
01007 
01008    memset(&ia, 0, sizeof(ia));
01009    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
01010 }

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

References ast_log(), ast_rtcp_new(), free, LOG_ERROR, malloc, ast_rtp::rtcp, rtp_socket(), rtpend, 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().

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

void ast_rtp_offered_from_local struct ast_rtp rtp,
int  local
 

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

00773                                                                 {
00774    if (rtp)
00775       rtp->rtp_offered_from_local = local;
00776    else
00777       ast_log(LOG_WARNING, "rtp structure is null\n");
00778 }

int ast_rtp_proto_register struct ast_rtp_protocol proto  ) 
 

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

01473 {
01474    struct ast_rtp_protocol *cur;
01475    cur = protos;
01476    while(cur) {
01477       if (cur->type == proto->type) {
01478          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
01479          return -1;
01480       }
01481       cur = cur->next;
01482    }
01483    proto->next = protos;
01484    protos = proto;
01485    return 0;
01486 }

void ast_rtp_proto_unregister struct ast_rtp_protocol proto  ) 
 

Definition at line 1452 of file rtp.c.

References ast_rtp_protocol::next, and protos.

Referenced by unload_module().

01453 {
01454    struct ast_rtp_protocol *cur, *prev;
01455 
01456    cur = protos;
01457    prev = NULL;
01458    while(cur) {
01459       if (cur == proto) {
01460          if (prev)
01461             prev->next = proto->next;
01462          else
01463             protos = proto->next;
01464          return;
01465       }
01466       prev = cur;
01467       cur = cur->next;
01468    }
01469 }

void ast_rtp_pt_clear struct ast_rtp rtp  ) 
 

Definition at line 696 of file rtp.c.

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

Referenced by process_sdp().

00697 {
00698    int i;
00699    if (!rtp)
00700       return;
00701 
00702    for (i = 0; i < MAX_RTP_PT; ++i) {
00703       rtp->current_RTP_PT[i].isAstFormat = 0;
00704       rtp->current_RTP_PT[i].code = 0;
00705    }
00706 
00707    rtp->rtp_lookup_code_cache_isAstFormat = 0;
00708    rtp->rtp_lookup_code_cache_code = 0;
00709    rtp->rtp_lookup_code_cache_result = 0;
00710 }

void ast_rtp_pt_default struct ast_rtp rtp  ) 
 

Definition at line 712 of file rtp.c.

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

00713 {
00714    int i;
00715 
00716    /* Initialize to default payload types */
00717    for (i = 0; i < MAX_RTP_PT; ++i) {
00718       rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
00719       rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
00720    }
00721 
00722    rtp->rtp_lookup_code_cache_isAstFormat = 0;
00723    rtp->rtp_lookup_code_cache_code = 0;
00724    rtp->rtp_lookup_code_cache_result = 0;
00725 }

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

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

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

struct ast_frame* ast_rtp_read struct ast_rtp rtp  ) 
 

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

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

void ast_rtp_reload void   ) 
 

Definition at line 1813 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(), and ast_rtp_init().

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

void ast_rtp_reset struct ast_rtp rtp  ) 
 

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

01055 {
01056    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
01057    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
01058    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
01059    rtp->lastts = 0;
01060    rtp->lastdigitts = 0;
01061    rtp->lastrxts = 0;
01062    rtp->lastividtimestamp = 0;
01063    rtp->lastovidtimestamp = 0;
01064    rtp->lasteventseqn = 0;
01065    rtp->lasteventendseqn = 0;
01066    rtp->lasttxformat = 0;
01067    rtp->lastrxformat = 0;
01068    rtp->dtmfcount = 0;
01069    rtp->dtmfduration = 0;
01070    rtp->seqno = 0;
01071    rtp->rxseqno = 0;
01072 }

int ast_rtp_sendcng struct ast_rtp rtp,
int  level
 

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

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

int ast_rtp_senddigit struct ast_rtp rtp,
char  digit
 

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

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

void ast_rtp_set_callback struct ast_rtp rtp,
ast_rtp_callback  callback
 

Definition at line 169 of file rtp.c.

References ast_rtp::callback.

Referenced by start_rtp().

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

void ast_rtp_set_data struct ast_rtp rtp,
void *  data
 

Definition at line 164 of file rtp.c.

References ast_rtp::data.

Referenced by start_rtp().

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

void ast_rtp_set_m_type struct ast_rtp rtp,
int  pt
 

Definition at line 730 of file rtp.c.

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

Referenced by process_sdp().

00730                                                      {
00731    if (pt < 0 || pt > MAX_RTP_PT) 
00732       return; /* bogus payload type */
00733 
00734    if (static_RTP_PT[pt].code != 0) {
00735       rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
00736    }
00737 } 

void ast_rtp_set_peer struct ast_rtp rtp,
struct sockaddr_in *  them
 

Definition at line 1021 of file rtp.c.

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

Referenced by process_sdp(), and setup_rtp_connection().

01022 {
01023    rtp->them.sin_port = them->sin_port;
01024    rtp->them.sin_addr = them->sin_addr;
01025    if (rtp->rtcp) {
01026       rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1);
01027       rtp->rtcp->them.sin_addr = them->sin_addr;
01028    }
01029    rtp->rxseqno = 0;
01030 }

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

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

00742                                              {
00743    int i;
00744 
00745    if (pt < 0 || pt > MAX_RTP_PT) 
00746          return; /* bogus payload type */
00747 
00748    for (i = 0; i < sizeof mimeTypes/sizeof mimeTypes[0]; ++i) {
00749       if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
00750            strcasecmp(mimeType, mimeTypes[i].type) == 0) {
00751          rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
00752       return;
00753       }
00754    }
00755 } 

void ast_rtp_setnat struct ast_rtp rtp,
int  nat
 

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

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

int ast_rtp_settos struct ast_rtp rtp,
int  tos
 

Definition at line 1012 of file rtp.c.

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

Referenced by oh323_alloc(), and sip_alloc().

01013 {
01014    int res;
01015 
01016    if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 
01017       ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
01018    return res;
01019 }

void ast_rtp_stop struct ast_rtp rtp  ) 
 

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

01045 {
01046    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
01047    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
01048    if (rtp->rtcp) {
01049       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
01050       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->them.sin_port));
01051    }
01052 }

int ast_rtp_write struct ast_rtp rtp,
struct ast_frame _f
 

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

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

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

Definition at line 414 of file rtp.c.

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

Referenced by ast_rtp_read(), and schedule_delivery().

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

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

Definition at line 1089 of file rtp.c.

References ast_rtp::txcore.

Referenced by ast_rtp_raw_write().

01090 {
01091    struct timeval t;
01092    long ms;
01093    if (ast_tvzero(rtp->txcore)) {
01094       rtp->txcore = ast_tvnow();
01095       /* Round to 20ms for nice, pretty timestamps */
01096       rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
01097    }
01098    /* Use previous txcore if available */
01099    t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
01100    ms = ast_tvdiff_ms(t, rtp->txcore);
01101    if (ms < 0)
01102       ms = 0;
01103    /* Use what we just got for next time */
01104    rtp->txcore = t;
01105    return (unsigned int) ms;
01106 }

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

Definition at line 1489 of file rtp.c.

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

Referenced by ast_rtp_bridge().

01490 {
01491    struct ast_rtp_protocol *cur;
01492 
01493    cur = protos;
01494    while(cur) {
01495       if (cur->type == chan->type) {
01496          return cur;
01497       }
01498       cur = cur->next;
01499    }
01500    return NULL;
01501 }

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

Definition at line 223 of file rtp.c.

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

Referenced by ast_rtp_read().

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

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

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

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

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

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

Definition at line 210 of file rtp.c.

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

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

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

Definition at line 1774 of file rtp.c.

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

01775 {
01776    if(argc != 2) {
01777       if(argc != 4)
01778          return RESULT_SHOWUSAGE;
01779       return rtp_do_debug_ip(fd, argc, argv);
01780    }
01781    rtpdebug = 1;
01782    memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr));
01783    ast_cli(fd, "RTP Debugging Enabled\n");
01784    return RESULT_SUCCESS;
01785 }

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

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

01744 {
01745    struct hostent *hp;
01746    struct ast_hostent ahp;
01747    char iabuf[INET_ADDRSTRLEN];
01748    int port = 0;
01749    char *p, *arg;
01750 
01751    if (argc != 4)
01752       return RESULT_SHOWUSAGE;
01753    arg = argv[3];
01754    p = strstr(arg, ":");
01755    if (p) {
01756       *p = '\0';
01757       p++;
01758       port = atoi(p);
01759    }
01760    hp = ast_gethostbyname(arg, &ahp);
01761    if (hp == NULL)
01762       return RESULT_SHOWUSAGE;
01763    rtpdebugaddr.sin_family = AF_INET;
01764    memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr));
01765    rtpdebugaddr.sin_port = htons(port);
01766    if (port == 0)
01767       ast_cli(fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtpdebugaddr.sin_addr));
01768    else
01769       ast_cli(fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtpdebugaddr.sin_addr), port);
01770    rtpdebug = 1;
01771    return RESULT_SUCCESS;
01772 }

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

Definition at line 1787 of file rtp.c.

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

01788 {
01789    if(argc !=3)
01790       return RESULT_SHOWUSAGE;
01791    rtpdebug = 0;
01792    ast_cli(fd,"RTP Debugging Disabled\n");
01793    return RESULT_SUCCESS;
01794 }

static int rtp_socket void   )  [static]
 

Definition at line 879 of file rtp.c.

References s.

Referenced by ast_rtcp_new(), and ast_rtp_new_with_bindaddr().

00880 {
00881    int s;
00882    long flags;
00883    s = socket(AF_INET, SOCK_DGRAM, 0);
00884    if (s > -1) {
00885       flags = fcntl(s, F_GETFL);
00886       fcntl(s, F_SETFL, flags | O_NONBLOCK);
00887 #ifdef SO_NO_CHECK
00888       if (nochecksums)
00889          setsockopt(s, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums));
00890 #endif
00891    }
00892    return s;
00893 }

static int rtpread int *  id,
int  fd,
short  events,
void *  cbdata
[static]
 

Definition at line 357 of file rtp.c.

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

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

static struct ast_frame* send_dtmf struct ast_rtp rtp  )  [static]
 

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

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


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 1807 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 1804 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 1810 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 1796 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 1800 of file rtp.c.

struct rtpPayloadType payloadType
 

Definition at line 639 of file rtp.c.

Referenced by ast_rtp_lookup_mime_subtype().

struct ast_rtp_protocol* protos = NULL [static]
 

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

Referenced by ast_rtp_pt_default(), and ast_rtp_set_m_type().

char* subtype
 

Definition at line 641 of file rtp.c.

Referenced by ast_rtp_set_rtpmap_type().

char* type
 

Definition at line 640 of file rtp.c.

Referenced by ast_rtp_set_rtpmap_type(), ast_writestream(), build_filename(), check_header(), find_subscription_type(), load_module(), mgcp_new(), misdn_new(), schedule_delivery(), subscription_type2str(), and yyparse().


Generated on Sat Mar 24 23:30:11 2007 for Asterisk - the Open Source PBX by  doxygen 1.4.6