Sat Mar 24 23:30:11 2007

Asterisk developer's documentation


rtp.h File Reference

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

#include "asterisk/frame.h"
#include "asterisk/io.h"
#include "asterisk/sched.h"
#include "asterisk/channel.h"
#include <netinet/in.h>

Include dependency graph for rtp.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ast_rtp_protocol

Defines

#define AST_RTP_CISCO_DTMF   (1 << 2)
#define AST_RTP_CN   (1 << 1)
#define AST_RTP_DTMF   (1 << 0)
#define AST_RTP_MAX   AST_RTP_CISCO_DTMF

Typedefs

typedef int(* ast_rtp_callback )(struct ast_rtp *rtp, struct ast_frame *f, void *data)

Functions

int ast_rtcp_fd (struct ast_rtp *rtp)
ast_frameast_rtcp_read (struct ast_rtp *rtp)
int 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, int isAstFormat, int code)
char * ast_rtp_lookup_mime_multiple (char *buf, int size, const int capability, const int isAstFormat)
char * ast_rtp_lookup_mime_subtype (int isAstFormat, 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 in)
 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)
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)


Detailed Description

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

RTP is defined in RFC 3550.

Definition in file rtp.h.


Define Documentation

#define AST_RTP_CISCO_DTMF   (1 << 2)
 

DTMF (Cisco Proprietary)

Definition at line 46 of file rtp.h.

Referenced by ast_rtp_read().

#define AST_RTP_CN   (1 << 1)
 

'Comfort Noise' (RFC3389)

Definition at line 44 of file rtp.h.

Referenced by ast_rtp_read(), and ast_rtp_sendcng().

#define AST_RTP_DTMF   (1 << 0)
 

DTMF (RFC2833)

Definition at line 42 of file rtp.h.

Referenced by add_noncodec_to_sdp(), ast_rtp_read(), ast_rtp_senddigit(), check_user_full(), create_addr(), create_addr_from_peer(), oh323_alloc(), oh323_request(), process_sdp(), and sip_alloc().

#define AST_RTP_MAX   AST_RTP_CISCO_DTMF
 

Maximum RTP-specific code

Definition at line 48 of file rtp.h.

Referenced by ast_rtp_lookup_mime_multiple().


Typedef Documentation

typedef int(* ast_rtp_callback)(struct ast_rtp *rtp, struct ast_frame *f, void *data)
 

Definition at line 70 of file rtp.h.


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 }

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 }

int 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_rtcp::s, ast_rtp::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,
int  isAstFormat,
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 int  isAstFormat,
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_rtcp::s, ast_rtp::s, ast_rtp::sched, sched, ast_rtp::seqno, ast_rtp::ssrc, ast_rtp::them, ast_rtcp::us, and ast_rtp::us.

Referenced by ast_rtp_new(), oh323_alloc(), sip_alloc(), and start_rtp().

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 }

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_rtcp::them, and ast_rtp::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_rtcp::them, and ast_rtp::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 }


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