Codename Pineapple

Home page | Mailing list | Docs

Last updated: Sat Feb 3 05:01:47 2007

Asterisk developer's documentation :: Codename Pineapple


rtp.h File Reference


Detailed Description

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

RTP is defined in RFC 3550.

Definition in file rtp.h.

#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
 This is the structure that binds a channel (SIP/Jingle/H.323) to the RTP subsystem. More...

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)
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)
 The RTP bridge.
int ast_rtp_codec_getformat (int pt)
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 *c0, struct ast_channel *c1)
 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)
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)
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)
 Return RTCP quality string.
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):.
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)
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.
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 an RTP channel client.
void ast_rtp_proto_unregister (struct ast_rtp_protocol *proto)
 Unregister an RTP channel client.
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.
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)
 Make a note of a RTP payload type that was seen in a SDP "m=" line. By default, use the well-known value for this type (although it may still be set to a different value by a subsequent "a=rtpmap:" line).
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
void ast_rtp_set_rtpmap_type (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype, enum ast_rtp_options options)
 Make a note of a RTP payload type (with MIME type) that was seen in an SDP "a=rtpmap:" line.
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)
 Send STUN request (??).
int ast_rtp_write (struct ast_rtp *rtp, struct ast_frame *f)


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)
 

DTMF (RFC2833)

Definition at line 43 of file rtp.h.

Referenced by add_noncodec_to_sdp(), ast_rtp_read(), ast_rtp_senddigit_begin(), bridge_p2p_rtp_write(), check_peer_ok(), check_user_full(), check_user_ok(), create_addr(), create_addr_from_peer(), oh323_alloc(), oh323_request(), and sip_alloc().

#define AST_RTP_MAX   AST_RTP_CISCO_DTMF
 

Maximum RTP-specific code

Definition at line 49 of file rtp.h.

Referenced by ast_rtp_lookup_mime_multiple().

#define FLAG_3389_WARNING   (1 << 0)
 

Definition at line 54 of file rtp.h.

#define MAX_RTP_PT   256
 

Maxmum number of payload defintions for a RTP session

Definition at line 52 of file rtp.h.

Referenced by ast_rtp_codec_getformat(), ast_rtp_get_current_formats(), ast_rtp_pt_clear(), ast_rtp_pt_copy(), ast_rtp_pt_default(), ast_rtp_set_m_type(), and ast_rtp_set_rtpmap_type().


Typedef Documentation

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

RTP callback structure

Definition at line 87 of file rtp.h.


Enumeration Type Documentation

enum ast_rtp_get_result
 

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 60 of file rtp.h.

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

enum ast_rtp_options
 

Enumerator:
AST_RTP_OPT_G726_NONSTANDARD 

Definition at line 56 of file rtp.h.

00056                      {
00057    AST_RTP_OPT_G726_NONSTANDARD = (1 << 0),
00058 };


Function Documentation

int ast_rtcp_fd struct ast_rtp rtp  ) 
 

Definition at line 519 of file rtp.c.

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

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

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

struct ast_frame* ast_rtcp_read struct ast_rtp rtp  ) 
 

Definition at line 888 of file rtp.c.

References ast_rtcp::accumulated_transit, AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_verbose(), CRASH, ast_frame::datalen, ast_rtp::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().

00889 {
00890    socklen_t len;
00891    int position, i, packetwords;
00892    int res;
00893    struct sockaddr_in sin;
00894    unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET];
00895    unsigned int *rtcpheader;
00896    int pt;
00897    struct timeval now;
00898    unsigned int length;
00899    int rc;
00900    double rtt = 0;
00901    double a;
00902    double dlsr;
00903    double lsr;
00904    unsigned int msw;
00905    unsigned int lsw;
00906    unsigned int comp;
00907    struct ast_frame *f = &ast_null_frame;
00908    
00909    if (!rtp || !rtp->rtcp)
00910       return &ast_null_frame;
00911 
00912    len = sizeof(sin);
00913    
00914    res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET,
00915                0, (struct sockaddr *)&sin, &len);
00916    rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET);
00917    
00918    if (res < 0) {
00919       if (errno != EAGAIN)
00920          ast_log(LOG_WARNING, "RTCP Read error: %s\n", strerror(errno));
00921       if (errno == EBADF)
00922          CRASH;
00923       return &ast_null_frame;
00924    }
00925 
00926    packetwords = res / 4;
00927    
00928    if (rtp->nat) {
00929       /* Send to whoever sent to us */
00930       if ((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
00931           (rtp->rtcp->them.sin_port != sin.sin_port)) {
00932          memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
00933          if (option_debug || rtpdebug)
00934             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));
00935       }
00936    }
00937 
00938    if (option_debug)
00939       ast_log(LOG_DEBUG, "Got RTCP report of %d bytes\n", res);
00940 
00941    /* Process a compound packet */
00942    position = 0;
00943    while (position < packetwords) {
00944       i = position;
00945       length = ntohl(rtcpheader[i]);
00946       pt = (length & 0xff0000) >> 16;
00947       rc = (length & 0x1f000000) >> 24;
00948       length &= 0xffff;
00949     
00950       if ((i + length) > packetwords) {
00951          ast_log(LOG_WARNING, "RTCP Read too short\n");
00952          return &ast_null_frame;
00953       }
00954       
00955       if (rtcp_debug_test_addr(&sin)) {
00956          ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
00957          ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown");
00958          ast_verbose("Reception reports: %d\n", rc);
00959          ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]);
00960       }
00961     
00962       i += 2; /* Advance past header and ssrc */
00963       
00964       switch (pt) {
00965       case RTCP_PT_SR:
00966          gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */
00967          rtp->rtcp->spc = ntohl(rtcpheader[i+3]);
00968          rtp->rtcp->soc = ntohl(rtcpheader[i + 4]);
00969          rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff) >> 16); /* Going to LSR in RR*/
00970     
00971          if (rtcp_debug_test_addr(&sin)) {
00972             ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096);
00973             ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2]));
00974             ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4]));
00975          }
00976          i += 5;
00977          if (rc < 1)
00978             break;
00979          /* Intentional fall through */
00980       case RTCP_PT_RR:
00981          /* This is the place to calculate RTT */
00982          /* Don't handle multiple reception reports (rc > 1) yet */
00983          gettimeofday(&now, NULL);
00984          timeval2ntp(now, &msw, &lsw);
00985          /* Use the one we sent them in our SR instead, rtcp->txlsr could have been rewritten if the dlsr is large */
00986          if (ntohl(rtcpheader[i + 4])) { /* We must have the LSR */
00987             comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16);
00988             a = (double)((comp & 0xffff0000) >> 16) + (double)((double)(comp & 0xffff)/1000000.);
00989             lsr = (double)((ntohl(rtcpheader[i + 4]) & 0xffff0000) >> 16) + (double)((double)(ntohl(rtcpheader[i + 4]) & 0xffff) / 1000000.);
00990             dlsr = (double)(ntohl(rtcpheader[i + 5])/65536.);
00991             rtt = a - dlsr - lsr;
00992             rtp->rtcp->accumulated_transit += rtt;
00993             rtp->rtcp->rtt = rtt;
00994             if (rtp->rtcp->maxrtt<rtt)
00995                rtp->rtcp->maxrtt = rtt;
00996             if (rtp->rtcp->minrtt>rtt)
00997             rtp->rtcp->minrtt = rtt;
00998          }
00999          rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]);
01000          rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff;
01001          if (rtcp_debug_test_addr(&sin)) {
01002             ast_verbose("Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24));
01003             ast_verbose("Packets lost so far: %d\n", rtp->rtcp->reported_lost);
01004             ast_verbose("Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff));
01005             ast_verbose("Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16);
01006             ast_verbose("Interarrival jitter: %u\n", rtp->rtcp->reported_jitter);
01007             ast_verbose("Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096);
01008             ast_verbose("DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0);
01009             if (rtt)
01010                ast_verbose("RTT: %f(sec)\n", rtt);
01011          }
01012          break;
01013       case RTCP_PT_FUR:
01014          if (rtcp_debug_test_addr(&sin))
01015             ast_verbose("Received an RTCP Fast Update Request\n");
01016          rtp->f.frametype = AST_FRAME_CONTROL;
01017          rtp->f.subclass = AST_CONTROL_VIDUPDATE;
01018          rtp->f.datalen = 0;
01019          rtp->f.samples = 0;
01020          rtp->f.mallocd = 0;
01021          rtp->f.src = "RTP";
01022          f = &rtp->f;
01023          break;
01024       case RTCP_PT_SDES:
01025          if (rtcp_debug_test_addr(&sin))
01026             ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
01027          break;
01028       case RTCP_PT_BYE:
01029          if (rtcp_debug_test_addr(&sin))
01030             ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
01031          break;
01032       default:
01033          if (option_debug)
01034             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));
01035          break;
01036       }
01037       position += (length + 1);
01038    }
01039          
01040    return f;
01041 }

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

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

02330 {
02331    struct ast_rtp *rtp = data;
02332    int res;
02333 
02334    rtp->rtcp->sendfur = 1;
02335    res = ast_rtcp_write(data);
02336    
02337    return res;
02338 }

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

Referenced by process_sdp().

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

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

The RTP bridge.

Definition at line 3259 of file rtp.c.

References AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, ast_channel_lock, ast_channel_trylock, ast_channel_unlock, 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(), 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, option_debug, option_verbose, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel_tech::send_digit_begin, ast_channel::tech, ast_channel::tech_pvt, and VERBOSE_PREFIX_3.

03260 {
03261    struct ast_rtp *p0 = NULL, *p1 = NULL;    /* Audio RTP Channels */
03262    struct ast_rtp *vp0 = NULL, *vp1 = NULL;  /* Video RTP channels */
03263    struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL;
03264    enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED;
03265    enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED;
03266    enum ast_bridge_result res = AST_BRIDGE_FAILED;
03267    int codec0 = 0, codec1 = 0;
03268    void *pvt0 = NULL, *pvt1 = NULL;
03269 
03270    /* Lock channels */
03271    ast_channel_lock(c0);
03272    while (ast_channel_trylock(c1)) {
03273       ast_channel_unlock(c0);
03274       usleep(1);
03275       ast_channel_lock(c0);
03276    }
03277 
03278    /* Find channel driver interfaces */
03279    if (!(pr0 = get_proto(c0))) {
03280       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
03281       ast_channel_unlock(c0);
03282       ast_channel_unlock(c1);
03283       return AST_BRIDGE_FAILED;
03284    }
03285    if (!(pr1 = get_proto(c1))) {
03286       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
03287       ast_channel_unlock(c0);
03288       ast_channel_unlock(c1);
03289       return AST_BRIDGE_FAILED;
03290    }
03291 
03292    /* Get channel specific interface structures */
03293    pvt0 = c0->tech_pvt;
03294    pvt1 = c1->tech_pvt;
03295 
03296    /* Get audio and video interface (if native bridge is possible) */
03297    audio_p0_res = pr0->get_rtp_info(c0, &p0);
03298    video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
03299    audio_p1_res = pr1->get_rtp_info(c1, &p1);
03300    video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
03301 
03302    /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */
03303    if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE))
03304       audio_p0_res = AST_RTP_GET_FAILED;
03305    if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE))
03306       audio_p1_res = AST_RTP_GET_FAILED;
03307 
03308    /* Check if a bridge is possible (partial/native) */
03309    if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) {
03310       /* Somebody doesn't want to play... */
03311       ast_channel_unlock(c0);
03312       ast_channel_unlock(c1);
03313       return AST_BRIDGE_FAILED_NOWARN;
03314    }
03315 
03316    /* If we need to feed DTMF frames into the core then only do a partial native bridge */
03317    if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
03318       ast_set_flag(p0, FLAG_P2P_NEED_DTMF);
03319       audio_p0_res = AST_RTP_TRY_PARTIAL;
03320    }
03321 
03322    if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) {
03323       ast_set_flag(p1, FLAG_P2P_NEED_DTMF);
03324       audio_p1_res = AST_RTP_TRY_PARTIAL;
03325    }
03326 
03327    /* If both sides are not using the same method of DTMF transmission 
03328     * (ie: one is RFC2833, other is INFO... then we can not do direct media. 
03329     * --------------------------------------------------
03330     * | DTMF Mode |  HAS_DTMF  |  Accepts Begin Frames |
03331     * |-----------|------------|-----------------------|
03332     * | Inband    | False      | True                  |
03333     * | RFC2833   | True       | True                  |
03334     * | SIP INFO  | False      | False                 |
03335     * --------------------------------------------------
03336     * However, if DTMF from both channels is being monitored by the core, then
03337     * we can still do packet-to-packet bridging, because passing through the 
03338     * core will handle DTMF mode translation.
03339     */
03340    if ( (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) ||
03341        (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) {
03342       if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) {
03343          ast_channel_unlock(c0);
03344          ast_channel_unlock(c1);
03345          return AST_BRIDGE_FAILED_NOWARN;
03346       }
03347       audio_p0_res = AST_RTP_TRY_PARTIAL;
03348       audio_p1_res = AST_RTP_TRY_PARTIAL;
03349    }
03350 
03351    /* Get codecs from both sides */
03352    codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0;
03353    codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0;
03354    if (codec0 && codec1 && !(codec0 & codec1)) {
03355       /* Hey, we can't do native bridging if both parties speak different codecs */
03356       if (option_debug > 2)
03357          ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1);
03358       ast_channel_unlock(c0);
03359       ast_channel_unlock(c1);
03360       return AST_BRIDGE_FAILED_NOWARN;
03361    }
03362 
03363    /* If either side can only do a partial bridge, then don't try for a true native bridge */
03364    if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) {
03365       /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */
03366       if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) {
03367          if (option_debug)
03368             ast_log(LOG_DEBUG, "Cannot packet2packet bridge - raw formats are incompatible\n");
03369          ast_channel_unlock(c0);
03370          ast_channel_unlock(c1);
03371          return AST_BRIDGE_FAILED_NOWARN;
03372       }
03373       if (option_verbose > 2)
03374          ast_verbose(VERBOSE_PREFIX_3 "Packet2Packet bridging %s and %s\n", c0->name, c1->name);
03375       res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1);
03376    } else {
03377       if (option_verbose > 2) 
03378          ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
03379       res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1);
03380    }
03381 
03382    return res;
03383 }

int ast_rtp_codec_getformat int  pt  ) 
 

get format from predefined dynamic payload format

Definition at line 2711 of file rtp.c.

References rtpPayloadType::code, MAX_RTP_PT, and static_RTP_PT.

02712 {
02713    if (pt < 0 || pt > MAX_RTP_PT)
02714       return 0; /* bogus payload type */
02715 
02716    if (static_RTP_PT[pt].isAstFormat)
02717       return static_RTP_PT[pt].code;
02718    else
02719       return 0;
02720 }

struct ast_codec_pref* ast_rtp_codec_getpref struct ast_rtp rtp  ) 
 

Get codec preference

Definition at line 2706 of file rtp.c.

References ast_rtp::pref.

Referenced by add_codec_to_sdp().

02707 {
02708    return &rtp->pref;
02709 }

int ast_rtp_codec_setpref struct ast_rtp rtp,
struct ast_codec_pref prefs
 

Set codec preference

Definition at line 2693 of file rtp.c.

References ast_codec_pref::framing, ast_codec_pref::order, ast_rtp::pref, and prefs.

Referenced by __oh323_rtp_create(), check_peer_ok(), check_user_full(), check_user_ok(), create_addr_from_peer(), register_verify(), set_peer_capabilities(), start_rtp(), transmit_response_with_attachment(), and transmit_response_with_sdp().

02694 {
02695    int x;
02696    for (x = 0; x < 32; x++) {  /* Ugly way */
02697       rtp->pref.order[x] = prefs->order[x];
02698       rtp->pref.framing[x] = prefs->framing[x];
02699    }
02700    if (rtp->smoother)
02701       ast_smoother_free(rtp->smoother);
02702    rtp->smoother = NULL;
02703    return 0;
02704 }

void ast_rtp_destroy struct ast_rtp rtp  ) 
 

Destroy RTP session

Definition at line 2111 of file rtp.c.

References ast_io_remove(), ast_mutex_destroy(), ast_sched_del(), ast_smoother_free(), ast_verbose(), 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(), rtcpstats, 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_peer_ok(), check_user_full(), check_user_ok(), cleanup_connection(), create_addr_from_peer(), gtalk_free_pvt(), jingle_free_pvt(), mgcp_hangup(), oh323_alloc(), skinny_hangup(), start_rtp(), and unalloc_sub().

02112 {
02113    if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) {
02114       /*Print some info on the call here */
02115       ast_verbose("  RTP-stats\n");
02116       ast_verbose("* Our Receiver:\n");
02117       ast_verbose("  SSRC:     %u\n", rtp->themssrc);
02118       ast_verbose("  Received packets: %u\n", rtp->rxcount);
02119       ast_verbose("  Lost packets:   %u\n", rtp->rtcp->expected_prior - rtp->rtcp->received_prior);
02120       ast_verbose("  Jitter:      %.4f\n", rtp->rxjitter);
02121       ast_verbose("  Transit:     %.4f\n", rtp->rxtransit);
02122       ast_verbose("  RR-count:    %u\n", rtp->rtcp->rr_count);
02123       ast_verbose("* Our Sender:\n");
02124       ast_verbose("  SSRC:     %u\n", rtp->ssrc);
02125       ast_verbose("  Sent packets:   %u\n", rtp->txcount);
02126       ast_verbose("  Lost packets:   %u\n", rtp->rtcp->reported_lost);
02127       ast_verbose("  Jitter:      %u\n", rtp->rtcp->reported_jitter);
02128       ast_verbose("  SR-count:    %u\n", rtp->rtcp->sr_count);
02129       ast_verbose("  RTT:      %f\n", rtp->rtcp->rtt);
02130    }
02131 
02132    if (rtp->smoother)
02133       ast_smoother_free(rtp->smoother);
02134    if (rtp->ioid)
02135       ast_io_remove(rtp->io, rtp->ioid);
02136    if (rtp->s > -1)
02137       close(rtp->s);
02138    if (rtp->rtcp) {
02139       if (rtp->rtcp->schedid > 0)
02140          ast_sched_del(rtp->sched, rtp->rtcp->schedid);
02141       close(rtp->rtcp->s);
02142       free(rtp->rtcp);
02143       rtp->rtcp=NULL;
02144    }
02145 #ifdef P2P_INTENSE
02146    ast_mutex_destroy(&rtp->bridge_lock);
02147 #endif
02148    free(rtp);
02149 }

int ast_rtp_early_bridge struct ast_channel c0,
struct ast_channel c1
 

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

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

01523 {
01524    // dest = c0, src = c1
01525    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
01526    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
01527    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
01528    enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED;
01529    enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED;
01530    int srccodec, nat_active = 0;
01531 
01532    /* Lock channels */
01533    ast_channel_lock(c0);
01534    if (c1) {
01535       while (ast_channel_trylock(c1)) {
01536          ast_channel_unlock(c0);
01537          usleep(1);
01538          ast_channel_lock(c0);
01539       }
01540    }
01541 
01542    /* Find channel driver interfaces */
01543    destpr = get_proto(c0);
01544    if (c1)
01545       srcpr = get_proto(c1);
01546    if (!destpr) {
01547       if (option_debug)
01548          ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", c0->name);
01549       ast_channel_unlock(c0);
01550       if (c1)
01551          ast_channel_unlock(c1);
01552       return -1;
01553    }
01554    if (!srcpr) {
01555       if (option_debug)
01556          ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", c1 ? c1->name : "<unspecified>");
01557       ast_channel_unlock(c0);
01558       if (c1)
01559          ast_channel_unlock(c1);
01560       return -1;
01561    }
01562 
01563    /* Get audio and video interface (if native bridge is possible) */
01564    audio_dest_res = destpr->get_rtp_info(c0, &destp);
01565    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(c0, &vdestp) : AST_RTP_GET_FAILED;
01566    if (srcpr) {
01567       audio_src_res = srcpr->get_rtp_info(c1, &srcp);
01568       video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(c1, &vsrcp) : AST_RTP_GET_FAILED;
01569    }
01570 
01571    /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
01572    if (audio_dest_res != AST_RTP_TRY_NATIVE) {
01573       /* Somebody doesn't want to play... */
01574       ast_channel_unlock(c0);
01575       if (c1)
01576          ast_channel_unlock(c1);
01577       return -1;
01578    }
01579    if (audio_src_res == AST_RTP_TRY_NATIVE && srcpr->get_codec)
01580       srccodec = srcpr->get_codec(c1);
01581    else
01582       srccodec = 0;
01583    /* Consider empty media as non-existant */
01584    if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr)
01585       srcp = NULL;
01586    if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
01587       nat_active = 1;
01588    /* Bridge media early */
01589    if (destpr->set_rtp_peer(c0, srcp, vsrcp, srccodec, nat_active))
01590       ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
01591    ast_channel_unlock(c0);
01592    if (c1)
01593       ast_channel_unlock(c1);
01594    if (option_debug)
01595       ast_log(LOG_DEBUG, "Setting early bridge SDP of '%s' with that of '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
01596    return 0;
01597 }

int ast_rtp_fd struct ast_rtp rtp  ) 
 

Definition at line 514 of file rtp.c.

References ast_rtp::s.

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

00515 {
00516    return rtp->s;
00517 }

struct ast_rtp* ast_rtp_get_bridged struct ast_rtp rtp  ) 
 

Definition at line 2045 of file rtp.c.

References ast_rtp::bridged, rtp_bridge_lock(), and rtp_bridge_unlock().

Referenced by ast_rtp_read(), and check_rtp_timeout().

02046 {
02047    struct ast_rtp *bridged = NULL;
02048 
02049    rtp_bridge_lock(rtp);
02050    bridged = rtp->bridged;
02051    rtp_bridge_unlock(rtp);
02052 
02053    return bridged;
02054 }

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

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, and rtp_bridge_lock().

Referenced by process_sdp().

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

int ast_rtp_get_peer struct ast_rtp rtp,
struct sockaddr_in *  them
 

Definition at line 2027 of file rtp.c.

References ast_rtp::them.

Referenced by add_sdp(), bridge_native_loop(), check_rtp_timeout(), oh323_set_rtp_peer(), sip_set_rtp_peer(), and transmit_modify_with_sdp().

02028 {
02029    if ((them->sin_family != AF_INET) ||
02030       (them->sin_port != rtp->them.sin_port) ||
02031       (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
02032       them->sin_family = AF_INET;
02033       them->sin_port = rtp->them.sin_port;
02034       them->sin_addr = rtp->them.sin_addr;
02035       return 1;
02036    }
02037    return 0;
02038 }

char* ast_rtp_get_quality struct ast_rtp rtp  ) 
 

Definition at line 2093 of file rtp.c.

References ast_rtcp::expected_prior, ast_rtcp::quality, ast_rtcp::received_prior, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtp::rtcp, ast_rtcp::rtt, ast_rtp::rxcount, ast_rtp::rxjitter, ast_rtp::ssrc, ast_rtp::themssrc, and ast_rtp::txcount.

Referenced by handle_request_bye(), and sip_hangup().

02094 {
02095    /*
02096    *ssrc          our ssrc
02097    *themssrc      their ssrc
02098    *lp            lost packets
02099    *rxjitter      our calculated jitter(rx)
02100    *rxcount       no. received packets
02101    *txjitter      reported jitter of the other end
02102    *txcount       transmitted packets
02103    *rlp           remote lost packets
02104    */
02105    
02106    snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality), "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f", rtp->ssrc, rtp->themssrc, rtp->rtcp->expected_prior - rtp->rtcp->received_prior, rtp->rxjitter, rtp->rxcount, (double)rtp->rtcp->reported_jitter/65536., rtp->txcount, rtp->rtcp->reported_lost, rtp->rtcp->rtt);
02107    
02108    return rtp->rtcp->quality;
02109 }

int ast_rtp_get_rtpholdtimeout struct ast_rtp rtp  ) 
 

Get rtp hold timeout.

Definition at line 569 of file rtp.c.

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

Referenced by check_rtp_timeout().

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

int ast_rtp_get_rtpkeepalive struct ast_rtp rtp  ) 
 

Get RTP keepalive interval.

Definition at line 577 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by check_rtp_timeout().

00578 {
00579    return rtp->rtpkeepalive;
00580 }

int ast_rtp_get_rtptimeout struct ast_rtp rtp  ) 
 

Get rtp timeout.

Definition at line 561 of file rtp.c.

References ast_rtp::rtptimeout.

Referenced by check_rtp_timeout().

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

void ast_rtp_get_us struct ast_rtp rtp,
struct sockaddr_in *  us
 

Definition at line 2040 of file rtp.c.

References ast_rtp::us.

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

02041 {
02042    *us = rtp->us;
02043 }

int ast_rtp_getnat struct ast_rtp rtp  ) 
 

Definition at line 597 of file rtp.c.

References ast_test_flag, and FLAG_NAT_ACTIVE.

Referenced by sip_get_rtp_peer().

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

void ast_rtp_init void   ) 
 

Return RTCP quality string.

Definition at line 3664 of file rtp.c.

References ast_cli_register_multiple(), ast_rtp_reload(), and cli_rtp.

03665 {
03666    ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
03667    ast_rtp_reload();
03668 }

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

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, rtp_bridge_lock(), rtp_bridge_unlock(), 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(), ast_rtp_sendcng(), ast_rtp_senddigit_begin(), ast_rtp_write(), and bridge_p2p_rtp_write().

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

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

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

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

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 1795 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(), ast_rtp_lookup_mime_multiple(), transmit_connect_with_sdp(), and transmit_modify_with_sdp().

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

struct rtpPayloadType ast_rtp_lookup_pt struct ast_rtp rtp,
int  pt
 

Mapping between RTP payload format codes and Asterisk codes:.

Definition at line 1732 of file rtp.c.

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

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

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

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

01600 {
01601    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
01602    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
01603    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
01604    enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED;
01605    enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED; 
01606    int srccodec;
01607 
01608    /* Lock channels */
01609    ast_channel_lock(dest);
01610    while (ast_channel_trylock(src)) {
01611       ast_channel_unlock(dest);
01612       usleep(1);
01613       ast_channel_lock(dest);
01614    }
01615 
01616    /* Find channel driver interfaces */
01617    if (!(destpr = get_proto(dest))) {
01618       if (option_debug)
01619          ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", dest->name);
01620       ast_channel_unlock(dest);
01621       ast_channel_unlock(src);
01622       return 0;
01623    }
01624    if (!(srcpr = get_proto(src))) {
01625       if (option_debug)
01626          ast_log(LOG_DEBUG, "Channel '%s' has no RTP, not doing anything\n", src->name);
01627       ast_channel_unlock(dest);
01628       ast_channel_unlock(src);
01629       return 0;
01630    }
01631 
01632    /* Get audio and video interface (if native bridge is possible) */
01633    audio_dest_res = destpr->get_rtp_info(dest, &destp);
01634    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED;
01635    audio_src_res = srcpr->get_rtp_info(src, &srcp);
01636    video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED;
01637 
01638    /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
01639    if (audio_dest_res != AST_RTP_TRY_NATIVE || audio_src_res != AST_RTP_TRY_NATIVE) {
01640       /* Somebody doesn't want to play... */
01641       ast_channel_unlock(dest);
01642       ast_channel_unlock(src);
01643       return 0;
01644    }
01645    ast_rtp_pt_copy(destp, srcp);
01646    if (vdestp && vsrcp)
01647       ast_rtp_pt_copy(vdestp, vsrcp);
01648    if (srcpr->get_codec)
01649       srccodec = srcpr->get_codec(src);
01650    else
01651       srccodec = 0;
01652    if (media) {
01653       /* Bridge early */
01654       if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
01655          ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name);
01656    }
01657    ast_channel_unlock(dest);
01658    ast_channel_unlock(src);
01659    if (option_debug)
01660       ast_log(LOG_DEBUG, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name);
01661    return 1;
01662 }

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

Initializate a RTP session.

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

Definition at line 1999 of file rtp.c.

References ast_rtp_new_with_bindaddr(), io, and sched.

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

void ast_rtp_new_init struct ast_rtp rtp  ) 
 

Initialize a new RTP structure.

reload rtp configuration

Definition at line 1896 of file rtp.c.

References ast_mutex_init(), ast_random(), ast_set_flag, 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().

01897 {
01898 #ifdef P2P_INTENSE
01899    ast_mutex_init(&rtp->bridge_lock);
01900 #endif
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
 

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_log(), ast_random(), ast_rtcp_new(), ast_rtp_new_init(), free, LOG_ERROR, rtp_socket(), rtpend, rtpstart, and sched.

Referenced by __oh323_rtp_create(), ast_rtp_new(), dialog_activate_media(), gtalk_alloc(), jingle_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 
01945       /* If there's rtcp, initialize it as well. */
01946       if (rtp->rtcp) {
01947          rtp->rtcp->us.sin_port = htons(x + 1);
01948          rtp->rtcp->us.sin_addr = addr;
01949       }
01950       /* Try to bind it/them. */
01951       if (!(first = bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) &&
01952          (!rtp->rtcp || !bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us))))
01953          break;
01954       if (!first) {
01955          /* Primary bind succeeded! Gotta recreate it */
01956          close(rtp->s);
01957          rtp->s = rtp_socket();
01958       }
01959       if (errno != EADDRINUSE) {
01960          /* We got an error that wasn't expected, abort! */
01961          ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno));
01962          close(rtp->s);
01963          if (rtp->rtcp) {
01964             close(rtp->rtcp->s);
01965             free(rtp->rtcp);
01966          }
01967          free(rtp);
01968          return NULL;
01969       }
01970       /* The port was used, increment it (by two). */
01971       x += 2;
01972       /* Did we go over the limit ? */
01973       if (x > rtpend)
01974          /* then, start from the begingig. */
01975          x = (rtpstart + 1) & ~1;
01976       /* Check if we reached the place were we started. */
01977       if (x == startplace) {
01978          /* If so, there's no ports available. */
01979          ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n");
01980          close(rtp->s);
01981          if (rtp->rtcp) {
01982             close(rtp->rtcp->s);
01983             free(rtp->rtcp);
01984          }
01985          free(rtp);
01986          return NULL;
01987       }
01988    }
01989    rtp->sched = sched;
01990    rtp->io = io;
01991    if (callbackmode) {
01992       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
01993       ast_set_flag(rtp, FLAG_CALLBACK_MODE);
01994    }
01995    ast_rtp_pt_default(rtp);
01996    return rtp;
01997 }

int ast_rtp_proto_register struct ast_rtp_protocol proto  ) 
 

Register an RTP channel client.

Definition at line 2809 of file rtp.c.

References ast_log(), AST_RWLIST_INSERT_HEAD, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, LOG_WARNING, protos, and ast_rtp_protocol::type.

Referenced by load_module(), and register_rtp_and_udptl().

02810 {
02811    struct ast_rtp_protocol *cur;
02812 
02813    AST_RWLIST_WRLOCK(&protos);
02814    AST_RWLIST_TRAVERSE(&protos, cur, list) { 
02815       if (!strcmp(cur->type, proto->type)) {
02816          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
02817          AST_RWLIST_UNLOCK(&protos);
02818          return -1;
02819       }
02820    }
02821    AST_RWLIST_INSERT_HEAD(&protos, proto, list);
02822    AST_RWLIST_UNLOCK(&protos);
02823    
02824    return 0;
02825 }

void ast_rtp_proto_unregister struct ast_rtp_protocol proto  ) 
 

Unregister an RTP channel client.

Definition at line 2801 of file rtp.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and protos.

Referenced by load_module(), unload_module(), and unregister_rtp_and_udptl().

02802 {
02803    AST_RWLIST_WRLOCK(&protos);
02804    AST_RWLIST_REMOVE(&protos, proto, list);
02805    AST_RWLIST_UNLOCK(&protos);
02806 }

void ast_rtp_pt_clear struct ast_rtp rtp  ) 
 

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

Definition at line 1446 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, and rtp_bridge_lock().

Referenced by process_sdp().

01447 {
01448    int i;
01449 
01450    if (!rtp)
01451       return;
01452 
01453    rtp_bridge_lock(rtp);
01454 
01455    for (i = 0; i < MAX_RTP_PT; ++i) {
01456       rtp->current_RTP_PT[i].isAstFormat = 0;
01457       rtp->current_RTP_PT[i].code = 0;
01458    }
01459 
01460    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01461    rtp->rtp_lookup_code_cache_code = 0;
01462    rtp->rtp_lookup_code_cache_result = 0;
01463 
01464    rtp_bridge_unlock(rtp);
01465 }

void ast_rtp_pt_copy struct ast_rtp dest,
struct ast_rtp src
 

Copy payload types between RTP structures.

Definition at line 1486 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, and rtp_bridge_lock().

Referenced by ast_rtp_make_compatible().

01487 {
01488    unsigned int i;
01489 
01490    rtp_bridge_lock(dest);
01491    rtp_bridge_lock(src);
01492 
01493    for (i=0; i < MAX_RTP_PT; ++i) {
01494       dest->current_RTP_PT[i].isAstFormat = 
01495          src->current_RTP_PT[i].isAstFormat;
01496       dest->current_RTP_PT[i].code = 
01497          src->current_RTP_PT[i].code; 
01498    }
01499    dest->rtp_lookup_code_cache_isAstFormat = 0;
01500    dest->rtp_lookup_code_cache_code = 0;
01501    dest->rtp_lookup_code_cache_result = 0;
01502 
01503    rtp_bridge_unlock(src);
01504    rtp_bridge_unlock(dest);
01505 }

void ast_rtp_pt_default struct ast_rtp rtp  ) 
 

Set payload types to defaults.

Definition at line 1467 of file rtp.c.

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

01468 {
01469    int i;
01470 
01471    rtp_bridge_lock(rtp);
01472 
01473    /* Initialize to default payload types */
01474    for (i = 0; i < MAX_RTP_PT; ++i) {
01475       rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
01476       rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
01477    }
01478 
01479    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01480    rtp->rtp_lookup_code_cache_code = 0;
01481    rtp->rtp_lookup_code_cache_result = 0;
01482 
01483    rtp_bridge_unlock(rtp);
01484 }

struct ast_frame* ast_rtp_read struct ast_rtp rtp  ) 
 

Definition at line 1144 of file rtp.c.

References ast_codec_get_samples(), AST_FORMAT_MAX_AUDIO, AST_FORMAT_SLINEAR, ast_frame_byteswap_be, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), 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, CRASH, ast_rtp::cycles, ast_frame::data, ast_frame::datalen, ast_frame::delivery, event, ext, ast_rtp::f, FLAG_NAT_ACTIVE, ast_frame::frametype, ast_frame::has_timing_info, rtpPayloadType::isAstFormat, ast_rtp::lasteventseqn, 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(), jingle_rtp_read(), mgcp_rtp_read(), oh323_rtp_read(), rtpread(), sip_rtp_read(), and skinny_rtp_read().

01145 {
01146    int res;
01147    struct sockaddr_in sin;
01148    socklen_t len;
01149    unsigned int seqno;
01150    int version;
01151    int payloadtype;
01152    int tseqno;
01153    int hdrlen = 12;
01154    int padding;
01155    int mark;
01156    int ext;
01157    unsigned int ssrc;
01158    unsigned int timestamp;
01159    unsigned int *rtpheader;
01160    struct rtpPayloadType rtpPT;
01161    struct ast_rtp *bridged = NULL;
01162    
01163    /* If time is up, kill it */
01164    if (rtp->sending_digit)
01165       ast_rtp_senddigit_continuation(rtp);
01166 
01167    len = sizeof(sin);
01168    
01169    /* Cache where the header will go */
01170    res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,
01171                0, (struct sockaddr *)&sin, &len);
01172 
01173    rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET);
01174    if (res < 0) {
01175       if (errno != EAGAIN)
01176          ast_log(LOG_WARNING, "RTP Read error: %s\n", strerror(errno));
01177       if (errno == EBADF)
01178          CRASH;
01179       return &ast_null_frame;
01180    }
01181    
01182    if (res < hdrlen) {
01183       ast_log(LOG_WARNING, "RTP Read too short\n");
01184       return &ast_null_frame;
01185    }
01186 
01187    /* Get fields */
01188    seqno = ntohl(rtpheader[0]);
01189 
01190    /* Check RTP version */
01191    version = (seqno & 0xC0000000) >> 30;
01192    if (!version) {
01193       if ((stun_handle_packet(rtp->s, &sin, rtp->rawdata + AST_FRIENDLY_OFFSET, res) == STUN_ACCEPT) &&
01194          (!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) {
01195          memcpy(&rtp->them, &sin, sizeof(rtp->them));
01196       }
01197       return &ast_null_frame;
01198    }
01199 
01200 #if 0 /* Allow to receive RTP stream with closed transmission path */
01201    /* If we don't have the other side's address, then ignore this */
01202    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
01203       return &ast_null_frame;
01204 #endif
01205 
01206    /* Send to whoever send to us if NAT is turned on */
01207    if (rtp->nat) {
01208       if ((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
01209           (rtp->them.sin_port != sin.sin_port)) {
01210          rtp->them = sin;
01211          if (rtp->rtcp) {
01212             memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
01213             rtp->rtcp->them.sin_port = htons(ntohs(rtp->them.sin_port)+1);
01214          }
01215          rtp->rxseqno = 0;
01216          ast_set_flag(rtp, FLAG_NAT_ACTIVE);
01217          if (option_debug || rtpdebug)
01218             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));
01219       }
01220    }
01221 
01222    /* If we are bridged to another RTP stream, send direct */
01223    if ((bridged = ast_rtp_get_bridged(rtp)) && !bridge_p2p_rtp_write(rtp, bridged, rtpheader, res, hdrlen))
01224       return &ast_null_frame;
01225 
01226    if (version != 2)
01227       return &ast_null_frame;
01228 
01229    payloadtype = (seqno & 0x7f0000) >> 16;
01230    padding = seqno & (1 << 29);
01231    mark = seqno & (1 << 23);
01232    ext = seqno & (1 << 28);
01233    seqno &= 0xffff;
01234    timestamp = ntohl(rtpheader[1]);
01235    ssrc = ntohl(rtpheader[2]);
01236    
01237    if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) {
01238       if (option_debug || rtpdebug)
01239          ast_log(LOG_DEBUG, "Forcing Marker bit, because SSRC has changed\n");
01240       mark = 1;
01241    }
01242 
01243    rtp->rxssrc = ssrc;
01244    
01245    if (padding) {
01246       /* Remove padding bytes */
01247       res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1];
01248    }
01249    
01250    if (ext) {
01251       /* RTP Extension present */
01252       hdrlen += 4;
01253       hdrlen += (ntohl(rtpheader[3]) & 0xffff) << 2;
01254       if (option_debug) {
01255          int profile;
01256          profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16;
01257          if (profile == 0x505a)
01258             ast_log(LOG_DEBUG, "Found Zfone extension in RTP stream - zrtp - not supported.\n");
01259          else
01260             ast_log(LOG_DEBUG, "Found unknown RTP Extensions %x\n", profile);
01261       }
01262    }
01263 
01264    if (res < hdrlen) {
01265       ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen);
01266       return &ast_null_frame;
01267    }
01268 
01269    rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */
01270 
01271    tseqno = rtp->lastrxseqno +1;
01272 
01273    if (rtp->rxcount==1) {
01274       /* This is the first RTP packet successfully received from source */
01275       rtp->seedrxseqno = seqno;
01276    }
01277 
01278    /* Do not schedule RR if RTCP isn't run */
01279    if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) {
01280       /* Schedule transmission of Receiver Report */
01281       rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
01282    }
01283 
01284    if (tseqno > RTP_SEQ_MOD) { /* if tseqno is greater than RTP_SEQ_MOD it would indicate that the sender cycled */
01285       rtp->cycles += RTP_SEQ_MOD;
01286       ast_verbose("SEQNO cycled: %u\t%d\n", rtp->cycles, seqno);
01287    }
01288 
01289    rtp->lastrxseqno = seqno;
01290    
01291    if (rtp->themssrc==0)
01292       rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */
01293    
01294    if (rtp_debug_test_addr(&sin))
01295       ast_verbose("Got  RTP packet from    %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
01296          ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen);
01297 
01298    rtpPT = ast_rtp_lookup_pt(rtp, payloadtype);
01299    if (!rtpPT.isAstFormat) {
01300       struct ast_frame *f = NULL;
01301 
01302       /* This is special in-band data that's not one of our codecs */
01303       if (rtpPT.code == AST_RTP_DTMF) {
01304          /* It's special -- rfc2833 process it */
01305          if (rtp_debug_test_addr(&sin)) {
01306             unsigned char *data;
01307             unsigned int event;
01308             unsigned int event_end;
01309             unsigned int duration;
01310             data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen;
01311             event = ntohl(*((unsigned int *)(data)));
01312             event >>= 24;
01313             event_end = ntohl(*((unsigned int *)(data)));
01314             event_end <<= 8;
01315             event_end >>= 24;
01316             duration = ntohl(*((unsigned int *)(data)));
01317             duration &= 0xFFFF;
01318             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);
01319          }
01320          f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno);
01321       } else if (rtpPT.code == AST_RTP_CISCO_DTMF) {
01322          /* It's really special -- process it the Cisco way */
01323          if (rtp->lasteventseqn <= seqno || (rtp->lasteventseqn >= 65530 && seqno <= 6)) {
01324             f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
01325             rtp->lasteventseqn = seqno;
01326          }
01327       } else if (rtpPT.code == AST_RTP_CN) {
01328          /* Comfort Noise */
01329          f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
01330       } else {
01331          ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr));
01332       }
01333       return f ? f : &ast_null_frame;
01334    }
01335    rtp->lastrxformat = rtp->f.subclass = rtpPT.code;
01336    rtp->f.frametype = (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) ? AST_FRAME_VOICE : AST_FRAME_VIDEO;
01337 
01338    if (!rtp->lastrxts)
01339       rtp->lastrxts = timestamp;
01340 
01341    rtp->rxseqno = seqno;
01342 
01343    /* Record received timestamp as last received now */
01344    rtp->lastrxts = timestamp;
01345 
01346    rtp->f.mallocd = 0;
01347    rtp->f.datalen = res - hdrlen;
01348    rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
01349    rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
01350    if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) {
01351       rtp->f.samples = ast_codec_get_samples(&rtp->f);
01352       if (rtp->f.subclass == AST_FORMAT_SLINEAR) 
01353          ast_frame_byteswap_be(&rtp->f);
01354       calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
01355       /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */
01356       rtp->f.has_timing_info = 1;
01357       rtp->f.ts = timestamp / 8;
01358       rtp->f.len = rtp->f.samples / 8;
01359       rtp->f.seqno = seqno;
01360    } else {
01361       /* Video -- samples is # of samples vs. 90000 */
01362       if (!rtp->lastividtimestamp)
01363          rtp->lastividtimestamp = timestamp;
01364       rtp->f.samples = timestamp - rtp->lastividtimestamp;
01365       rtp->lastividtimestamp = timestamp;
01366       rtp->f.delivery.tv_sec = 0;
01367       rtp->f.delivery.tv_usec = 0;
01368       if (mark)
01369          rtp->f.subclass |= 0x1;
01370       
01371    }
01372    rtp->f.src = "RTP";
01373    return &rtp->f;
01374 }

int ast_rtp_reload void   ) 
 

Initialize RTP subsystem

Definition at line 3599 of file rtp.c.

References ast_config_destroy(), ast_config_load(), ast_false(), ast_log(), ast_variable_retrieve(), ast_verbose(), DEFAULT_DTMF_TIMEOUT, dtmftimeout, option_verbose, RTCP_MAX_INTERVALMS, RTCP_MIN_INTERVALMS, rtcpinterval, rtpend, rtpstart, s, and VERBOSE_PREFIX_2.

Referenced by ast_rtp_init().

03600 {
03601    struct ast_config *cfg;
03602    const char *s;
03603 
03604    rtpstart = 5000;
03605    rtpend = 31000;
03606    dtmftimeout = DEFAULT_DTMF_TIMEOUT;
03607    cfg = ast_config_load("rtp.conf");
03608    if (cfg) {
03609       if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
03610          rtpstart = atoi(s);
03611          if (rtpstart < 1024)
03612             rtpstart = 1024;
03613          if (rtpstart > 65535)
03614             rtpstart = 65535;
03615       }
03616       if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
03617          rtpend = atoi(s);
03618          if (rtpend < 1024)
03619             rtpend = 1024;
03620          if (rtpend > 65535)
03621             rtpend = 65535;
03622       }
03623       if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
03624          rtcpinterval = atoi(s);
03625          if (rtcpinterval == 0)
03626             rtcpinterval = 0; /* Just so we're clear... it's zero */
03627          if (rtcpinterval < RTCP_MIN_INTERVALMS)
03628             rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
03629          if (rtcpinterval > RTCP_MAX_INTERVALMS)
03630             rtcpinterval = RTCP_MAX_INTERVALMS;
03631       }
03632       if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
03633 #ifdef SO_NO_CHECK
03634          if (ast_false(s))
03635             nochecksums = 1;
03636          else
03637             nochecksums = 0;
03638 #else
03639          if (ast_false(s))
03640             ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
03641 #endif
03642       }
03643       if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
03644          dtmftimeout = atoi(s);
03645          if ((dtmftimeout < 0) || (dtmftimeout > 20000)) {
03646             ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
03647                dtmftimeout, DEFAULT_DTMF_TIMEOUT);
03648             dtmftimeout = DEFAULT_DTMF_TIMEOUT;
03649          };
03650       }
03651       ast_config_destroy(cfg);
03652    }
03653    if (rtpstart >= rtpend) {
03654       ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
03655       rtpstart = 5000;
03656       rtpend = 31000;
03657    }
03658    if (option_verbose > 1)
03659       ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
03660    return 0;
03661 }

void ast_rtp_reset struct ast_rtp rtp  ) 
 

Definition at line 2073 of file rtp.c.

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

02074 {
02075    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
02076    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
02077    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
02078    rtp->lastts = 0;
02079    rtp->lastdigitts = 0;
02080    rtp->lastrxts = 0;
02081    rtp->lastividtimestamp = 0;
02082    rtp->lastovidtimestamp = 0;
02083    rtp->lasteventseqn = 0;
02084    rtp->lasteventendseqn = 0;
02085    rtp->lasttxformat = 0;
02086    rtp->lastrxformat = 0;
02087    rtp->dtmfcount = 0;
02088    rtp->dtmfsamples = 0;
02089    rtp->seqno = 0;
02090    rtp->rxseqno = 0;
02091 }

int ast_rtp_sendcng struct ast_rtp rtp,
int  level
 

generate comfort noice (CNG)

Definition at line 2568 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, ast_rtp::lastts, LOG_ERROR, rtp_debug_test_addr(), ast_rtp::s, ast_rtp::seqno, ast_rtp::ssrc, and ast_rtp::them.

Referenced by check_rtp_timeout().

02569 {
02570    unsigned int *rtpheader;
02571    int hdrlen = 12;
02572    int res;
02573    int payload;
02574    char data[256];
02575    level = 127 - (level & 0x7f);
02576    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN);
02577 
02578    /* If we have no peer, return immediately */ 
02579    if (!rtp->them.sin_addr.s_addr)
02580       return 0;
02581 
02582    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
02583 
02584    /* Get a pointer to the header */
02585    rtpheader = (unsigned int *)data;
02586    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
02587    rtpheader[1] = htonl(rtp->lastts);
02588    rtpheader[2] = htonl(rtp->ssrc); 
02589    data[12] = level;
02590    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
02591       res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
02592       if (res <0) 
02593          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));
02594       if (rtp_debug_test_addr(&rtp->them))
02595          ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n"
02596                , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen);         
02597          
02598    }
02599    return 0;
02600 }

int ast_rtp_senddigit_begin struct ast_rtp rtp,
char  digit
 

Send begin frames for DTMF.

Definition at line 2171 of file rtp.c.

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

Referenced by oh323_digit_begin(), and sip_senddigit_begin().

02172 {
02173    unsigned int *rtpheader;
02174    int hdrlen = 12, res = 0, i = 0, payload = 0;
02175    char data[256];
02176 
02177    if ((digit <= '9') && (digit >= '0'))
02178       digit -= '0';
02179    else if (digit == '*')
02180       digit = 10;
02181    else if (digit == '#')
02182       digit = 11;
02183    else if ((digit >= 'A') && (digit <= 'D'))
02184       digit = digit - 'A' + 12;
02185    else if ((digit >= 'a') && (digit <= 'd'))
02186       digit = digit - 'a' + 12;
02187    else {
02188       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
02189       return 0;
02190    }
02191 
02192    /* If we have no peer, return immediately */ 
02193    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
02194       return 0;
02195 
02196    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF);
02197 
02198    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
02199    rtp->send_duration = 160;
02200    
02201    /* Get a pointer to the header */
02202    rtpheader = (unsigned int *)data;
02203    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
02204    rtpheader[1] = htonl(rtp->lastdigitts);
02205    rtpheader[2] = htonl(rtp->ssrc); 
02206 
02207    for (i = 0; i < 2; i++) {
02208       rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
02209       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
02210       if (res < 0) 
02211          ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n",
02212             ast_inet_ntoa(rtp->them.sin_addr),
02213             ntohs(rtp->them.sin_port), strerror(errno));
02214       if (rtp_debug_test_addr(&rtp->them))
02215          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02216                 ast_inet_ntoa(rtp->them.sin_addr),
02217                 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
02218       /* Increment sequence number */
02219       rtp->seqno++;
02220       /* Increment duration */
02221       rtp->send_duration += 160;
02222       /* Clear marker bit and set seqno */
02223       rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
02224    }
02225 
02226    /* Since we received a begin, we can safely store the digit and disable any compensation */
02227    rtp->sending_digit = 1;
02228    rtp->send_digit = digit;
02229    rtp->send_payload = payload;
02230 
02231    return 0;
02232 }

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

References ast_rtp::callback.

Referenced by start_rtp().

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

void ast_rtp_set_data struct ast_rtp rtp,
void *  data
 

Definition at line 582 of file rtp.c.

References ast_rtp::data.

Referenced by start_rtp().

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

void ast_rtp_set_m_type struct ast_rtp rtp,
int  pt
 

Make a note of a RTP payload type that was seen in a SDP "m=" line. By default, use the well-known value for this type (although it may still be set to a different value by a subsequent "a=rtpmap:" line).

Definition at line 1668 of file rtp.c.

References ast_rtp::current_RTP_PT, MAX_RTP_PT, rtp_bridge_lock(), rtp_bridge_unlock(), and static_RTP_PT.

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

01669 {
01670    if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 
01671       return; /* bogus payload type */
01672 
01673    rtp_bridge_lock(rtp);
01674    rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
01675    rtp_bridge_unlock(rtp);
01676 } 

void ast_rtp_set_peer struct ast_rtp rtp,
struct sockaddr_in *  them
 

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

02017 {
02018    rtp->them.sin_port = them->sin_port;
02019    rtp->them.sin_addr = them->sin_addr;
02020    if (rtp->rtcp) {
02021       rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1);
02022       rtp->rtcp->them.sin_addr = them->sin_addr;
02023    }
02024    rtp->rxseqno = 0;
02025 }

void ast_rtp_set_rtpholdtimeout struct ast_rtp rtp,
int  timeout
 

Set rtp hold timeout.

Definition at line 549 of file rtp.c.

References ast_rtp::rtpholdtimeout.

Referenced by check_rtp_timeout(), create_addr_from_peer(), dialog_activate_media(), and sip_alloc().

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

void ast_rtp_set_rtpkeepalive struct ast_rtp rtp,
int  period
 

set RTP keepalive interval

Definition at line 555 of file rtp.c.

References ast_rtp::rtpkeepalive.

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

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

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

Make a note of a RTP payload type (with MIME type) that was seen in an SDP "a=rtpmap:" line.

Definition at line 1681 of file rtp.c.

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

Referenced by __oh323_rtp_create(), gtalk_newcall(), jingle_newcall(), process_sdp(), set_dtmf_payload(), and setup_rtp_connection().

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

void ast_rtp_set_rtptimeout struct ast_rtp rtp,
int  timeout
 

Set rtp timeout.

Definition at line 543 of file rtp.c.

References ast_rtp::rtptimeout.

Referenced by check_rtp_timeout(), create_addr_from_peer(), dialog_activate_media(), and sip_alloc().

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

void ast_rtp_set_rtptimers_onhold struct ast_rtp rtp  ) 
 

Definition at line 536 of file rtp.c.

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

Referenced by handle_response_answer(), and handle_response_invite().

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

void ast_rtp_setdtmf struct ast_rtp rtp,
int  dtmf
 

Indicate whether this RTP session is carrying DTMF or not.

Definition at line 602 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_DTMF.

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

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

void ast_rtp_setdtmfcompensate struct ast_rtp rtp,
int  compensate
 

Compensate for devices that send RFC2833 packets all at once.

Definition at line 607 of file rtp.c.

References ast_set2_flag, and FLAG_DTMF_COMPENSATE.

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

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

void ast_rtp_setnat struct ast_rtp rtp,
int  nat
 

Definition at line 592 of file rtp.c.

References ast_rtp::nat.

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

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

void ast_rtp_setstun struct ast_rtp rtp,
int  stun_enable
 

Enable STUN capability.

Definition at line 612 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_STUN.

Referenced by gtalk_new().

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

int ast_rtp_settos struct ast_rtp rtp,
int  tos
 

Definition at line 2007 of file rtp.c.

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

Referenced by __oh323_rtp_create(), dialog_activate_media(), and sip_alloc().

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

void ast_rtp_stop struct ast_rtp rtp  ) 
 

Stop RTP session, do not destroy structure

Definition at line 2056 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 setup_rtp_connection(), and stop_media_flows().

02057 {
02058    if (rtp->rtcp && rtp->rtcp->schedid > 0) {
02059       ast_sched_del(rtp->sched, rtp->rtcp->schedid);
02060       rtp->rtcp->schedid = -1;
02061    }
02062 
02063    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
02064    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
02065    if (rtp->rtcp) {
02066       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
02067       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
02068    }
02069    
02070    ast_clear_flag(rtp, FLAG_P2P_SENT_MARK);
02071 }

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

Send STUN request (??).

Definition at line 404 of file rtp.c.

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

Referenced by gtalk_update_stun(), and jingle_update_stun().

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

int ast_rtp_write struct ast_rtp rtp,
struct ast_frame _f
 

Bug:
XXX this might never be free'd. Why do we do this?

Definition at line 2722 of file rtp.c.

References ast_codec_pref_getsize(), 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_frame::datalen, fmt, ast_frame::frametype, ast_rtp::lasttxformat, LOG_DEBUG, LOG_WARNING, ast_frame::offset, option_debug, ast_rtp::pref, ast_rtp::smoother, ast_frame::subclass, and ast_rtp::them.

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

02723 {
02724    struct ast_frame *f;
02725    int codec;
02726    int hdrlen = 12;
02727    int subclass;
02728    
02729 
02730    /* If we have no peer, return immediately */ 
02731    if (!rtp->them.sin_addr.s_addr)
02732       return 0;
02733 
02734    /* If there is no data length, return immediately */
02735    if (!_f->datalen) 
02736       return 0;
02737    
02738    /* Make sure we have enough space for RTP header */
02739    if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) {
02740       ast_log(LOG_WARNING, "RTP can only send voice and video\n");
02741       return -1;
02742    }
02743 
02744    subclass = _f->subclass;
02745    if (_f->frametype == AST_FRAME_VIDEO)
02746       subclass &= ~0x1;
02747 
02748    codec = ast_rtp_lookup_code(rtp, 1, subclass);
02749    if (codec < 0) {
02750       ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass));
02751       return -1;
02752    }
02753 
02754    if (rtp->lasttxformat != subclass) {
02755       /* New format, reset the smoother */
02756       if (option_debug)
02757          ast_log(LOG_DEBUG, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
02758       rtp->lasttxformat = subclass;
02759       if (rtp->smoother)
02760          ast_smoother_free(rtp->smoother);
02761       rtp->smoother = NULL;
02762    }
02763 
02764    if (!rtp->smoother) {
02765       struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass);
02766       if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */
02767          if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
02768             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));
02769             return -1;
02770          }
02771          if (fmt.flags)
02772             ast_smoother_set_flags(rtp->smoother, fmt.flags);
02773          if (option_debug)
02774             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));
02775       }
02776    }
02777    if (rtp->smoother) {
02778       if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) {
02779          ast_smoother_feed_be(rtp->smoother, _f);
02780       } else {
02781          ast_smoother_feed(rtp->smoother, _f);
02782       }
02783 
02784       while ((f = ast_smoother_read(rtp->smoother)))
02785          ast_rtp_raw_write(rtp, f, codec);
02786    } else {
02787            /* Don't buffer outgoing frames; send them one-per-packet: */
02788       if (_f->offset < hdrlen) 
02789          f = ast_frdup(_f);   /*! \bug XXX this might never be free'd. Why do we do this? */
02790       else
02791          f = _f;
02792       ast_rtp_raw_write(rtp, f, codec);
02793       if (f != _f)
02794          ast_frfree(f);
02795    }
02796       
02797    return 0;
02798 }


Asterisk is a trademark for Digium, inc.. | Edvina.net | Asterisk.org | This documentation was generated with Doxygen