Sun Jun 12 16:38:01 2011

Asterisk developer's documentation


rtp.h File Reference

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

#include <netinet/in.h>
#include "asterisk/frame.h"
#include "asterisk/io.h"
#include "asterisk/sched.h"
#include "asterisk/channel.h"
#include "asterisk/linkedlists.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
struct  ast_rtp_quality

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
#define FLAG_3389_WARNING   (1 << 0)
#define MAX_RTP_PT   256

Typedefs

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

Enumerations

enum  ast_rtp_get_result { AST_RTP_GET_FAILED = 0, AST_RTP_TRY_PARTIAL, AST_RTP_TRY_NATIVE }
enum  ast_rtp_options { AST_RTP_OPT_G726_NONSTANDARD = (1 << 0) }

Functions

int ast_rtcp_fd (struct ast_rtp *rtp)
struct ast_frameast_rtcp_read (struct ast_rtp *rtp)
int ast_rtcp_send_h261fur (void *data)
 Send an H.261 fast update request. Some devices need this rather than the XML message in SIP.
size_t ast_rtp_alloc_size (void)
 Get the amount of space required to hold an RTP session.
int ast_rtp_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
 Bridge calls. If possible and allowed, initiate re-invite so the peers exchange media directly outside of Asterisk.
void ast_rtp_change_source (struct ast_rtp *instance)
 Indicate a new source of audio has dropped in and the ssrc should change.
int ast_rtp_codec_getformat (int pt)
struct ast_codec_prefast_rtp_codec_getpref (struct ast_rtp *rtp)
int ast_rtp_codec_setpref (struct ast_rtp *rtp, struct ast_codec_pref *prefs)
void ast_rtp_destroy (struct ast_rtp *rtp)
int ast_rtp_early_bridge (struct ast_channel *dest, struct ast_channel *src)
 If possible, create an early bridge directly between the devices without having to send a re-invite later.
int ast_rtp_fd (struct ast_rtp *rtp)
struct ast_rtpast_rtp_get_bridged (struct ast_rtp *rtp)
void ast_rtp_get_current_formats (struct ast_rtp *rtp, int *astFormats, int *nonAstFormats)
 Return the union of all of the codecs that were set by rtp_set...() calls They're returned as two distinct sets: AST_FORMATs, and AST_RTPs.
int ast_rtp_get_peer (struct ast_rtp *rtp, struct sockaddr_in *them)
char * ast_rtp_get_quality (struct ast_rtp *rtp, struct ast_rtp_quality *qual)
 Return RTCP quality string.
int ast_rtp_get_rtpholdtimeout (struct ast_rtp *rtp)
 Get rtp hold timeout.
int ast_rtp_get_rtpkeepalive (struct ast_rtp *rtp)
 Get RTP keepalive interval.
int ast_rtp_get_rtptimeout (struct ast_rtp *rtp)
 Get rtp timeout.
void ast_rtp_get_us (struct ast_rtp *rtp, struct sockaddr_in *us)
int ast_rtp_getnat (struct ast_rtp *rtp)
void ast_rtp_init (void)
 Initialize the RTP system in Asterisk.
int ast_rtp_lookup_code (struct ast_rtp *rtp, int isAstFormat, int code)
 Looks up an RTP code out of our *static* outbound list.
char * ast_rtp_lookup_mime_multiple (char *buf, size_t size, const int capability, const int isAstFormat, enum ast_rtp_options options)
 Build a string of MIME subtype names from a capability list.
const char * ast_rtp_lookup_mime_subtype (int isAstFormat, int code, enum ast_rtp_options options)
 Mapping an Asterisk code into a MIME subtype (string):.
struct rtpPayloadType ast_rtp_lookup_pt (struct ast_rtp *rtp, int pt)
 Mapping between RTP payload format codes and Asterisk codes:.
int ast_rtp_make_compatible (struct ast_channel *dest, struct ast_channel *src, int media)
struct ast_rtpast_rtp_new (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode)
 Initializate a RTP session.
void ast_rtp_new_init (struct ast_rtp *rtp)
 Initialize a new RTP structure.
struct 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.
int ast_rtp_proto_register (struct ast_rtp_protocol *proto)
 Register interface to channel driver.
void ast_rtp_proto_unregister (struct ast_rtp_protocol *proto)
 Unregister interface to channel driver.
void ast_rtp_pt_clear (struct ast_rtp *rtp)
 Setting RTP payload types from lines in a SDP description:.
void ast_rtp_pt_copy (struct ast_rtp *dest, struct ast_rtp *src)
 Copy payload types between RTP structures.
void ast_rtp_pt_default (struct ast_rtp *rtp)
 Set payload types to defaults.
struct ast_frameast_rtp_read (struct ast_rtp *rtp)
int ast_rtp_reload (void)
void ast_rtp_reset (struct ast_rtp *rtp)
int ast_rtp_sendcng (struct ast_rtp *rtp, int level)
 generate comfort noice (CNG)
int ast_rtp_senddigit_begin (struct ast_rtp *rtp, char digit)
 Send begin frames for DTMF.
int ast_rtp_senddigit_end (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)
 Activate payload type.
void ast_rtp_set_peer (struct ast_rtp *rtp, struct sockaddr_in *them)
void ast_rtp_set_rtpholdtimeout (struct ast_rtp *rtp, int timeout)
 Set rtp hold timeout.
void ast_rtp_set_rtpkeepalive (struct ast_rtp *rtp, int period)
 set RTP keepalive interval
int ast_rtp_set_rtpmap_type (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype, enum ast_rtp_options options)
 Initiate payload type to a known MIME media type for a codec.
void ast_rtp_set_rtptimeout (struct ast_rtp *rtp, int timeout)
 Set rtp timeout.
void ast_rtp_set_rtptimers_onhold (struct ast_rtp *rtp)
void ast_rtp_setdtmf (struct ast_rtp *rtp, int dtmf)
 Indicate whether this RTP session is carrying DTMF or not.
void ast_rtp_setdtmfcompensate (struct ast_rtp *rtp, int compensate)
 Compensate for devices that send RFC2833 packets all at once.
void ast_rtp_setnat (struct ast_rtp *rtp, int nat)
void ast_rtp_setstun (struct ast_rtp *rtp, int stun_enable)
 Enable STUN capability.
int ast_rtp_settos (struct ast_rtp *rtp, int tos)
void ast_rtp_stop (struct ast_rtp *rtp)
void ast_rtp_stun_request (struct ast_rtp *rtp, struct sockaddr_in *suggestion, const char *username)
void ast_rtp_unset_m_type (struct ast_rtp *rtp, int pt)
 clear payload type
void ast_rtp_update_source (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 47 of file rtp.h.

Referenced by ast_rtp_read().

#define AST_RTP_CN   (1 << 1)

'Comfort Noise' (RFC3389)

Definition at line 45 of file rtp.h.

Referenced by ast_rtp_read(), and ast_rtp_sendcng().

#define AST_RTP_DTMF   (1 << 0)

#define AST_RTP_MAX   AST_RTP_CISCO_DTMF

Maximum RTP-specific code

Definition at line 49 of file rtp.h.

Referenced by add_sdp(), and ast_rtp_lookup_mime_multiple().

#define FLAG_3389_WARNING   (1 << 0)

Definition at line 93 of file rtp.h.

#define MAX_RTP_PT   256


Typedef Documentation

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

Definition at line 95 of file rtp.h.


Enumeration Type Documentation

Enumerator:
AST_RTP_GET_FAILED  Failed to find the RTP structure
AST_RTP_TRY_PARTIAL  RTP structure exists but true native bridge can not occur so try partial
AST_RTP_TRY_NATIVE  RTP structure exists and native bridge can occur

Definition at line 57 of file rtp.h.

00057                         {
00058    /*! Failed to find the RTP structure */
00059    AST_RTP_GET_FAILED = 0,
00060    /*! RTP structure exists but true native bridge can not occur so try partial */
00061    AST_RTP_TRY_PARTIAL,
00062    /*! RTP structure exists and native bridge can occur */
00063    AST_RTP_TRY_NATIVE,
00064 };

Enumerator:
AST_RTP_OPT_G726_NONSTANDARD 

Definition at line 53 of file rtp.h.

00053                      {
00054    AST_RTP_OPT_G726_NONSTANDARD = (1 << 0),
00055 };


Function Documentation

int ast_rtcp_fd ( struct ast_rtp rtp  ) 

Definition at line 518 of file rtp.c.

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

Referenced by __oh323_new(), __oh323_rtp_create(), __oh323_update_info(), gtalk_new(), sip_new(), and start_rtp().

00519 {
00520    if (rtp->rtcp)
00521       return rtp->rtcp->s;
00522    return -1;
00523 }

struct ast_frame* ast_rtcp_read ( struct ast_rtp rtp  )  [read]

Definition at line 827 of file rtp.c.

References ast_rtcp::accumulated_transit, ast_assert, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_verbose(), ast_frame::datalen, errno, ast_rtp::f, f, ast_frame::frametype, len, LOG_DEBUG, LOG_WARNING, ast_frame::mallocd, ast_rtcp::maxrtt, ast_rtcp::minrtt, ast_rtp::nat, option_debug, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtp::rtcp, rtcp_debug_test_addr(), RTCP_PT_BYE, RTCP_PT_FUR, RTCP_PT_RR, RTCP_PT_SDES, RTCP_PT_SR, ast_rtcp::rtt, ast_rtcp::rxlsr, ast_rtcp::s, ast_frame::samples, ast_rtcp::soc, ast_rtcp::spc, ast_frame::src, ast_frame::subclass, ast_rtcp::them, ast_rtcp::themrxlsr, and timeval2ntp().

Referenced by oh323_read(), sip_rtp_read(), and skinny_rtp_read().

00828 {
00829    socklen_t len;
00830    int position, i, packetwords;
00831    int res;
00832    struct sockaddr_in sin;
00833    unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET];
00834    unsigned int *rtcpheader;
00835    int pt;
00836    struct timeval now;
00837    unsigned int length;
00838    int rc;
00839    double rttsec;
00840    uint64_t rtt = 0;
00841    unsigned int dlsr;
00842    unsigned int lsr;
00843    unsigned int msw;
00844    unsigned int lsw;
00845    unsigned int comp;
00846    struct ast_frame *f = &ast_null_frame;
00847    
00848    if (!rtp || !rtp->rtcp)
00849       return &ast_null_frame;
00850 
00851    len = sizeof(sin);
00852    
00853    res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET,
00854                0, (struct sockaddr *)&sin, &len);
00855    rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET);
00856    
00857    if (res < 0) {
00858       ast_assert(errno != EBADF);
00859       if (errno != EAGAIN) {
00860          ast_log(LOG_WARNING, "RTCP Read error: %s.  Hanging up.\n", strerror(errno));
00861          return NULL;
00862       }
00863       return &ast_null_frame;
00864    }
00865 
00866    packetwords = res / 4;
00867    
00868    if (rtp->nat) {
00869       /* Send to whoever sent to us */
00870       if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
00871           (rtp->rtcp->them.sin_port != sin.sin_port)) {
00872          memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
00873          if (option_debug || rtpdebug)
00874             ast_log(LOG_DEBUG, "RTCP NAT: Got RTCP from other end. Now sending to address %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
00875       }
00876    }
00877 
00878    if (option_debug)
00879       ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res);
00880 
00881    /* Process a compound packet */
00882    position = 0;
00883    while (position < packetwords) {
00884       i = position;
00885       length = ntohl(rtcpheader[i]);
00886       pt = (length & 0xff0000) >> 16;
00887       rc = (length & 0x1f000000) >> 24;
00888       length &= 0xffff;
00889     
00890       if ((i + length) > packetwords) {
00891          ast_log(LOG_WARNING, "RTCP Read too short\n");
00892          return &ast_null_frame;
00893       }
00894       
00895       if (rtcp_debug_test_addr(&sin)) {
00896          ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
00897          ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown");
00898          ast_verbose("Reception reports: %d\n", rc);
00899          ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]);
00900       }
00901     
00902       i += 2; /* Advance past header and ssrc */
00903       
00904       switch (pt) {
00905       case RTCP_PT_SR:
00906          gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */
00907          rtp->rtcp->spc = ntohl(rtcpheader[i+3]);
00908          rtp->rtcp->soc = ntohl(rtcpheader[i + 4]);
00909          rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/
00910     
00911          if (rtcp_debug_test_addr(&sin)) {
00912             ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096);
00913             ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2]));
00914             ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4]));
00915          }
00916          i += 5;
00917          if (rc < 1)
00918             break;
00919          /* Intentional fall through */
00920       case RTCP_PT_RR:
00921          /* Don't handle multiple reception reports (rc > 1) yet */
00922          /* Calculate RTT per RFC */
00923          gettimeofday(&now, NULL);
00924          timeval2ntp(now, &msw, &lsw);
00925          if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */
00926             comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16);
00927             lsr = ntohl(rtcpheader[i + 4]);
00928             dlsr = ntohl(rtcpheader[i + 5]);
00929             rtt = comp - lsr - dlsr;
00930 
00931             /* Convert end to end delay to usec (keeping the calculation in 64bit space)
00932                sess->ee_delay = (eedelay * 1000) / 65536; */
00933             if (rtt < 4294) {
00934                 rtt = (rtt * 1000000) >> 16;
00935             } else {
00936                 rtt = (rtt * 1000) >> 16;
00937                 rtt *= 1000;
00938             }
00939             rtt = rtt / 1000.;
00940             rttsec = rtt / 1000.;
00941 
00942             if (comp - dlsr >= lsr) {
00943                rtp->rtcp->accumulated_transit += rttsec;
00944                rtp->rtcp->rtt = rttsec;
00945                if (rtp->rtcp->maxrtt<rttsec)
00946                   rtp->rtcp->maxrtt = rttsec;
00947                if (rtp->rtcp->minrtt>rttsec)
00948                   rtp->rtcp->minrtt = rttsec;
00949             } else if (rtcp_debug_test_addr(&sin)) {
00950                ast_verbose("Internal RTCP NTP clock skew detected: "
00951                         "lsr=%u, now=%u, dlsr=%u (%d:%03dms), "
00952                         "diff=%d\n",
00953                         lsr, comp, dlsr, dlsr / 65536,
00954                         (dlsr % 65536) * 1000 / 65536,
00955                         dlsr - (comp - lsr));
00956             }
00957          }
00958 
00959          rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]);
00960          rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff;
00961          if (rtcp_debug_test_addr(&sin)) {
00962             ast_verbose("  Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24));
00963             ast_verbose("  Packets lost so far: %d\n", rtp->rtcp->reported_lost);
00964             ast_verbose("  Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff));
00965             ast_verbose("  Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16);
00966             ast_verbose("  Interarrival jitter: %u\n", rtp->rtcp->reported_jitter);
00967             ast_verbose("  Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096);
00968             ast_verbose("  DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0);
00969             if (rtt)
00970                ast_verbose("  RTT: %lu(sec)\n", (unsigned long) rtt);
00971          }
00972          break;
00973       case RTCP_PT_FUR:
00974          if (rtcp_debug_test_addr(&sin))
00975             ast_verbose("Received an RTCP Fast Update Request\n");
00976          rtp->f.frametype = AST_FRAME_CONTROL;
00977          rtp->f.subclass = AST_CONTROL_VIDUPDATE;
00978          rtp->f.datalen = 0;
00979          rtp->f.samples = 0;
00980          rtp->f.mallocd = 0;
00981          rtp->f.src = "RTP";
00982          f = &rtp->f;
00983          break;
00984       case RTCP_PT_SDES:
00985          if (rtcp_debug_test_addr(&sin))
00986             ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
00987          break;
00988       case RTCP_PT_BYE:
00989          if (rtcp_debug_test_addr(&sin))
00990             ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
00991          break;
00992       default:
00993          if (option_debug)
00994             ast_log(LOG_DEBUG, "Unknown RTCP packet (pt=%d) received from %s:%d\n", pt, ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
00995          break;
00996       }
00997       position += (length + 1);
00998    }
00999          
01000    return f;
01001 }

int ast_rtcp_send_h261fur ( void *  data  ) 

Send an H.261 fast update request. Some devices need this rather than the XML message in SIP.

Definition at line 2366 of file rtp.c.

References ast_rtcp_write(), ast_rtp::rtcp, and ast_rtcp::sendfur.

02367 {
02368    struct ast_rtp *rtp = data;
02369    int res;
02370 
02371    rtp->rtcp->sendfur = 1;
02372    res = ast_rtcp_write(data);
02373    
02374    return res;
02375 }

size_t ast_rtp_alloc_size ( void   ) 

Get the amount of space required to hold an RTP session.

Returns:
number of bytes required

Definition at line 398 of file rtp.c.

Referenced by process_sdp().

00399 {
00400    return sizeof(struct ast_rtp);
00401 }

int ast_rtp_bridge ( struct ast_channel c0,
struct ast_channel c1,
int  flags,
struct ast_frame **  fo,
struct ast_channel **  rc,
int  timeoutms 
)

Bridge calls. If possible and allowed, initiate re-invite so the peers exchange media directly outside of Asterisk.

Definition at line 3304 of file rtp.c.

References AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_check_hangup(), ast_codec_pref_getsize(), ast_log(), AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, ast_set_flag, ast_test_flag, ast_verbose(), bridge_native_loop(), bridge_p2p_loop(), ast_format_list::cur_ms, FLAG_HAS_DTMF, FLAG_P2P_NEED_DTMF, ast_rtp_protocol::get_codec, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_vrtp_info, LOG_DEBUG, LOG_WARNING, option_debug, option_verbose, ast_rtp::pref, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel_tech::send_digit_begin, ast_channel::tech, ast_channel::tech_pvt, and VERBOSE_PREFIX_3.

03305 {
03306    struct ast_rtp *p0 = NULL, *p1 = NULL;    /* Audio RTP Channels */
03307    struct ast_rtp *vp0 = NULL, *vp1 = NULL;  /* Video RTP channels */
03308    struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL;
03309    enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED;
03310    enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED;
03311    enum ast_bridge_result res = AST_BRIDGE_FAILED;
03312    int codec0 = 0, codec1 = 0;
03313    void *pvt0 = NULL, *pvt1 = NULL;
03314 
03315    /* Lock channels */
03316    ast_channel_lock(c0);
03317    while(ast_channel_trylock(c1)) {
03318       ast_channel_unlock(c0);
03319       usleep(1);
03320       ast_channel_lock(c0);
03321    }
03322 
03323    /* Ensure neither channel got hungup during lock avoidance */
03324    if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
03325       ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name);
03326       ast_channel_unlock(c0);
03327       ast_channel_unlock(c1);
03328       return AST_BRIDGE_FAILED;
03329    }
03330       
03331    /* Find channel driver interfaces */
03332    if (!(pr0 = get_proto(c0))) {
03333       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
03334       ast_channel_unlock(c0);
03335       ast_channel_unlock(c1);
03336       return AST_BRIDGE_FAILED;
03337    }
03338    if (!(pr1 = get_proto(c1))) {
03339       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
03340       ast_channel_unlock(c0);
03341       ast_channel_unlock(c1);
03342       return AST_BRIDGE_FAILED;
03343    }
03344 
03345    /* Get channel specific interface structures */
03346    pvt0 = c0->tech_pvt;
03347    pvt1 = c1->tech_pvt;
03348 
03349    /* Get audio and video interface (if native bridge is possible) */
03350    audio_p0_res = pr0->get_rtp_info(c0, &p0);
03351    video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
03352    audio_p1_res = pr1->get_rtp_info(c1, &p1);
03353    video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
03354 
03355    /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */
03356    if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE))
03357       audio_p0_res = AST_RTP_GET_FAILED;
03358    if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE))
03359       audio_p1_res = AST_RTP_GET_FAILED;
03360 
03361    /* Check if a bridge is possible (partial/native) */
03362    if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) {
03363       /* Somebody doesn't want to play... */
03364       ast_channel_unlock(c0);
03365       ast_channel_unlock(c1);
03366       return AST_BRIDGE_FAILED_NOWARN;
03367    }
03368 
03369    /* If we need to feed DTMF frames into the core then only do a partial native bridge */
03370    if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
03371       ast_set_flag(p0, FLAG_P2P_NEED_DTMF);
03372       audio_p0_res = AST_RTP_TRY_PARTIAL;
03373    }
03374 
03375    if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) {
03376       ast_set_flag(p1, FLAG_P2P_NEED_DTMF);
03377       audio_p1_res = AST_RTP_TRY_PARTIAL;
03378    }
03379 
03380    /* If both sides are not using the same method of DTMF transmission 
03381     * (ie: one is RFC2833, other is INFO... then we can not do direct media. 
03382     * --------------------------------------------------
03383     * | DTMF Mode |  HAS_DTMF  |  Accepts Begin Frames |
03384     * |-----------|------------|-----------------------|
03385     * | Inband    | False      | True                  |
03386     * | RFC2833   | True       | True                  |
03387     * | SIP INFO  | False      | False                 |
03388     * --------------------------------------------------
03389     * However, if DTMF from both channels is being monitored by the core, then
03390     * we can still do packet-to-packet bridging, because passing through the 
03391     * core will handle DTMF mode translation.
03392     */
03393    if ( (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) ||
03394        (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) {
03395       if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) {
03396          ast_channel_unlock(c0);
03397          ast_channel_unlock(c1);
03398          return AST_BRIDGE_FAILED_NOWARN;
03399       }
03400       audio_p0_res = AST_RTP_TRY_PARTIAL;
03401       audio_p1_res = AST_RTP_TRY_PARTIAL;
03402    }
03403 
03404    /* If we need to feed frames into the core don't do a P2P bridge */
03405    if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF)) ||
03406        (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF))) {
03407       ast_channel_unlock(c0);
03408       ast_channel_unlock(c1);
03409       return AST_BRIDGE_FAILED_NOWARN;
03410    }
03411 
03412    /* Get codecs from both sides */
03413    codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0;
03414    codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0;
03415    if (codec0 && codec1 && !(codec0 & codec1)) {
03416       /* Hey, we can't do native bridging if both parties speak different codecs */
03417       if (option_debug)
03418          ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1);
03419       ast_channel_unlock(c0);
03420       ast_channel_unlock(c1);
03421       return AST_BRIDGE_FAILED_NOWARN;
03422    }
03423 
03424    /* If either side can only do a partial bridge, then don't try for a true native bridge */
03425    if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) {
03426       struct ast_format_list fmt0, fmt1;
03427 
03428       /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */
03429       if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) {
03430          if (option_debug)
03431             ast_log(LOG_DEBUG, "Cannot packet2packet bridge - raw formats are incompatible\n");
03432          ast_channel_unlock(c0);
03433          ast_channel_unlock(c1);
03434          return AST_BRIDGE_FAILED_NOWARN;
03435       }
03436       /* They must also be using the same packetization */
03437       fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat);
03438       fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat);
03439       if (fmt0.cur_ms != fmt1.cur_ms) {
03440          if (option_debug)
03441             ast_log(LOG_DEBUG, "Cannot packet2packet bridge - packetization settings prevent it\n");
03442          ast_channel_unlock(c0);
03443          ast_channel_unlock(c1);
03444          return AST_BRIDGE_FAILED_NOWARN;
03445       }
03446 
03447       if (option_verbose > 2)
03448          ast_verbose(VERBOSE_PREFIX_3 "Packet2Packet bridging %s and %s\n", c0->name, c1->name);
03449       res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1);
03450    } else {
03451       if (option_verbose > 2) 
03452          ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
03453       res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1);
03454    }
03455 
03456    return res;
03457 }

void ast_rtp_change_source ( struct ast_rtp instance  ) 

Indicate a new source of audio has dropped in and the ssrc should change.

Parameters:
instance Instance that the new media source is feeding into
Example usage:

 ast_rtp_instance_change_source(instance);

This indicates that the source of media that is feeding the instance pointed to by instance has changed and that the marker bit should be set and the SSRC updated.

Definition at line 2021 of file rtp.c.

References ast_log(), ast_random(), LOG_DEBUG, ast_rtp::set_marker_bit, and ast_rtp::ssrc.

Referenced by mgcp_indicate(), oh323_indicate(), sip_indicate(), and skinny_indicate().

02022 {
02023    unsigned int ssrc = ast_random();
02024    /* We simply set this bit so that the next packet sent will have the marker bit turned on */
02025    rtp->set_marker_bit = 1;
02026    ast_log(LOG_DEBUG, "Changing ssrc from %u to %u due to a source change\n", rtp->ssrc, ssrc);
02027 
02028    rtp->ssrc = ssrc;
02029 }

int ast_rtp_codec_getformat ( int  pt  ) 

Definition at line 2748 of file rtp.c.

References rtpPayloadType::code, and MAX_RTP_PT.

Referenced by process_sdp().

02749 {
02750    if (pt < 0 || pt > MAX_RTP_PT)
02751       return 0; /* bogus payload type */
02752 
02753    if (static_RTP_PT[pt].isAstFormat)
02754       return static_RTP_PT[pt].code;
02755    else
02756       return 0;
02757 }

struct ast_codec_pref* ast_rtp_codec_getpref ( struct ast_rtp rtp  )  [read]

Definition at line 2743 of file rtp.c.

References ast_rtp::pref.

Referenced by add_codec_to_sdp(), and process_sdp().

02744 {
02745    return &rtp->pref;
02746 }

int ast_rtp_codec_setpref ( struct ast_rtp rtp,
struct ast_codec_pref prefs 
)

Definition at line 2730 of file rtp.c.

References ast_smoother_free(), ast_codec_pref::framing, ast_codec_pref::order, ast_rtp::pref, and ast_rtp::smoother.

Referenced by __oh323_rtp_create(), check_user_full(), create_addr_from_peer(), process_sdp(), register_verify(), set_peer_capabilities(), sip_alloc(), start_rtp(), and transmit_response_with_sdp().

02731 {
02732    int x;
02733    for (x = 0; x < 32; x++) {  /* Ugly way */
02734       rtp->pref.order[x] = prefs->order[x];
02735       rtp->pref.framing[x] = prefs->framing[x];
02736    }
02737    if (rtp->smoother)
02738       ast_smoother_free(rtp->smoother);
02739    rtp->smoother = NULL;
02740    return 0;
02741 }

void ast_rtp_destroy ( struct ast_rtp rtp  ) 

Definition at line 2149 of file rtp.c.

References ast_io_remove(), ast_mutex_destroy(), AST_SCHED_DEL, ast_smoother_free(), ast_verbose(), ast_rtp::bridge_lock, ast_rtcp::expected_prior, free, ast_rtp::io, ast_rtp::ioid, ast_rtcp::received_prior, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtcp::rr_count, ast_rtp::rtcp, rtcp_debug_test_addr(), ast_rtcp::rtt, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtp::rxtransit, ast_rtcp::s, ast_rtp::s, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::smoother, ast_rtcp::sr_count, ast_rtp::ssrc, ast_rtp::them, ast_rtp::themssrc, and ast_rtp::txcount.

Referenced by __oh323_destroy(), __sip_destroy(), check_user_full(), cleanup_connection(), create_addr_from_peer(), destroy_endpoint(), gtalk_free_pvt(), mgcp_hangup(), oh323_alloc(), skinny_hangup(), start_rtp(), and unalloc_sub().

02150 {
02151    if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) {
02152       /*Print some info on the call here */
02153       ast_verbose("  RTP-stats\n");
02154       ast_verbose("* Our Receiver:\n");
02155       ast_verbose("  SSRC:     %u\n", rtp->themssrc);
02156       ast_verbose("  Received packets: %u\n", rtp->rxcount);
02157       ast_verbose("  Lost packets:   %u\n", rtp->rtcp->expected_prior - rtp->rtcp->received_prior);
02158       ast_verbose("  Jitter:      %.4f\n", rtp->rxjitter);
02159       ast_verbose("  Transit:     %.4f\n", rtp->rxtransit);
02160       ast_verbose("  RR-count:    %u\n", rtp->rtcp->rr_count);
02161       ast_verbose("* Our Sender:\n");
02162       ast_verbose("  SSRC:     %u\n", rtp->ssrc);
02163       ast_verbose("  Sent packets:   %u\n", rtp->txcount);
02164       ast_verbose("  Lost packets:   %u\n", rtp->rtcp->reported_lost);
02165       ast_verbose("  Jitter:      %u\n", rtp->rtcp->reported_jitter / (unsigned int)65536.0);
02166       ast_verbose("  SR-count:    %u\n", rtp->rtcp->sr_count);
02167       ast_verbose("  RTT:      %f\n", rtp->rtcp->rtt);
02168    }
02169 
02170    if (rtp->smoother)
02171       ast_smoother_free(rtp->smoother);
02172    if (rtp->ioid)
02173       ast_io_remove(rtp->io, rtp->ioid);
02174    if (rtp->s > -1)
02175       close(rtp->s);
02176    if (rtp->rtcp) {
02177       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02178       close(rtp->rtcp->s);
02179       free(rtp->rtcp);
02180       rtp->rtcp=NULL;
02181    }
02182 
02183    ast_mutex_destroy(&rtp->bridge_lock);
02184 
02185    free(rtp);
02186 }

int ast_rtp_early_bridge ( struct ast_channel dest,
struct ast_channel src 
)

If possible, create an early bridge directly between the devices without having to send a re-invite later.

Definition at line 1491 of file rtp.c.

References ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_log(), AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, 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, LOG_DEBUG, LOG_WARNING, option_debug, and ast_rtp_protocol::set_rtp_peer.

Referenced by wait_for_answer().

01492 {
01493    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
01494    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
01495    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
01496    enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED;
01497    enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED;
01498    int srccodec, destcodec, nat_active = 0;
01499 
01500    /* Lock channels */
01501    ast_channel_lock(dest);
01502    if (src) {
01503       while(ast_channel_trylock(src)) {
01504          ast_channel_unlock(dest);
01505          usleep(1);
01506          ast_channel_lock(dest);
01507       }
01508    }
01509 
01510    /* Find channel driver interfaces */
01511    destpr = get_proto(dest);
01512    if (src)
01513       srcpr = get_proto(src);
01514    if (!destpr) {
01515       if (option_debug)
01516          ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name);
01517       ast_channel_unlock(dest);
01518       if (src)
01519          ast_channel_unlock(src);
01520       return 0;
01521    }
01522    if (!srcpr) {
01523       if (option_debug)
01524          ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src ? src->name : "<unspecified>");
01525       ast_channel_unlock(dest);
01526       if (src)
01527          ast_channel_unlock(src);
01528       return 0;
01529    }
01530 
01531    /* Get audio and video interface (if native bridge is possible) */
01532    audio_dest_res = destpr->get_rtp_info(dest, &destp);
01533    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED;
01534    if (srcpr) {
01535       audio_src_res = srcpr->get_rtp_info(src, &srcp);
01536       video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED;
01537    }
01538 
01539    /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
01540    if (audio_dest_res != AST_RTP_TRY_NATIVE) {
01541       /* Somebody doesn't want to play... */
01542       ast_channel_unlock(dest);
01543       if (src)
01544          ast_channel_unlock(src);
01545       return 0;
01546    }
01547    if (audio_src_res == AST_RTP_TRY_NATIVE && srcpr->get_codec)
01548       srccodec = srcpr->get_codec(src);
01549    else
01550       srccodec = 0;
01551    if (audio_dest_res == AST_RTP_TRY_NATIVE && destpr->get_codec)
01552       destcodec = destpr->get_codec(dest);
01553    else
01554       destcodec = 0;
01555    /* Ensure we have at least one matching codec */
01556    if (!(srccodec & destcodec)) {
01557       ast_channel_unlock(dest);
01558       if (src)
01559          ast_channel_unlock(src);
01560       return 0;
01561    }
01562    /* Consider empty media as non-existant */
01563    if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr)
01564       srcp = NULL;
01565    /* If the client has NAT stuff turned on then just safe NAT is active */
01566    if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
01567       nat_active = 1;
01568    /* Bridge media early */
01569    if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, nat_active))
01570       ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src ? src->name : "<unspecified>");
01571    ast_channel_unlock(dest);
01572    if (src)
01573       ast_channel_unlock(src);
01574    if (option_debug)
01575       ast_log(LOG_DEBUG, "Setting early bridge SDP of '%s' with that of '%s'\n", dest->name, src ? src->name : "<unspecified>");
01576    return 1;
01577 }

int ast_rtp_fd ( struct ast_rtp rtp  ) 

Definition at line 513 of file rtp.c.

References ast_rtp::s.

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

00514 {
00515    return rtp->s;
00516 }

struct ast_rtp* ast_rtp_get_bridged ( struct ast_rtp rtp  )  [read]

Definition at line 2060 of file rtp.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, and ast_rtp::bridged.

Referenced by __sip_destroy(), and ast_rtp_read().

02061 {
02062    struct ast_rtp *bridged = NULL;
02063 
02064    ast_mutex_lock(&rtp->bridge_lock);
02065    bridged = rtp->bridged;
02066    ast_mutex_unlock(&rtp->bridge_lock);
02067 
02068    return bridged;
02069 }

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

Return the union of all of the codecs that were set by rtp_set...() calls They're returned as two distinct sets: AST_FORMATs, and AST_RTPs.

Definition at line 1713 of file rtp.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, and MAX_RTP_PT.

Referenced by gtalk_is_answered(), gtalk_newcall(), and process_sdp().

01715 {
01716    int pt;
01717    
01718    ast_mutex_lock(&rtp->bridge_lock);
01719    
01720    *astFormats = *nonAstFormats = 0;
01721    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
01722       if (rtp->current_RTP_PT[pt].isAstFormat) {
01723          *astFormats |= rtp->current_RTP_PT[pt].code;
01724       } else {
01725          *nonAstFormats |= rtp->current_RTP_PT[pt].code;
01726       }
01727    }
01728    
01729    ast_mutex_unlock(&rtp->bridge_lock);
01730    
01731    return;
01732 }

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

Definition at line 2042 of file rtp.c.

References ast_rtp::them.

Referenced by add_sdp(), bridge_native_loop(), do_monitor(), gtalk_update_stun(), oh323_set_rtp_peer(), process_sdp(), sip_set_rtp_peer(), and transmit_modify_with_sdp().

02043 {
02044    if ((them->sin_family != AF_INET) ||
02045       (them->sin_port != rtp->them.sin_port) ||
02046       (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
02047       them->sin_family = AF_INET;
02048       them->sin_port = rtp->them.sin_port;
02049       them->sin_addr = rtp->them.sin_addr;
02050       return 1;
02051    }
02052    return 0;
02053 }

char* ast_rtp_get_quality ( struct ast_rtp rtp,
struct ast_rtp_quality qual 
)

Return RTCP quality string.

Definition at line 2105 of file rtp.c.

References ast_rtcp::expected_prior, ast_rtp_quality::local_count, ast_rtp_quality::local_jitter, ast_rtp_quality::local_lostpackets, ast_rtp_quality::local_ssrc, ast_rtcp::quality, ast_rtcp::received_prior, ast_rtp_quality::remote_count, ast_rtp_quality::remote_jitter, ast_rtp_quality::remote_lostpackets, ast_rtp_quality::remote_ssrc, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtp::rtcp, ast_rtcp::rtt, ast_rtp_quality::rtt, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtp::ssrc, ast_rtp::themssrc, and ast_rtp::txcount.

Referenced by acf_channel_read(), handle_request_bye(), and sip_hangup().

02106 {
02107    /*
02108    *ssrc          our ssrc
02109    *themssrc      their ssrc
02110    *lp            lost packets
02111    *rxjitter      our calculated jitter(rx)
02112    *rxcount       no. received packets
02113    *txjitter      reported jitter of the other end
02114    *txcount       transmitted packets
02115    *rlp           remote lost packets
02116    *rtt           round trip time
02117    */
02118 
02119    if (qual && rtp) {
02120       qual->local_ssrc = rtp->ssrc;
02121       qual->local_jitter = rtp->rxjitter;
02122       qual->local_count = rtp->rxcount;
02123       qual->remote_ssrc = rtp->themssrc;
02124       qual->remote_count = rtp->txcount;
02125       if (rtp->rtcp) {
02126          qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior;
02127          qual->remote_lostpackets = rtp->rtcp->reported_lost;
02128          qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0;
02129          qual->rtt = rtp->rtcp->rtt;
02130       }
02131    }
02132    if (rtp->rtcp) {
02133       snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality),
02134          "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f",
02135          rtp->ssrc,
02136          rtp->themssrc,
02137          rtp->rtcp->expected_prior - rtp->rtcp->received_prior,
02138          rtp->rxjitter,
02139          rtp->rxcount,
02140          (double)rtp->rtcp->reported_jitter / 65536.0,
02141          rtp->txcount,
02142          rtp->rtcp->reported_lost,
02143          rtp->rtcp->rtt);
02144       return rtp->rtcp->quality;
02145    } else
02146       return "<Unknown> - RTP/RTCP has already been destroyed";
02147 }

int ast_rtp_get_rtpholdtimeout ( struct ast_rtp rtp  ) 

Get rtp hold timeout.

Definition at line 568 of file rtp.c.

References ast_rtp::rtpholdtimeout, and ast_rtp::rtptimeout.

Referenced by do_monitor().

00569 {
00570    if (rtp->rtptimeout < 0)   /* We're not checking, but remembering the setting (during T.38 transmission) */
00571       return 0;
00572    return rtp->rtpholdtimeout;
00573 }

int ast_rtp_get_rtpkeepalive ( struct ast_rtp rtp  ) 

Get RTP keepalive interval.

Definition at line 576 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by do_monitor().

00577 {
00578    return rtp->rtpkeepalive;
00579 }

int ast_rtp_get_rtptimeout ( struct ast_rtp rtp  ) 

Get rtp timeout.

Definition at line 560 of file rtp.c.

References ast_rtp::rtptimeout.

Referenced by do_monitor().

00561 {
00562    if (rtp->rtptimeout < 0)   /* We're not checking, but remembering the setting (during T.38 transmission) */
00563       return 0;
00564    return rtp->rtptimeout;
00565 }

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

Definition at line 2055 of file rtp.c.

References ast_rtp::us.

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

02056 {
02057    *us = rtp->us;
02058 }

int ast_rtp_getnat ( struct ast_rtp rtp  ) 

Definition at line 596 of file rtp.c.

References ast_test_flag, and FLAG_NAT_ACTIVE.

Referenced by sip_get_rtp_peer().

00597 {
00598    return ast_test_flag(rtp, FLAG_NAT_ACTIVE);
00599 }

void ast_rtp_init ( void   ) 

Initialize the RTP system in Asterisk.

Definition at line 3842 of file rtp.c.

References ast_cli_register_multiple(), and ast_rtp_reload().

Referenced by main().

03843 {
03844    ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
03845    ast_rtp_reload();
03846 }

int ast_rtp_lookup_code ( struct ast_rtp rtp,
int  isAstFormat,
int  code 
)

Looks up an RTP code out of our *static* outbound list.

Definition at line 1756 of file rtp.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.

Referenced by add_codec_to_answer(), add_codec_to_sdp(), add_noncodec_to_sdp(), add_sdp(), ast_rtp_sendcng(), ast_rtp_senddigit_begin(), ast_rtp_write(), and bridge_p2p_rtp_write().

01757 {
01758    int pt = 0;
01759 
01760    ast_mutex_lock(&rtp->bridge_lock);
01761 
01762    if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
01763       code == rtp->rtp_lookup_code_cache_code) {
01764       /* Use our cached mapping, to avoid the overhead of the loop below */
01765       pt = rtp->rtp_lookup_code_cache_result;
01766       ast_mutex_unlock(&rtp->bridge_lock);
01767       return pt;
01768    }
01769 
01770    /* Check the dynamic list first */
01771    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
01772       if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
01773          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
01774          rtp->rtp_lookup_code_cache_code = code;
01775          rtp->rtp_lookup_code_cache_result = pt;
01776          ast_mutex_unlock(&rtp->bridge_lock);
01777          return pt;
01778       }
01779    }
01780 
01781    /* Then the static list */
01782    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
01783       if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) {
01784          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
01785          rtp->rtp_lookup_code_cache_code = code;
01786          rtp->rtp_lookup_code_cache_result = pt;
01787          ast_mutex_unlock(&rtp->bridge_lock);
01788          return pt;
01789       }
01790    }
01791 
01792    ast_mutex_unlock(&rtp->bridge_lock);
01793 
01794    return -1;
01795 }

char* ast_rtp_lookup_mime_multiple ( char *  buf,
size_t  size,
const int  capability,
const int  isAstFormat,
enum ast_rtp_options  options 
)

Build a string of MIME subtype names from a capability list.

Definition at line 1816 of file rtp.c.

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

Referenced by process_sdp().

01818 {
01819    int format;
01820    unsigned len;
01821    char *end = buf;
01822    char *start = buf;
01823 
01824    if (!buf || !size)
01825       return NULL;
01826 
01827    snprintf(end, size, "0x%x (", capability);
01828 
01829    len = strlen(end);
01830    end += len;
01831    size -= len;
01832    start = end;
01833 
01834    for (format = 1; format < AST_RTP_MAX; format <<= 1) {
01835       if (capability & format) {
01836          const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options);
01837 
01838          snprintf(end, size, "%s|", name);
01839          len = strlen(end);
01840          end += len;
01841          size -= len;
01842       }
01843    }
01844 
01845    if (start == end)
01846       snprintf(start, size, "nothing)"); 
01847    else if (size > 1)
01848       *(end -1) = ')';
01849    
01850    return buf;
01851 }

const char* ast_rtp_lookup_mime_subtype ( int  isAstFormat,
int  code,
enum ast_rtp_options  options 
)

Mapping an Asterisk code into a MIME subtype (string):.

Definition at line 1797 of file rtp.c.

References AST_FORMAT_G726_AAL2, AST_RTP_OPT_G726_NONSTANDARD, 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().

01799 {
01800    unsigned int i;
01801 
01802    for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) {
01803       if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
01804          if (isAstFormat &&
01805              (code == AST_FORMAT_G726_AAL2) &&
01806              (options & AST_RTP_OPT_G726_NONSTANDARD))
01807             return "G726-32";
01808          else
01809             return mimeTypes[i].subtype;
01810       }
01811    }
01812 
01813    return "";
01814 }

struct rtpPayloadType ast_rtp_lookup_pt ( struct ast_rtp rtp,
int  pt 
) [read]

Mapping between RTP payload format codes and Asterisk codes:.

Definition at line 1734 of file rtp.c.

References ast_mutex_lock(), ast_mutex_unlock(), rtpPayloadType::code, rtpPayloadType::isAstFormat, and MAX_RTP_PT.

Referenced by ast_rtp_read(), bridge_p2p_rtp_write(), and setup_rtp_connection().

01735 {
01736    struct rtpPayloadType result;
01737 
01738    result.isAstFormat = result.code = 0;
01739 
01740    if (pt < 0 || pt > MAX_RTP_PT) 
01741       return result; /* bogus payload type */
01742 
01743    /* Start with negotiated codecs */
01744    ast_mutex_lock(&rtp->bridge_lock);
01745    result = rtp->current_RTP_PT[pt];
01746    ast_mutex_unlock(&rtp->bridge_lock);
01747 
01748    /* If it doesn't exist, check our static RTP type list, just in case */
01749    if (!result.code) 
01750       result = static_RTP_PT[pt];
01751 
01752    return result;
01753 }

int ast_rtp_make_compatible ( struct ast_channel dest,
struct ast_channel src,
int  media 
)

Definition at line 1579 of file rtp.c.

References ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_log(), AST_RTP_GET_FAILED, ast_rtp_pt_copy(), AST_RTP_TRY_NATIVE, 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, LOG_DEBUG, LOG_WARNING, option_debug, and ast_rtp_protocol::set_rtp_peer.

Referenced by wait_for_answer().

01580 {
01581    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
01582    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
01583    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
01584    enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED;
01585    enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 
01586    int srccodec, destcodec;
01587 
01588    /* Lock channels */
01589    ast_channel_lock(dest);
01590    while(ast_channel_trylock(src)) {
01591       ast_channel_unlock(dest);
01592       usleep(1);
01593       ast_channel_lock(dest);
01594    }
01595 
01596    /* Find channel driver interfaces */
01597    if (!(destpr = get_proto(dest))) {
01598       if (option_debug)
01599          ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name);
01600       ast_channel_unlock(dest);
01601       ast_channel_unlock(src);
01602       return 0;
01603    }
01604    if (!(srcpr = get_proto(src))) {
01605       if (option_debug)
01606          ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src->name);
01607       ast_channel_unlock(dest);
01608       ast_channel_unlock(src);
01609       return 0;
01610    }
01611 
01612    /* Get audio and video interface (if native bridge is possible) */
01613    audio_dest_res = destpr->get_rtp_info(dest, &destp);
01614    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED;
01615    audio_src_res = srcpr->get_rtp_info(src, &srcp);
01616    video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED;
01617 
01618    /* Ensure we have at least one matching codec */
01619    if (srcpr->get_codec)
01620       srccodec = srcpr->get_codec(src);
01621    else
01622       srccodec = 0;
01623    if (destpr->get_codec)
01624       destcodec = destpr->get_codec(dest);
01625    else
01626       destcodec = 0;
01627 
01628    /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
01629    if (audio_dest_res != AST_RTP_TRY_NATIVE || audio_src_res != AST_RTP_TRY_NATIVE || !(srccodec & destcodec)) {
01630       /* Somebody doesn't want to play... */
01631       ast_channel_unlock(dest);
01632       ast_channel_unlock(src);
01633       return 0;
01634    }
01635    ast_rtp_pt_copy(destp, srcp);
01636    if (vdestp && vsrcp)
01637       ast_rtp_pt_copy(vdestp, vsrcp);
01638    if (media) {
01639       /* Bridge early */
01640       if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
01641          ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name);
01642    }
01643    ast_channel_unlock(dest);
01644    ast_channel_unlock(src);
01645    if (option_debug)
01646       ast_log(LOG_DEBUG, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name);
01647    return 1;
01648 }

struct ast_rtp* ast_rtp_new ( struct sched_context sched,
struct io_context io,
int  rtcpenable,
int  callbackmode 
) [read]

Initializate a RTP session.

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

Definition at line 1998 of file rtp.c.

References ast_rtp_new_with_bindaddr().

01999 {
02000    struct in_addr ia;
02001 
02002    memset(&ia, 0, sizeof(ia));
02003    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
02004 }

void ast_rtp_new_init ( struct ast_rtp rtp  ) 

Initialize a new RTP structure.

Definition at line 1898 of file rtp.c.

References ast_mutex_init(), ast_random(), ast_set_flag, ast_rtp::bridge_lock, FLAG_HAS_DTMF, ast_rtp::seqno, ast_rtp::ssrc, ast_rtp::them, and ast_rtp::us.

Referenced by ast_rtp_new_with_bindaddr(), and process_sdp().

01899 {
01900    ast_mutex_init(&rtp->bridge_lock);
01901 
01902    rtp->them.sin_family = AF_INET;
01903    rtp->us.sin_family = AF_INET;
01904    rtp->ssrc = ast_random();
01905    rtp->seqno = ast_random() & 0xffff;
01906    ast_set_flag(rtp, FLAG_HAS_DTMF);
01907 
01908    return;
01909 }

struct ast_rtp* ast_rtp_new_with_bindaddr ( struct sched_context sched,
struct io_context io,
int  rtcpenable,
int  callbackmode,
struct in_addr  in 
) [read]

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

References ast_calloc, ast_io_add(), AST_IO_IN, ast_log(), ast_random(), ast_rtcp_new(), ast_rtp_new_init(), ast_rtp_pt_default(), ast_set_flag, errno, FLAG_CALLBACK_MODE, free, ast_rtp::io, ast_rtp::ioid, LOG_ERROR, ast_rtp::rtcp, rtp_socket(), rtpread(), ast_rtcp::s, ast_rtp::s, ast_rtp::sched, ast_rtcp::us, and ast_rtp::us.

Referenced by __oh323_rtp_create(), ast_rtp_new(), gtalk_alloc(), sip_alloc(), and start_rtp().

01912 {
01913    struct ast_rtp *rtp;
01914    int x;
01915    int first;
01916    int startplace;
01917    
01918    if (!(rtp = ast_calloc(1, sizeof(*rtp))))
01919       return NULL;
01920 
01921    ast_rtp_new_init(rtp);
01922 
01923    rtp->s = rtp_socket();
01924    if (rtp->s < 0) {
01925       free(rtp);
01926       ast_log(LOG_ERROR, "Unable to allocate socket: %s\n", strerror(errno));
01927       return NULL;
01928    }
01929    if (sched && rtcpenable) {
01930       rtp->sched = sched;
01931       rtp->rtcp = ast_rtcp_new();
01932    }
01933    
01934    /* Select a random port number in the range of possible RTP */
01935    x = (ast_random() % (rtpend-rtpstart)) + rtpstart;
01936    x = x & ~1;
01937    /* Save it for future references. */
01938    startplace = x;
01939    /* Iterate tring to bind that port and incrementing it otherwise untill a port was found or no ports are available. */
01940    for (;;) {
01941       /* Must be an even port number by RTP spec */
01942       rtp->us.sin_port = htons(x);
01943       rtp->us.sin_addr = addr;
01944       /* If there's rtcp, initialize it as well. */
01945       if (rtp->rtcp) {
01946          rtp->rtcp->us.sin_port = htons(x + 1);
01947          rtp->rtcp->us.sin_addr = addr;
01948       }
01949       /* Try to bind it/them. */
01950       if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) &&
01951          (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us))))
01952          break;
01953       if (!first) {
01954          /* Primary bind succeeded! Gotta recreate it */
01955          close(rtp->s);
01956          rtp->s = rtp_socket();
01957       }
01958       if (errno != EADDRINUSE) {
01959          /* We got an error that wasn't expected, abort! */
01960          ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno));
01961          close(rtp->s);
01962          if (rtp->rtcp) {
01963             close(rtp->rtcp->s);
01964             free(rtp->rtcp);
01965          }
01966          free(rtp);
01967          return NULL;
01968       }
01969       /* The port was used, increment it (by two). */
01970       x += 2;
01971       /* Did we go over the limit ? */
01972       if (x > rtpend)
01973          /* then, start from the begingig. */
01974          x = (rtpstart + 1) & ~1;
01975       /* Check if we reached the place were we started. */
01976       if (x == startplace) {
01977          /* If so, there's no ports available. */
01978          ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n");
01979          close(rtp->s);
01980          if (rtp->rtcp) {
01981             close(rtp->rtcp->s);
01982             free(rtp->rtcp);
01983          }
01984          free(rtp);
01985          return NULL;
01986       }
01987    }
01988    rtp->sched = sched;
01989    rtp->io = io;
01990    if (callbackmode) {
01991       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
01992       ast_set_flag(rtp, FLAG_CALLBACK_MODE);
01993    }
01994    ast_rtp_pt_default(rtp);
01995    return rtp;
01996 }

int ast_rtp_proto_register ( struct ast_rtp_protocol proto  ) 

Register interface to channel driver.

Definition at line 2859 of file rtp.c.

References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), LOG_WARNING, protos, and ast_rtp_protocol::type.

Referenced by load_module().

02860 {
02861    struct ast_rtp_protocol *cur;
02862 
02863    AST_LIST_LOCK(&protos);
02864    AST_LIST_TRAVERSE(&protos, cur, list) {   
02865       if (!strcmp(cur->type, proto->type)) {
02866          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
02867          AST_LIST_UNLOCK(&protos);
02868          return -1;
02869       }
02870    }
02871    AST_LIST_INSERT_HEAD(&protos, proto, list);
02872    AST_LIST_UNLOCK(&protos);
02873    
02874    return 0;
02875 }

void ast_rtp_proto_unregister ( struct ast_rtp_protocol proto  ) 

Unregister interface to channel driver.

Definition at line 2851 of file rtp.c.

References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, and protos.

Referenced by load_module(), and unload_module().

02852 {
02853    AST_LIST_LOCK(&protos);
02854    AST_LIST_REMOVE(&protos, proto, list);
02855    AST_LIST_UNLOCK(&protos);
02856 }

void ast_rtp_pt_clear ( struct ast_rtp rtp  ) 

Setting RTP payload types from lines in a SDP description:.

Definition at line 1415 of file rtp.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.

Referenced by gtalk_alloc(), and process_sdp().

01416 {
01417    int i;
01418 
01419    if (!rtp)
01420       return;
01421 
01422    ast_mutex_lock(&rtp->bridge_lock);
01423 
01424    for (i = 0; i < MAX_RTP_PT; ++i) {
01425       rtp->current_RTP_PT[i].isAstFormat = 0;
01426       rtp->current_RTP_PT[i].code = 0;
01427    }
01428 
01429    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01430    rtp->rtp_lookup_code_cache_code = 0;
01431    rtp->rtp_lookup_code_cache_result = 0;
01432 
01433    ast_mutex_unlock(&rtp->bridge_lock);
01434 }

void ast_rtp_pt_copy ( struct ast_rtp dest,
struct ast_rtp src 
)

Copy payload types between RTP structures.

Definition at line 1455 of file rtp.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.

Referenced by ast_rtp_make_compatible(), and process_sdp().

01456 {
01457    unsigned int i;
01458 
01459    ast_mutex_lock(&dest->bridge_lock);
01460    ast_mutex_lock(&src->bridge_lock);
01461 
01462    for (i=0; i < MAX_RTP_PT; ++i) {
01463       dest->current_RTP_PT[i].isAstFormat = 
01464          src->current_RTP_PT[i].isAstFormat;
01465       dest->current_RTP_PT[i].code = 
01466          src->current_RTP_PT[i].code; 
01467    }
01468    dest->rtp_lookup_code_cache_isAstFormat = 0;
01469    dest->rtp_lookup_code_cache_code = 0;
01470    dest->rtp_lookup_code_cache_result = 0;
01471 
01472    ast_mutex_unlock(&src->bridge_lock);
01473    ast_mutex_unlock(&dest->bridge_lock);
01474 }

void ast_rtp_pt_default ( struct ast_rtp rtp  ) 

Set payload types to defaults.

Definition at line 1436 of file rtp.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, and ast_rtp::rtp_lookup_code_cache_result.

Referenced by ast_rtp_new_with_bindaddr().

01437 {
01438    int i;
01439 
01440    ast_mutex_lock(&rtp->bridge_lock);
01441 
01442    /* Initialize to default payload types */
01443    for (i = 0; i < MAX_RTP_PT; ++i) {
01444       rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
01445       rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
01446    }
01447 
01448    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01449    rtp->rtp_lookup_code_cache_code = 0;
01450    rtp->rtp_lookup_code_cache_result = 0;
01451 
01452    ast_mutex_unlock(&rtp->bridge_lock);
01453 }

struct ast_frame* ast_rtp_read ( struct ast_rtp rtp  )  [read]

Definition at line 1105 of file rtp.c.

References ast_assert, ast_codec_get_samples(), AST_CONTROL_SRCCHANGE, AST_FORMAT_MAX_AUDIO, ast_format_rate(), AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_CONTROL, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, AST_FRIENDLY_OFFSET, ast_frisolate(), ast_inet_ntoa(), AST_LIST_FIRST, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_HEAD_NOLOCK, AST_LIST_INSERT_TAIL, ast_log(), ast_null_frame, ast_rtcp_calc_interval(), ast_rtcp_write(), AST_RTP_CISCO_DTMF, AST_RTP_CN, AST_RTP_DTMF, ast_rtp_get_bridged(), ast_rtp_lookup_pt(), ast_rtp_senddigit_continuation(), ast_sched_add(), ast_set_flag, ast_verbose(), bridge_p2p_rtp_write(), ast_rtp::bridged, calc_rxstamp(), rtpPayloadType::code, ast_rtp::cycles, ast_frame::data, ast_frame::datalen, ast_frame::delivery, errno, event, ext, ast_rtp::f, f, FLAG_NAT_ACTIVE, frames, ast_frame::frametype, rtpPayloadType::isAstFormat, ast_rtp::lastevent, ast_rtp::lastividtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxseqno, ast_rtp::lastrxts, ast_frame::len, len, 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::rtcp, rtp_debug_test_addr(), RTP_SEQ_MOD, ast_rtp::rxcount, ast_rtp::rxseqno, ast_rtp::rxssrc, ast_rtp::s, ast_frame::samples, ast_rtp::sched, ast_rtcp::schedid, ast_rtp::seedrxseqno, ast_rtp::sending_digit, ast_frame::seqno, ast_frame::src, STUN_ACCEPT, stun_handle_packet(), ast_frame::subclass, ast_rtcp::them, ast_rtp::them, ast_rtp::themssrc, and ast_frame::ts.

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

01106 {
01107    int res;
01108    struct sockaddr_in sin;
01109    socklen_t len;
01110    unsigned int seqno;
01111    int version;
01112    int payloadtype;
01113    int hdrlen = 12;
01114    int padding;
01115    int mark;
01116    int ext;
01117    int cc;
01118    unsigned int ssrc;
01119    unsigned int timestamp;
01120    unsigned int *rtpheader;
01121    struct rtpPayloadType rtpPT;
01122    struct ast_rtp *bridged = NULL;
01123    AST_LIST_HEAD_NOLOCK(, ast_frame) frames;
01124    
01125    /* If time is up, kill it */
01126    if (rtp->sending_digit)
01127       ast_rtp_senddigit_continuation(rtp);
01128 
01129    len = sizeof(sin);
01130    
01131    /* Cache where the header will go */
01132    res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,
01133                0, (struct sockaddr *)&sin, &len);
01134 
01135    rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET);
01136    if (res < 0) {
01137       ast_assert(errno != EBADF);
01138       if (errno != EAGAIN) {
01139          ast_log(LOG_WARNING, "RTP Read error: %s.  Hanging up.\n", strerror(errno));
01140          return NULL;
01141       }
01142       return &ast_null_frame;
01143    }
01144    
01145    if (res < hdrlen) {
01146       ast_log(LOG_WARNING, "RTP Read too short\n");
01147       return &ast_null_frame;
01148    }
01149 
01150    /* Get fields */
01151    seqno = ntohl(rtpheader[0]);
01152 
01153    /* Check RTP version */
01154    version = (seqno & 0xC0000000) >> 30;
01155    if (!version) {
01156       if ((stun_handle_packet(rtp->s, &sin, rtp->rawdata + AST_FRIENDLY_OFFSET, res) == STUN_ACCEPT) &&
01157          (!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) {
01158          memcpy(&rtp->them, &sin, sizeof(rtp->them));
01159       }
01160       return &ast_null_frame;
01161    }
01162 
01163 #if 0 /* Allow to receive RTP stream with closed transmission path */
01164    /* If we don't have the other side's address, then ignore this */
01165    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
01166       return &ast_null_frame;
01167 #endif
01168 
01169    /* Send to whoever send to us if NAT is turned on */
01170    if (rtp->nat) {
01171       if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
01172           (rtp->them.sin_port != sin.sin_port)) {
01173          rtp->them = sin;
01174          if (rtp->rtcp) {
01175             memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
01176             rtp->rtcp->them.sin_port = htons(ntohs(rtp->them.sin_port)+1);
01177          }
01178          rtp->rxseqno = 0;
01179          ast_set_flag(rtp, FLAG_NAT_ACTIVE);
01180          if (option_debug || rtpdebug)
01181             ast_log(LOG_DEBUG, "RTP NAT: Got audio from other end. Now sending to address %s:%d\n", ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port));
01182       }
01183    }
01184 
01185    /* If we are bridged to another RTP stream, send direct */
01186    if ((bridged = ast_rtp_get_bridged(rtp)) && !bridge_p2p_rtp_write(rtp, bridged, rtpheader, res, hdrlen))
01187       return &ast_null_frame;
01188 
01189    if (version != 2)
01190       return &ast_null_frame;
01191 
01192    payloadtype = (seqno & 0x7f0000) >> 16;
01193    padding = seqno & (1 << 29);
01194    mark = seqno & (1 << 23);
01195    ext = seqno & (1 << 28);
01196    cc = (seqno & 0xF000000) >> 24;
01197    seqno &= 0xffff;
01198    timestamp = ntohl(rtpheader[1]);
01199    ssrc = ntohl(rtpheader[2]);
01200    
01201    AST_LIST_HEAD_INIT_NOLOCK(&frames);
01202    /* Force a marker bit and change SSRC if the SSRC changes */
01203    if (rtp->rxssrc && rtp->rxssrc != ssrc) {
01204       struct ast_frame *f, srcupdate;
01205       srcupdate.frametype = AST_FRAME_CONTROL;
01206       srcupdate.subclass = AST_CONTROL_SRCCHANGE;
01207       if (!mark) {
01208          if (option_debug || rtpdebug)
01209             ast_log(LOG_DEBUG, "Forcing Marker bit, because SSRC has changed\n");
01210          mark = 1;
01211       }
01212 
01213       f = ast_frisolate(&srcupdate);
01214       AST_LIST_INSERT_TAIL(&frames, f, frame_list);
01215    }
01216 
01217    rtp->rxssrc = ssrc;
01218    
01219    if (padding) {
01220       /* Remove padding bytes */
01221       res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1];
01222    }
01223    
01224    if (cc) {
01225       /* CSRC fields present */
01226       hdrlen += cc*4;
01227    }
01228 
01229    if (ext) {
01230       /* RTP Extension present */
01231       hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2;
01232       hdrlen += 4;
01233    }
01234 
01235    if (res < hdrlen) {
01236       ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen);
01237       return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame;
01238    }
01239 
01240    rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */
01241 
01242    if (rtp->rxcount==1) {
01243       /* This is the first RTP packet successfully received from source */
01244       rtp->seedrxseqno = seqno;
01245    }
01246 
01247    /* Do not schedule RR if RTCP isn't run */
01248    if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) {
01249       /* Schedule transmission of Receiver Report */
01250       rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
01251    }
01252    if ( (int)rtp->lastrxseqno - (int)seqno  > 100) /* if so it would indicate that the sender cycled; allow for misordering */
01253       rtp->cycles += RTP_SEQ_MOD;
01254 
01255    rtp->lastrxseqno = seqno;
01256    
01257    if (rtp->themssrc==0)
01258       rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */
01259    
01260    if (rtp_debug_test_addr(&sin))
01261       ast_verbose("Got  RTP packet from    %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
01262          ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen);
01263 
01264    rtpPT = ast_rtp_lookup_pt(rtp, payloadtype);
01265    if (!rtpPT.isAstFormat) {
01266       struct ast_frame *f = NULL;
01267 
01268       /* This is special in-band data that's not one of our codecs */
01269       if (rtpPT.code == AST_RTP_DTMF) {
01270          /* It's special -- rfc2833 process it */
01271          if (rtp_debug_test_addr(&sin)) {
01272             unsigned char *data;
01273             unsigned int event;
01274             unsigned int event_end;
01275             unsigned int duration;
01276             data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen;
01277             event = ntohl(*((unsigned int *)(data)));
01278             event >>= 24;
01279             event_end = ntohl(*((unsigned int *)(data)));
01280             event_end <<= 8;
01281             event_end >>= 24;
01282             duration = ntohl(*((unsigned int *)(data)));
01283             duration &= 0xFFFF;
01284             ast_verbose("Got  RTP RFC2833 from   %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u, mark %d, event %08x, end %d, duration %-5.5d) \n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp, res - hdrlen, (mark?1:0), event, ((event_end & 0x80)?1:0), duration);
01285          }
01286          f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp);
01287       } else if (rtpPT.code == AST_RTP_CISCO_DTMF) {
01288          /* It's really special -- process it the Cisco way */
01289          if (rtp->lastevent <= seqno || (rtp->lastevent >= 65530 && seqno <= 6)) {
01290             f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
01291             rtp->lastevent = seqno;
01292          }
01293       } else if (rtpPT.code == AST_RTP_CN) {
01294          /* Comfort Noise */
01295          f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
01296       } else {
01297          ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr));
01298       }
01299       if (f) {
01300          AST_LIST_INSERT_TAIL(&frames, f, frame_list);
01301          return AST_LIST_FIRST(&frames);
01302       }
01303       return &ast_null_frame;
01304    }
01305    rtp->lastrxformat = rtp->f.subclass = rtpPT.code;
01306    rtp->f.frametype = (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) ? AST_FRAME_VOICE : AST_FRAME_VIDEO;
01307 
01308    if (!rtp->lastrxts)
01309       rtp->lastrxts = timestamp;
01310 
01311    rtp->rxseqno = seqno;
01312 
01313    /* Record received timestamp as last received now */
01314    rtp->lastrxts = timestamp;
01315 
01316    rtp->f.mallocd = 0;
01317    rtp->f.datalen = res - hdrlen;
01318    rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
01319    rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
01320    rtp->f.seqno = seqno;
01321    if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) {
01322       rtp->f.samples = ast_codec_get_samples(&rtp->f);
01323       if (rtp->f.subclass == AST_FORMAT_SLINEAR) 
01324          ast_frame_byteswap_be(&rtp->f);
01325       calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
01326       /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */
01327       ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO);
01328       rtp->f.ts = timestamp / 8;
01329       rtp->f.len = rtp->f.samples / (ast_format_rate(rtp->f.subclass) / 1000);
01330    } else {
01331       /* Video -- samples is # of samples vs. 90000 */
01332       if (!rtp->lastividtimestamp)
01333          rtp->lastividtimestamp = timestamp;
01334       rtp->f.samples = timestamp - rtp->lastividtimestamp;
01335       rtp->lastividtimestamp = timestamp;
01336       rtp->f.delivery.tv_sec = 0;
01337       rtp->f.delivery.tv_usec = 0;
01338       if (mark)
01339          rtp->f.subclass |= 0x1;
01340       
01341    }
01342    rtp->f.src = "RTP";
01343    return &rtp->f;
01344 }

int ast_rtp_reload ( void   ) 

Definition at line 3777 of file rtp.c.

References ast_config_destroy(), ast_config_load(), ast_false(), ast_log(), ast_variable_retrieve(), ast_verbose(), DEFAULT_DTMF_TIMEOUT, LOG_WARNING, option_verbose, RTCP_MAX_INTERVALMS, RTCP_MIN_INTERVALMS, s, and VERBOSE_PREFIX_2.

Referenced by ast_rtp_init().

03778 {
03779    struct ast_config *cfg;
03780    const char *s;
03781 
03782    rtpstart = 5000;
03783    rtpend = 31000;
03784    dtmftimeout = DEFAULT_DTMF_TIMEOUT;
03785    cfg = ast_config_load("rtp.conf");
03786    if (cfg) {
03787       if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
03788          rtpstart = atoi(s);
03789          if (rtpstart < 1024)
03790             rtpstart = 1024;
03791          if (rtpstart > 65535)
03792             rtpstart = 65535;
03793       }
03794       if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
03795          rtpend = atoi(s);
03796          if (rtpend < 1024)
03797             rtpend = 1024;
03798          if (rtpend > 65535)
03799             rtpend = 65535;
03800       }
03801       if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
03802          rtcpinterval = atoi(s);
03803          if (rtcpinterval == 0)
03804             rtcpinterval = 0; /* Just so we're clear... it's zero */
03805          if (rtcpinterval < RTCP_MIN_INTERVALMS)
03806             rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
03807          if (rtcpinterval > RTCP_MAX_INTERVALMS)
03808             rtcpinterval = RTCP_MAX_INTERVALMS;
03809       }
03810       if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
03811 #ifdef SO_NO_CHECK
03812          if (ast_false(s))
03813             nochecksums = 1;
03814          else
03815             nochecksums = 0;
03816 #else
03817          if (ast_false(s))
03818             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
03819 #endif
03820       }
03821       if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
03822          dtmftimeout = atoi(s);
03823          if ((dtmftimeout < 0) || (dtmftimeout > 20000)) {
03824             ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
03825                dtmftimeout, DEFAULT_DTMF_TIMEOUT);
03826             dtmftimeout = DEFAULT_DTMF_TIMEOUT;
03827          };
03828       }
03829       ast_config_destroy(cfg);
03830    }
03831    if (rtpstart >= rtpend) {
03832       ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
03833       rtpstart = 5000;
03834       rtpend = 31000;
03835    }
03836    if (option_verbose > 1)
03837       ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
03838    return 0;
03839 }

void ast_rtp_reset ( struct ast_rtp rtp  ) 

Definition at line 2085 of file rtp.c.

References ast_rtp::dtmfcount, ast_rtp::dtmfmute, ast_rtp::dtmfsamples, ast_rtp::lastdigitts, ast_rtp::lastevent, 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.

02086 {
02087    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
02088    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
02089    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
02090    rtp->lastts = 0;
02091    rtp->lastdigitts = 0;
02092    rtp->lastrxts = 0;
02093    rtp->lastividtimestamp = 0;
02094    rtp->lastovidtimestamp = 0;
02095    rtp->lasteventseqn = 0;
02096    rtp->lastevent = 0;
02097    rtp->lasttxformat = 0;
02098    rtp->lastrxformat = 0;
02099    rtp->dtmfcount = 0;
02100    rtp->dtmfsamples = 0;
02101    rtp->seqno = 0;
02102    rtp->rxseqno = 0;
02103 }

int ast_rtp_sendcng ( struct ast_rtp rtp,
int  level 
)

generate comfort noice (CNG)

Definition at line 2600 of file rtp.c.

References ast_inet_ntoa(), ast_log(), AST_RTP_CN, ast_rtp_lookup_code(), ast_tvadd(), ast_verbose(), ast_rtp::data, ast_rtp::dtmfmute, errno, 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().

02601 {
02602    unsigned int *rtpheader;
02603    int hdrlen = 12;
02604    int res;
02605    int payload;
02606    char data[256];
02607    level = 127 - (level & 0x7f);
02608    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN);
02609 
02610    /* If we have no peer, return immediately */ 
02611    if (!rtp->them.sin_addr.s_addr)
02612       return 0;
02613 
02614    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
02615 
02616    /* Get a pointer to the header */
02617    rtpheader = (unsigned int *)data;
02618    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
02619    rtpheader[1] = htonl(rtp->lastts);
02620    rtpheader[2] = htonl(rtp->ssrc); 
02621    data[12] = level;
02622    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
02623       res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
02624       if (res <0) 
02625          ast_log(LOG_ERROR, "RTP Comfort Noise Transmission error to %s:%d: %s\n", ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno));
02626       if (rtp_debug_test_addr(&rtp->them))
02627          ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n"
02628                , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen);         
02629          
02630    }
02631    return 0;
02632 }

int ast_rtp_senddigit_begin ( struct ast_rtp rtp,
char  digit 
)

Send begin frames for DTMF.

Definition at line 2208 of file rtp.c.

References ast_inet_ntoa(), ast_log(), AST_RTP_DTMF, ast_rtp_lookup_code(), ast_tvadd(), ast_verbose(), ast_rtp::dtmfmute, errno, ast_rtp::lastdigitts, LOG_ERROR, LOG_WARNING, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::send_digit, ast_rtp::send_duration, ast_rtp::send_payload, ast_rtp::sending_digit, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.

Referenced by mgcp_senddigit_begin(), oh323_digit_begin(), and sip_senddigit_begin().

02209 {
02210    unsigned int *rtpheader;
02211    int hdrlen = 12, res = 0, i = 0, payload = 0;
02212    char data[256];
02213 
02214    if ((digit <= '9') && (digit >= '0'))
02215       digit -= '0';
02216    else if (digit == '*')
02217       digit = 10;
02218    else if (digit == '#')
02219       digit = 11;
02220    else if ((digit >= 'A') && (digit <= 'D'))
02221       digit = digit - 'A' + 12;
02222    else if ((digit >= 'a') && (digit <= 'd'))
02223       digit = digit - 'a' + 12;
02224    else {
02225       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
02226       return 0;
02227    }
02228 
02229    /* If we have no peer, return immediately */ 
02230    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
02231       return 0;
02232 
02233    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF);
02234 
02235    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
02236    rtp->send_duration = 160;
02237    
02238    /* Get a pointer to the header */
02239    rtpheader = (unsigned int *)data;
02240    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
02241    rtpheader[1] = htonl(rtp->lastdigitts);
02242    rtpheader[2] = htonl(rtp->ssrc); 
02243 
02244    for (i = 0; i < 2; i++) {
02245       rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
02246       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
02247       if (res < 0) 
02248          ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n",
02249             ast_inet_ntoa(rtp->them.sin_addr),
02250             ntohs(rtp->them.sin_port), strerror(errno));
02251       if (rtp_debug_test_addr(&rtp->them))
02252          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02253                 ast_inet_ntoa(rtp->them.sin_addr),
02254                 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
02255       /* Increment sequence number */
02256       rtp->seqno++;
02257       /* Increment duration */
02258       rtp->send_duration += 160;
02259       /* Clear marker bit and set seqno */
02260       rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
02261    }
02262 
02263    /* Since we received a begin, we can safely store the digit and disable any compensation */
02264    rtp->sending_digit = 1;
02265    rtp->send_digit = digit;
02266    rtp->send_payload = payload;
02267 
02268    return 0;
02269 }

int ast_rtp_senddigit_end ( struct ast_rtp rtp,
char  digit 
)

void ast_rtp_set_callback ( struct ast_rtp rtp,
ast_rtp_callback  callback 
)

Definition at line 586 of file rtp.c.

References ast_rtp::callback.

Referenced by start_rtp().

00587 {
00588    rtp->callback = callback;
00589 }

void ast_rtp_set_data ( struct ast_rtp rtp,
void *  data 
)

Definition at line 581 of file rtp.c.

References ast_rtp::data.

Referenced by start_rtp().

00582 {
00583    rtp->data = data;
00584 }

void ast_rtp_set_m_type ( struct ast_rtp rtp,
int  pt 
)

Activate payload type.

Definition at line 1654 of file rtp.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, ast_rtp::current_RTP_PT, and MAX_RTP_PT.

Referenced by gtalk_is_answered(), gtalk_newcall(), and process_sdp().

01655 {
01656    if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 
01657       return; /* bogus payload type */
01658 
01659    ast_mutex_lock(&rtp->bridge_lock);
01660    rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
01661    ast_mutex_unlock(&rtp->bridge_lock);
01662 } 

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

Definition at line 2031 of file rtp.c.

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

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

02032 {
02033    rtp->them.sin_port = them->sin_port;
02034    rtp->them.sin_addr = them->sin_addr;
02035    if (rtp->rtcp) {
02036       rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1);
02037       rtp->rtcp->them.sin_addr = them->sin_addr;
02038    }
02039    rtp->rxseqno = 0;
02040 }

void ast_rtp_set_rtpholdtimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp hold timeout.

Definition at line 548 of file rtp.c.

References ast_rtp::rtpholdtimeout.

Referenced by create_addr_from_peer(), do_monitor(), and sip_alloc().

00549 {
00550    rtp->rtpholdtimeout = timeout;
00551 }

void ast_rtp_set_rtpkeepalive ( struct ast_rtp rtp,
int  period 
)

set RTP keepalive interval

Definition at line 554 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by create_addr_from_peer(), and sip_alloc().

00555 {
00556    rtp->rtpkeepalive = period;
00557 }

int ast_rtp_set_rtpmap_type ( struct ast_rtp rtp,
int  pt,
char *  mimeType,
char *  mimeSubtype,
enum ast_rtp_options  options 
)

Initiate payload type to a known MIME media type for a codec.

Initiate payload type to a known MIME media type for a codec.

Returns:
0 if the MIME type was found and set, -1 if it wasn't found

Definition at line 1681 of file rtp.c.

References AST_FORMAT_G726, AST_FORMAT_G726_AAL2, ast_mutex_lock(), ast_mutex_unlock(), AST_RTP_OPT_G726_NONSTANDARD, ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, MAX_RTP_PT, mimeTypes, payloadType, subtype, and type.

Referenced by __oh323_rtp_create(), gtalk_is_answered(), gtalk_newcall(), process_sdp(), and set_dtmf_payload().

01684 {
01685    unsigned int i;
01686    int found = 0;
01687 
01688    if (pt < 0 || pt > MAX_RTP_PT) 
01689       return -1; /* bogus payload type */
01690    
01691    ast_mutex_lock(&rtp->bridge_lock);
01692 
01693    for (i = 0; i < sizeof(mimeTypes)/sizeof(mimeTypes[0]); ++i) {
01694       if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
01695           strcasecmp(mimeType, mimeTypes[i].type) == 0) {
01696          found = 1;
01697          rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
01698          if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) &&
01699              mimeTypes[i].payloadType.isAstFormat &&
01700              (options & AST_RTP_OPT_G726_NONSTANDARD))
01701             rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2;
01702          break;
01703       }
01704    }
01705 
01706    ast_mutex_unlock(&rtp->bridge_lock);
01707 
01708    return (found ? 0 : -1);
01709 } 

void ast_rtp_set_rtptimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp timeout.

Definition at line 542 of file rtp.c.

References ast_rtp::rtptimeout.

Referenced by create_addr_from_peer(), do_monitor(), and sip_alloc().

00543 {
00544    rtp->rtptimeout = timeout;
00545 }

void ast_rtp_set_rtptimers_onhold ( struct ast_rtp rtp  ) 

Definition at line 535 of file rtp.c.

References ast_rtp::rtpholdtimeout, and ast_rtp::rtptimeout.

Referenced by handle_response_invite().

00536 {
00537    rtp->rtptimeout = (-1) * rtp->rtptimeout;
00538    rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout;
00539 }

void ast_rtp_setdtmf ( struct ast_rtp rtp,
int  dtmf 
)

Indicate whether this RTP session is carrying DTMF or not.

Definition at line 601 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_DTMF.

Referenced by create_addr_from_peer(), handle_request_invite(), process_sdp(), sip_alloc(), and sip_dtmfmode().

00602 {
00603    ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF);
00604 }

void ast_rtp_setdtmfcompensate ( struct ast_rtp rtp,
int  compensate 
)

Compensate for devices that send RFC2833 packets all at once.

Definition at line 606 of file rtp.c.

References ast_set2_flag, and FLAG_DTMF_COMPENSATE.

Referenced by create_addr_from_peer(), handle_request_invite(), process_sdp(), and sip_alloc().

00607 {
00608    ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE);
00609 }

void ast_rtp_setnat ( struct ast_rtp rtp,
int  nat 
)

Definition at line 591 of file rtp.c.

References ast_rtp::nat.

Referenced by __oh323_rtp_create(), do_setnat(), oh323_rtp_read(), and start_rtp().

00592 {
00593    rtp->nat = nat;
00594 }

void ast_rtp_setstun ( struct ast_rtp rtp,
int  stun_enable 
)

Enable STUN capability.

Definition at line 611 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_STUN.

Referenced by gtalk_new().

00612 {
00613    ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN);
00614 }

int ast_rtp_settos ( struct ast_rtp rtp,
int  tos 
)

Definition at line 2006 of file rtp.c.

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

Referenced by __oh323_rtp_create(), and sip_alloc().

02007 {
02008    int res;
02009 
02010    if ((res = setsockopt(rtp->s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))) 
02011       ast_log(LOG_WARNING, "Unable to set TOS to %d\n", tos);
02012    return res;
02013 }

void ast_rtp_stop ( struct ast_rtp rtp  ) 

Definition at line 2071 of file rtp.c.

References ast_clear_flag, AST_SCHED_DEL, FLAG_P2P_SENT_MARK, ast_rtp::rtcp, ast_rtp::sched, ast_rtcp::schedid, ast_rtcp::them, and ast_rtp::them.

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

02072 {
02073    AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02074 
02075    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
02076    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
02077    if (rtp->rtcp) {
02078       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
02079       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
02080    }
02081    
02082    ast_clear_flag(rtp, FLAG_P2P_SENT_MARK);
02083 }

void ast_rtp_stun_request ( struct ast_rtp rtp,
struct sockaddr_in *  suggestion,
const char *  username 
)

Definition at line 403 of file rtp.c.

References append_attr_string(), stun_attr::attr, stun_header::ies, stun_header::msglen, stun_header::msgtype, ast_rtp::s, STUN_BINDREQ, stun_req_id(), stun_send(), and STUN_USERNAME.

Referenced by gtalk_update_stun().

00404 {
00405    struct stun_header *req;
00406    unsigned char reqdata[1024];
00407    int reqlen, reqleft;
00408    struct stun_attr *attr;
00409 
00410    req = (struct stun_header *)reqdata;
00411    stun_req_id(req);
00412    reqlen = 0;
00413    reqleft = sizeof(reqdata) - sizeof(struct stun_header);
00414    req->msgtype = 0;
00415    req->msglen = 0;
00416    attr = (struct stun_attr *)req->ies;
00417    if (username)
00418       append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft);
00419    req->msglen = htons(reqlen);
00420    req->msgtype = htons(STUN_BINDREQ);
00421    stun_send(rtp->s, suggestion, req);
00422 }

void ast_rtp_unset_m_type ( struct ast_rtp rtp,
int  pt 
)

clear payload type

Definition at line 1666 of file rtp.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp::bridge_lock, rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, and MAX_RTP_PT.

Referenced by process_sdp().

01667 {
01668    if (pt < 0 || pt > MAX_RTP_PT)
01669       return; /* bogus payload type */
01670 
01671    ast_mutex_lock(&rtp->bridge_lock);
01672    rtp->current_RTP_PT[pt].isAstFormat = 0;
01673    rtp->current_RTP_PT[pt].code = 0;
01674    ast_mutex_unlock(&rtp->bridge_lock);
01675 }

void ast_rtp_update_source ( struct ast_rtp rtp  ) 

Definition at line 2015 of file rtp.c.

References ast_rtp::set_marker_bit.

Referenced by mgcp_indicate(), oh323_indicate(), sip_indicate(), sip_write(), and skinny_indicate().

02016 {
02017    rtp->set_marker_bit = 1;
02018    return;
02019 }

int ast_rtp_write ( struct ast_rtp rtp,
struct ast_frame f 
)

Definition at line 2759 of file rtp.c.

References ast_codec_pref_getsize(), AST_FORMAT_G722, AST_FORMAT_G723_1, AST_FORMAT_SPEEX, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frdup(), ast_frfree, ast_getformatname(), ast_log(), ast_rtp_lookup_code(), ast_rtp_raw_write(), ast_smoother_feed, ast_smoother_feed_be, AST_SMOOTHER_FLAG_BE, ast_smoother_free(), ast_smoother_new(), ast_smoother_read(), ast_smoother_set_flags(), ast_smoother_test_flag(), ast_format_list::cur_ms, ast_frame::data, ast_frame::datalen, f, ast_format_list::flags, ast_format_list::fr_len, ast_frame::frametype, ast_format_list::inc_ms, ast_rtp::lasttxformat, LOG_DEBUG, LOG_WARNING, ast_frame::offset, option_debug, ast_rtp::pref, ast_frame::samples, ast_rtp::smoother, ast_frame::subclass, and ast_rtp::them.

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

02760 {
02761    struct ast_frame *f;
02762    int codec;
02763    int hdrlen = 12;
02764    int subclass;
02765    
02766 
02767    /* If we have no peer, return immediately */ 
02768    if (!rtp->them.sin_addr.s_addr)
02769       return 0;
02770 
02771    /* If there is no data length, return immediately */
02772    if (!_f->datalen) 
02773       return 0;
02774    
02775    /* Make sure we have enough space for RTP header */
02776    if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) {
02777       ast_log(LOG_WARNING, "RTP can only send voice and video\n");
02778       return -1;
02779    }
02780 
02781    subclass = _f->subclass;
02782    if (_f->frametype == AST_FRAME_VIDEO)
02783       subclass &= ~0x1;
02784 
02785    codec = ast_rtp_lookup_code(rtp, 1, subclass);
02786    if (codec < 0) {
02787       ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass));
02788       return -1;
02789    }
02790 
02791    if (rtp->lasttxformat != subclass) {
02792       /* New format, reset the smoother */
02793       if (option_debug)
02794          ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
02795       rtp->lasttxformat = subclass;
02796       if (rtp->smoother)
02797          ast_smoother_free(rtp->smoother);
02798       rtp->smoother = NULL;
02799    }
02800 
02801    if (!rtp->smoother && subclass != AST_FORMAT_SPEEX && subclass != AST_FORMAT_G723_1) {
02802       struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass);
02803       if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */
02804          if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
02805             ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
02806             return -1;
02807          }
02808          if (fmt.flags)
02809             ast_smoother_set_flags(rtp->smoother, fmt.flags);
02810          if (option_debug)
02811             ast_log(LOG_DEBUG, "Created smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
02812       }
02813    }
02814    if (rtp->smoother) {
02815       if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) {
02816          ast_smoother_feed_be(rtp->smoother, _f);
02817       } else {
02818          ast_smoother_feed(rtp->smoother, _f);
02819       }
02820 
02821       while ((f = ast_smoother_read(rtp->smoother)) && (f->data)) {
02822          if (f->subclass == AST_FORMAT_G722) {
02823             /* G.722 is silllllllllllllly */
02824             f->samples /= 2;
02825          }
02826 
02827          ast_rtp_raw_write(rtp, f, codec);
02828       }
02829    } else {
02830       /* Don't buffer outgoing frames; send them one-per-packet: */
02831       if (_f->offset < hdrlen) {
02832          f = ast_frdup(_f);
02833       } else {
02834          f = _f;
02835       }
02836       if (f->data) {
02837          if (f->subclass == AST_FORMAT_G722) {
02838             /* G.722 is silllllllllllllly */
02839             f->samples /= 2;
02840          }
02841          ast_rtp_raw_write(rtp, f, codec);
02842       }
02843       if (f != _f)
02844          ast_frfree(f);
02845    }
02846       
02847    return 0;
02848 }


Generated on Sun Jun 12 16:38:01 2011 for Asterisk - the Open Source PBX by  doxygen 1.5.6