Sun Aug 6 15:15:39 2006

Asterisk developer's documentation


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

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.

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(), add_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 add_sdp(), and 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 158 of file rtp.c.

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

Referenced by sip_new().

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

struct ast_frame* ast_rtcp_read struct ast_rtp rtp  ) 
 

Definition at line 370 of file rtp.c.

References AST_FRAME_NULL, ast_inet_ntoa(), ast_log(), CRASH, LOG_DEBUG, LOG_WARNING, ast_rtp::nat, option_debug, ast_rtp::rtcp, rtpdebug, ast_rtcp::s, and ast_rtcp::them.

Referenced by sip_rtp_read().

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

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

References AST_BRIDGE_COMPLETE, AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, AST_BRIDGE_IGNORE_SIGS, AST_BRIDGE_RETRY, ast_check_hangup(), AST_CONTROL_HOLD, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree(), ast_indicate(), ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_read(), ast_rtp_get_peer(), ast_test_flag, ast_waitfor_n(), ast_write(), FLAG_NAT_ACTIVE, ast_frame::frametype, ast_rtp_protocol::get_codec, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_vrtp_info, inaddrcmp(), ast_channel::lock, LOG_DEBUG, LOG_WARNING, ast_channel::name, option_debug, ast_rtp_protocol::set_rtp_peer, ast_frame::subclass, and ast_channel::tech_pvt.

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

void ast_rtp_destroy struct ast_rtp rtp  ) 
 

Definition at line 1086 of file rtp.c.

References ast_io_remove(), ast_smoother_free(), free, ast_rtp::io, ast_rtp::ioid, ast_rtp::rtcp, ast_rtcp::s, ast_rtp::s, and ast_rtp::smoother.

Referenced by __oh323_destroy(), __sip_destroy(), cleanup_connection(), destroy_endpoint(), mgcp_hangup(), skinny_hangup(), start_rtp(), and unalloc_sub().

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

int ast_rtp_fd struct ast_rtp rtp  ) 
 

Definition at line 153 of file rtp.c.

References ast_rtp::s.

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

00154 {
00155    return rtp->s;
00156 }

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

Definition at line 771 of file rtp.c.

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

Referenced by process_sdp().

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

void ast_rtp_get_peer struct ast_rtp rtp,
struct sockaddr_in *  them
 

Definition at line 1044 of file rtp.c.

References ast_rtp::them.

Referenced by add_sdp(), ast_rtp_bridge(), do_monitor(), oh323_set_rtp_peer(), sip_set_rtp_peer(), and transmit_modify_with_sdp().

01045 {
01046    them->sin_family = AF_INET;
01047    them->sin_port = rtp->them.sin_port;
01048    them->sin_addr = rtp->them.sin_addr;
01049 }

void ast_rtp_get_us struct ast_rtp rtp,
struct sockaddr_in *  us
 

Definition at line 1051 of file rtp.c.

References ast_rtp::us.

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

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

void ast_rtp_init void   ) 
 

Definition at line 1881 of file rtp.c.

References ast_cli_register(), and ast_rtp_reload().

Referenced by main().

int ast_rtp_lookup_code struct ast_rtp rtp,
int  isAstFormat,
int  code
 

Definition at line 811 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.

Referenced by add_codec_to_sdp(), add_noncodec_to_sdp(), add_sdp(), ast_rtp_sendcng(), ast_rtp_senddigit(), and ast_rtp_write().

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

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

Definition at line 856 of file rtp.c.

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

Referenced by process_sdp().

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

char* ast_rtp_lookup_mime_subtype int  isAstFormat,
int  code
 

Definition at line 844 of file rtp.c.

References rtpPayloadType::code, mimeTypes, and payloadType.

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

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

struct rtpPayloadType ast_rtp_lookup_pt struct ast_rtp rtp,
int  pt
 

Definition at line 792 of file rtp.c.

References rtpPayloadType::code, and rtpPayloadType::isAstFormat.

Referenced by ast_rtp_read(), and setup_rtp_connection().

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

struct ast_rtp* ast_rtp_new struct sched_context sched,
struct io_context io,
int  rtcpenable,
int  callbackmode
 

Initializate a RTP session.

Parameters:
sched 
io 
rtcpenable 
callbackmode 
Returns:
A representation (structure) of an RTP session.

Definition at line 1016 of file rtp.c.

References ast_rtp_new_with_bindaddr().

Referenced by start_rtp().

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

struct ast_rtp* ast_rtp_new_with_bindaddr struct sched_context sched,
struct io_context io,
int  rtcpenable,
int  callbackmode,
struct in_addr  in
 

Initializate a RTP session using an in_addr structure.

This fuction gets called by ast_rtp_new().

Parameters:
sched 
io 
rtcpenable 
callbackmode 
in 
Returns:
A representation (structure) of an RTP session.

Definition at line 929 of file rtp.c.

References ast_io_add(), AST_IO_IN, ast_log(), ast_rtcp_new(), ast_rtp_pt_default(), free, LOG_ERROR, malloc, rtp_socket(), rtpend, rtpread(), and rtpstart.

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

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

void ast_rtp_offered_from_local struct ast_rtp rtp,
int  local
 

Definition at line 785 of file rtp.c.

References ast_log(), and LOG_WARNING.

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

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

int ast_rtp_proto_register struct ast_rtp_protocol proto  ) 
 

Definition at line 1484 of file rtp.c.

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

Referenced by load_module(), and unload_module().

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

void ast_rtp_proto_unregister struct ast_rtp_protocol proto  ) 
 

Definition at line 1464 of file rtp.c.

References ast_rtp_protocol::next.

Referenced by unload_module().

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

void ast_rtp_pt_clear struct ast_rtp rtp  ) 
 

Definition at line 708 of file rtp.c.

Referenced by process_sdp().

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

void ast_rtp_pt_default struct ast_rtp rtp  ) 
 

Definition at line 724 of file rtp.c.

References rtpPayloadType::code, and rtpPayloadType::isAstFormat.

Referenced by ast_rtp_new_with_bindaddr().

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

struct ast_frame* ast_rtp_read struct ast_rtp rtp  ) 
 

Definition at line 426 of file rtp.c.

References ast_codec_get_samples(), AST_FORMAT_MAX_AUDIO, AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_NULL, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), AST_RTP_CISCO_DTMF, AST_RTP_CN, AST_RTP_DTMF, ast_rtp_lookup_pt(), ast_set_flag, ast_verbose(), calc_rxstamp(), rtpPayloadType::code, CRASH, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp::dtmfcount, dtmftimeout, ast_rtp::f, FLAG_NAT_ACTIVE, ast_frame::frametype, rtpPayloadType::isAstFormat, ast_rtp::lasteventseqn, ast_rtp::lastividtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxts, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, ast_rtp::nat, ast_frame::offset, option_debug, process_cisco_dtmf(), process_rfc2833(), process_rfc3389(), ast_rtp::rawdata, ast_rtp::resp, rtp_debug_test_addr(), rtpdebug, ast_rtp::rxseqno, ast_rtp::rxssrc, ast_rtp::s, ast_frame::samples, send_dtmf(), ast_frame::src, ast_frame::subclass, and ast_rtp::them.

Referenced by mgcp_rtp_read(), oh323_rtp_read(), rtpread(), sip_rtp_read(), and skinny_rtp_read().

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

void ast_rtp_reload void   ) 
 

Definition at line 1825 of file rtp.c.

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

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

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

void ast_rtp_reset struct ast_rtp rtp  ) 
 

Definition at line 1066 of file rtp.c.

References ast_rtp::dtmfcount, ast_rtp::dtmfduration, ast_rtp::dtmfmute, ast_rtp::lastdigitts, ast_rtp::lasteventendseqn, ast_rtp::lasteventseqn, ast_rtp::lastividtimestamp, ast_rtp::lastovidtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxts, ast_rtp::lastts, ast_rtp::lasttxformat, ast_rtp::rxcore, ast_rtp::rxseqno, ast_rtp::seqno, and ast_rtp::txcore.

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

int ast_rtp_sendcng struct ast_rtp rtp,
int  level
 

Definition at line 1202 of file rtp.c.

References ast_inet_ntoa(), ast_log(), AST_RTP_CN, ast_rtp_lookup_code(), ast_tvadd(), ast_verbose(), ast_rtp::dtmfmute, ast_rtp::lastts, LOG_ERROR, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.

Referenced by do_monitor().

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

int ast_rtp_senddigit struct ast_rtp rtp,
char  digit
 

Definition at line 1120 of file rtp.c.

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

Referenced by oh323_digit(), and sip_senddigit().

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

void ast_rtp_set_callback struct ast_rtp rtp,
ast_rtp_callback  callback
 

Definition at line 170 of file rtp.c.

References ast_rtp::callback.

Referenced by start_rtp().

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

void ast_rtp_set_data struct ast_rtp rtp,
void *  data
 

Definition at line 165 of file rtp.c.

References ast_rtp::data.

Referenced by start_rtp().

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

void ast_rtp_set_m_type struct ast_rtp rtp,
int  pt
 

Definition at line 742 of file rtp.c.

References rtpPayloadType::code.

Referenced by process_sdp().

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

void ast_rtp_set_peer struct ast_rtp rtp,
struct sockaddr_in *  them
 

Definition at line 1033 of file rtp.c.

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

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

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

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

Definition at line 753 of file rtp.c.

References ast_rtp::current_RTP_PT, mimeTypes, subtype, and type.

Referenced by process_sdp(), and set_dtmf_payload().

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

void ast_rtp_setnat struct ast_rtp rtp,
int  nat
 

Definition at line 175 of file rtp.c.

References ast_rtp::nat.

Referenced by check_user_full(), create_addr(), create_addr_from_peer(), oh323_request(), oh323_rtp_read(), sip_alloc(), and start_rtp().

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

int ast_rtp_settos struct ast_rtp rtp,
int  tos
 

Definition at line 1024 of file rtp.c.

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

Referenced by oh323_alloc(), and sip_alloc().

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

void ast_rtp_stop struct ast_rtp rtp  ) 
 

Definition at line 1056 of file rtp.c.

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

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

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

int ast_rtp_write struct ast_rtp rtp,
struct ast_frame f
 

Definition at line 1318 of file rtp.c.

References AST_FORMAT_ADPCM, AST_FORMAT_ALAW, AST_FORMAT_G723_1, AST_FORMAT_G726, AST_FORMAT_G729A, AST_FORMAT_GSM, AST_FORMAT_H261, AST_FORMAT_H263, AST_FORMAT_H263_PLUS, AST_FORMAT_ILBC, AST_FORMAT_LPC10, AST_FORMAT_SLINEAR, AST_FORMAT_SPEEX, AST_FORMAT_ULAW, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup(), ast_getformatname(), ast_log(), ast_rtp_lookup_code(), ast_rtp_raw_write(), ast_smoother_feed, ast_smoother_feed_be, AST_SMOOTHER_FLAG_G729, ast_smoother_free(), ast_smoother_new(), ast_smoother_read(), ast_smoother_set_flags(), ast_frame::datalen, ast_frame::frametype, LOG_DEBUG, LOG_WARNING, ast_frame::offset, option_debug, ast_frame::subclass, and ast_rtp::them.

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

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


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