Wed Aug 18 22:34:32 2010

Asterisk developer's documentation


rtp.h File Reference

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

#include "asterisk/network.h"
#include "asterisk/frame.h"
#include "asterisk/io.h"
#include "asterisk/sched.h"
#include "asterisk/channel.h"
#include "asterisk/linkedlists.h"

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...
struct  ast_rtp_quality
 RTCP quality report storage. 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
#define RED_MAX_GENERATION   5

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) }
enum  ast_rtp_qos_vars {
  AST_RTP_TXCOUNT, AST_RTP_RXCOUNT, AST_RTP_TXJITTER, AST_RTP_RXJITTER,
  AST_RTP_RXPLOSS, AST_RTP_TXPLOSS, AST_RTP_RTT
}
 Variables used in ast_rtcp_get function. More...
enum  ast_rtp_quality_type { RTPQOS_SUMMARY = 0, RTPQOS_JITTER, RTPQOS_LOSS, RTPQOS_RTT }

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.
void ast_rtp_change_source (struct ast_rtp *rtp)
 Indicate that we need to set the marker bit and change the ssrc.
int ast_rtp_codec_getformat (int pt)
 get format from predefined dynamic payload format
ast_codec_prefast_rtp_codec_getpref (struct ast_rtp *rtp)
 Get codec preference.
void ast_rtp_codec_setpref (struct ast_rtp *rtp, struct ast_codec_pref *prefs)
 Set codec preference.
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)
int ast_rtp_get_qos (struct ast_rtp *rtp, const char *qos, char *buf, unsigned int buflen)
 Get QOS stats on a RTP channel.
unsigned int ast_rtp_get_qosvalue (struct ast_rtp *rtp, enum ast_rtp_qos_vars value)
 Return RTP and RTCP QoS values.
char * ast_rtp_get_quality (struct ast_rtp *rtp, struct ast_rtp_quality *qual, enum ast_rtp_quality_type qtype)
 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):.
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.
void ast_rtp_new_source (struct ast_rtp *rtp)
 Indicate that we need to set the marker bit.
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_alt_peer (struct ast_rtp *rtp, struct sockaddr_in *alt)
 set potential alternate source for RTP media
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_set_vars (struct ast_channel *chan, struct ast_rtp *rtp)
 Set RTPAUDIOQOS(...) variables on a channel when it is being hung up.
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)
int ast_rtp_setqos (struct ast_rtp *rtp, int tos, int cos, char *desc)
void ast_rtp_setstun (struct ast_rtp *rtp, int stun_enable)
 Enable STUN capability.
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 for an RTP socket Deprecated, this is just a wrapper for ast_rtp_stun_request().
void ast_rtp_unset_m_type (struct ast_rtp *rtp, int pt)
 clear payload type
int ast_rtp_write (struct ast_rtp *rtp, struct ast_frame *f)
int ast_stun_request (int s, struct sockaddr_in *dst, const char *username, struct sockaddr_in *answer)
 Generic STUN request send a generic stun request to the server specified.
void red_buffer_t140 (struct ast_rtp *rtp, struct ast_frame *f)
 Buffer t.140 data.
int rtp_red_init (struct ast_rtp *rtp, int ti, int *pt, int num_gen)
 Initalize t.140 redudancy.


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)

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(), create_addr(), create_addr_from_peer(), oh323_alloc(), oh323_request(), process_sdp(), sip_alloc(), and sip_dtmfmode().

#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 57 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_get_current_formats(), ast_rtp_lookup_code(), ast_rtp_lookup_pt(), ast_rtp_pt_clear(), ast_rtp_pt_copy(), ast_rtp_pt_default(), ast_rtp_set_m_type(), ast_rtp_set_rtpmap_type(), ast_rtp_unset_m_type(), and process_sdp_a_audio().

#define RED_MAX_GENERATION   5

T.140 Redundancy Maxium number of generations

Definition at line 55 of file rtp.h.

Referenced by process_sdp_a_text().


Typedef Documentation

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

RTP callback structure

Definition at line 124 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 63 of file rtp.h.

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

enum ast_rtp_options

Enumerator:
AST_RTP_OPT_G726_NONSTANDARD 

Definition at line 59 of file rtp.h.

00059                      {
00060    AST_RTP_OPT_G726_NONSTANDARD = (1 << 0),
00061 };

enum ast_rtp_qos_vars

Variables used in ast_rtcp_get function.

Enumerator:
AST_RTP_TXCOUNT 
AST_RTP_RXCOUNT 
AST_RTP_TXJITTER 
AST_RTP_RXJITTER 
AST_RTP_RXPLOSS 
AST_RTP_TXPLOSS 
AST_RTP_RTT 

Definition at line 73 of file rtp.h.

00073                       {
00074    AST_RTP_TXCOUNT,
00075    AST_RTP_RXCOUNT,
00076    AST_RTP_TXJITTER,
00077    AST_RTP_RXJITTER,
00078    AST_RTP_RXPLOSS,
00079    AST_RTP_TXPLOSS,
00080    AST_RTP_RTT
00081 };

enum ast_rtp_quality_type

Enumerator:
RTPQOS_SUMMARY 
RTPQOS_JITTER 
RTPQOS_LOSS 
RTPQOS_RTT 

Definition at line 103 of file rtp.h.

00103                           {
00104    RTPQOS_SUMMARY = 0,
00105    RTPQOS_JITTER,
00106    RTPQOS_LOSS,
00107    RTPQOS_RTT
00108 };


Function Documentation

int ast_rtcp_fd ( struct ast_rtp rtp  ) 

Definition at line 730 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(), start_rtp(), and unistim_new().

00731 {
00732    if (rtp->rtcp)
00733       return rtp->rtcp->s;
00734    return -1;
00735 }

struct ast_frame* ast_rtcp_read ( struct ast_rtp rtp  ) 

Definition at line 1187 of file rtp.c.

References ast_rtcp::accumulated_transit, ast_rtcp::altthem, ast_assert, AST_CONTROL_VIDUPDATE, ast_debug, AST_FRAME_CONTROL, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_verbose, ast_frame::datalen, errno, EVENT_FLAG_REPORTING, ast_rtp::f, f, ast_frame::frametype, len(), LOG_DEBUG, LOG_WARNING, ast_frame::mallocd, manager_event, ast_rtcp::maxrtt, ast_rtcp::minrtt, ast_rtp::nat, normdev_compute(), ast_rtcp::normdevrtt, option_debug, ast_rtcp::reported_jitter, ast_rtcp::reported_jitter_count, ast_rtcp::reported_lost, ast_rtcp::reported_maxjitter, ast_rtcp::reported_maxlost, ast_rtcp::reported_minjitter, ast_rtcp::reported_minlost, ast_rtcp::reported_normdev_jitter, ast_rtcp::reported_normdev_lost, ast_rtcp::reported_stdev_jitter, ast_rtcp::reported_stdev_lost, ast_rtp::rtcp, rtcp_debug_test_addr(), ast_rtcp::rtcp_info, RTCP_PT_BYE, RTCP_PT_FUR, RTCP_PT_RR, RTCP_PT_SDES, RTCP_PT_SR, ast_rtcp::rtt, ast_rtcp::rtt_count, ast_rtcp::rxlsr, ast_rtcp::s, ast_frame::samples, ast_rtcp::soc, ast_rtcp::spc, ast_frame::src, stddev_compute(), ast_rtcp::stdevrtt, ast_frame::subclass, ast_rtcp::them, ast_rtcp::themrxlsr, and timeval2ntp().

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

01188 {
01189    socklen_t len;
01190    int position, i, packetwords;
01191    int res;
01192    struct sockaddr_in sock_in;
01193    unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET];
01194    unsigned int *rtcpheader;
01195    int pt;
01196    struct timeval now;
01197    unsigned int length;
01198    int rc;
01199    double rttsec;
01200    uint64_t rtt = 0;
01201    unsigned int dlsr;
01202    unsigned int lsr;
01203    unsigned int msw;
01204    unsigned int lsw;
01205    unsigned int comp;
01206    struct ast_frame *f = &ast_null_frame;
01207    
01208    double reported_jitter;
01209    double reported_normdev_jitter_current;
01210    double normdevrtt_current;
01211    double reported_lost;
01212    double reported_normdev_lost_current;
01213 
01214    if (!rtp || !rtp->rtcp)
01215       return &ast_null_frame;
01216 
01217    len = sizeof(sock_in);
01218    
01219    res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET,
01220                0, (struct sockaddr *)&sock_in, &len);
01221    rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET);
01222    
01223    if (res < 0) {
01224       ast_assert(errno != EBADF);
01225       if (errno != EAGAIN) {
01226          ast_log(LOG_WARNING, "RTCP Read error: %s.  Hanging up.\n", strerror(errno));
01227          return NULL;
01228       }
01229       return &ast_null_frame;
01230    }
01231 
01232    packetwords = res / 4;
01233    
01234    if (rtp->nat) {
01235       /* Send to whoever sent to us */
01236       if (((rtp->rtcp->them.sin_addr.s_addr != sock_in.sin_addr.s_addr) ||
01237           (rtp->rtcp->them.sin_port != sock_in.sin_port)) && 
01238           ((rtp->rtcp->altthem.sin_addr.s_addr != sock_in.sin_addr.s_addr) || 
01239           (rtp->rtcp->altthem.sin_port != sock_in.sin_port))) {
01240          memcpy(&rtp->rtcp->them, &sock_in, sizeof(rtp->rtcp->them));
01241          if (option_debug || rtpdebug)
01242             ast_debug(0, "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));
01243       }
01244    }
01245 
01246    ast_debug(1, "Got RTCP report of %d bytes\n", res);
01247 
01248    /* Process a compound packet */
01249    position = 0;
01250    while (position < packetwords) {
01251       i = position;
01252       length = ntohl(rtcpheader[i]);
01253       pt = (length & 0xff0000) >> 16;
01254       rc = (length & 0x1f000000) >> 24;
01255       length &= 0xffff;
01256  
01257       if ((i + length) > packetwords) {
01258          if (option_debug || rtpdebug)
01259             ast_log(LOG_DEBUG, "RTCP Read too short\n");
01260          return &ast_null_frame;
01261       }
01262       
01263       if (rtcp_debug_test_addr(&sock_in)) {
01264          ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port));
01265          ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown");
01266          ast_verbose("Reception reports: %d\n", rc);
01267          ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]);
01268       }
01269  
01270       i += 2; /* Advance past header and ssrc */
01271       
01272       switch (pt) {
01273       case RTCP_PT_SR:
01274          gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */
01275          rtp->rtcp->spc = ntohl(rtcpheader[i+3]);
01276          rtp->rtcp->soc = ntohl(rtcpheader[i + 4]);
01277          rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/
01278  
01279          if (rtcp_debug_test_addr(&sock_in)) {
01280             ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096);
01281             ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2]));
01282             ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4]));
01283          }
01284          i += 5;
01285          if (rc < 1)
01286             break;
01287          /* Intentional fall through */
01288       case RTCP_PT_RR:
01289          /* Don't handle multiple reception reports (rc > 1) yet */
01290          /* Calculate RTT per RFC */
01291          gettimeofday(&now, NULL);
01292          timeval2ntp(now, &msw, &lsw);
01293          if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */
01294             comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16);
01295             lsr = ntohl(rtcpheader[i + 4]);
01296             dlsr = ntohl(rtcpheader[i + 5]);
01297             rtt = comp - lsr - dlsr;
01298 
01299             /* Convert end to end delay to usec (keeping the calculation in 64bit space)
01300                sess->ee_delay = (eedelay * 1000) / 65536; */
01301             if (rtt < 4294) {
01302                 rtt = (rtt * 1000000) >> 16;
01303             } else {
01304                 rtt = (rtt * 1000) >> 16;
01305                 rtt *= 1000;
01306             }
01307             rtt = rtt / 1000.;
01308             rttsec = rtt / 1000.;
01309             rtp->rtcp->rtt = rttsec;
01310 
01311             if (comp - dlsr >= lsr) {
01312                rtp->rtcp->accumulated_transit += rttsec;
01313 
01314                if (rtp->rtcp->rtt_count == 0) 
01315                   rtp->rtcp->minrtt = rttsec;
01316 
01317                if (rtp->rtcp->maxrtt<rttsec)
01318                   rtp->rtcp->maxrtt = rttsec;
01319 
01320                if (rtp->rtcp->minrtt>rttsec)
01321                   rtp->rtcp->minrtt = rttsec;
01322 
01323                normdevrtt_current = normdev_compute(rtp->rtcp->normdevrtt, rttsec, rtp->rtcp->rtt_count);
01324 
01325                rtp->rtcp->stdevrtt = stddev_compute(rtp->rtcp->stdevrtt, rttsec, rtp->rtcp->normdevrtt, normdevrtt_current, rtp->rtcp->rtt_count);
01326 
01327                rtp->rtcp->normdevrtt = normdevrtt_current;
01328 
01329                rtp->rtcp->rtt_count++;
01330             } else if (rtcp_debug_test_addr(&sock_in)) {
01331                ast_verbose("Internal RTCP NTP clock skew detected: "
01332                         "lsr=%u, now=%u, dlsr=%u (%d:%03dms), "
01333                         "diff=%d\n",
01334                         lsr, comp, dlsr, dlsr / 65536,
01335                         (dlsr % 65536) * 1000 / 65536,
01336                         dlsr - (comp - lsr));
01337             }
01338          }
01339 
01340          rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]);
01341          reported_jitter = (double) rtp->rtcp->reported_jitter;
01342 
01343          if (rtp->rtcp->reported_jitter_count == 0) 
01344             rtp->rtcp->reported_minjitter = reported_jitter;
01345 
01346          if (reported_jitter < rtp->rtcp->reported_minjitter) 
01347             rtp->rtcp->reported_minjitter = reported_jitter;
01348 
01349          if (reported_jitter > rtp->rtcp->reported_maxjitter) 
01350             rtp->rtcp->reported_maxjitter = reported_jitter;
01351 
01352          reported_normdev_jitter_current = normdev_compute(rtp->rtcp->reported_normdev_jitter, reported_jitter, rtp->rtcp->reported_jitter_count);
01353 
01354          rtp->rtcp->reported_stdev_jitter = stddev_compute(rtp->rtcp->reported_stdev_jitter, reported_jitter, rtp->rtcp->reported_normdev_jitter, reported_normdev_jitter_current, rtp->rtcp->reported_jitter_count);
01355 
01356          rtp->rtcp->reported_normdev_jitter = reported_normdev_jitter_current;
01357 
01358          rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff;
01359 
01360          reported_lost = (double) rtp->rtcp->reported_lost;
01361 
01362          /* using same counter as for jitter */
01363          if (rtp->rtcp->reported_jitter_count == 0)
01364             rtp->rtcp->reported_minlost = reported_lost;
01365 
01366          if (reported_lost < rtp->rtcp->reported_minlost)
01367             rtp->rtcp->reported_minlost = reported_lost;
01368 
01369          if (reported_lost > rtp->rtcp->reported_maxlost) 
01370             rtp->rtcp->reported_maxlost = reported_lost;
01371 
01372          reported_normdev_lost_current = normdev_compute(rtp->rtcp->reported_normdev_lost, reported_lost, rtp->rtcp->reported_jitter_count);
01373 
01374          rtp->rtcp->reported_stdev_lost = stddev_compute(rtp->rtcp->reported_stdev_lost, reported_lost, rtp->rtcp->reported_normdev_lost, reported_normdev_lost_current, rtp->rtcp->reported_jitter_count);
01375 
01376          rtp->rtcp->reported_normdev_lost = reported_normdev_lost_current;
01377 
01378          rtp->rtcp->reported_jitter_count++;
01379 
01380          if (rtcp_debug_test_addr(&sock_in)) {
01381             ast_verbose("  Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24));
01382             ast_verbose("  Packets lost so far: %d\n", rtp->rtcp->reported_lost);
01383             ast_verbose("  Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff));
01384             ast_verbose("  Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16);
01385             ast_verbose("  Interarrival jitter: %u\n", rtp->rtcp->reported_jitter);
01386             ast_verbose("  Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096);
01387             ast_verbose("  DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0);
01388             if (rtt)
01389                ast_verbose("  RTT: %lu(sec)\n", (unsigned long) rtt);
01390          }
01391 
01392          if (rtt) {
01393             manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From: %s:%d\r\n"
01394                             "PT: %d(%s)\r\n"
01395                             "ReceptionReports: %d\r\n"
01396                             "SenderSSRC: %u\r\n"
01397                             "FractionLost: %ld\r\n"
01398                             "PacketsLost: %d\r\n"
01399                             "HighestSequence: %ld\r\n"
01400                             "SequenceNumberCycles: %ld\r\n"
01401                             "IAJitter: %u\r\n"
01402                             "LastSR: %lu.%010lu\r\n"
01403                             "DLSR: %4.4f(sec)\r\n"
01404                             "RTT: %llu(sec)\r\n",
01405                             ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port),
01406                             pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
01407                             rc,
01408                             rtcpheader[i + 1],
01409                             (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24),
01410                             rtp->rtcp->reported_lost,
01411                             (long) (ntohl(rtcpheader[i + 2]) & 0xffff),
01412                             (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16,
01413                             rtp->rtcp->reported_jitter,
01414                             (unsigned long) ntohl(rtcpheader[i + 4]) >> 16, ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096,
01415                             ntohl(rtcpheader[i + 5])/65536.0,
01416                             (unsigned long long)rtt);
01417          } else {
01418             manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From: %s:%d\r\n"
01419                             "PT: %d(%s)\r\n"
01420                             "ReceptionReports: %d\r\n"
01421                             "SenderSSRC: %u\r\n"
01422                             "FractionLost: %ld\r\n"
01423                             "PacketsLost: %d\r\n"
01424                             "HighestSequence: %ld\r\n"
01425                             "SequenceNumberCycles: %ld\r\n"
01426                             "IAJitter: %u\r\n"
01427                             "LastSR: %lu.%010lu\r\n"
01428                             "DLSR: %4.4f(sec)\r\n",
01429                             ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port),
01430                             pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
01431                             rc,
01432                             rtcpheader[i + 1],
01433                             (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24),
01434                             rtp->rtcp->reported_lost,
01435                             (long) (ntohl(rtcpheader[i + 2]) & 0xffff),
01436                             (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16,
01437                             rtp->rtcp->reported_jitter,
01438                             (unsigned long) ntohl(rtcpheader[i + 4]) >> 16,
01439                             ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096,
01440                             ntohl(rtcpheader[i + 5])/65536.0);
01441          }
01442          break;
01443       case RTCP_PT_FUR:
01444          if (rtcp_debug_test_addr(&sock_in))
01445             ast_verbose("Received an RTCP Fast Update Request\n");
01446          rtp->f.frametype = AST_FRAME_CONTROL;
01447          rtp->f.subclass = AST_CONTROL_VIDUPDATE;
01448          rtp->f.datalen = 0;
01449          rtp->f.samples = 0;
01450          rtp->f.mallocd = 0;
01451          rtp->f.src = "RTP";
01452          f = &rtp->f;
01453          break;
01454       case RTCP_PT_SDES:
01455          if (rtcp_debug_test_addr(&sock_in))
01456             ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
01457          break;
01458       case RTCP_PT_BYE:
01459          if (rtcp_debug_test_addr(&sock_in))
01460             ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
01461          break;
01462       default:
01463          ast_debug(1, "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));
01464          break;
01465       }
01466       position += (length + 1);
01467    }
01468    rtp->rtcp->rtcp_info = 1;  
01469    return f;
01470 }

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

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

03305 {
03306    struct ast_rtp *rtp = data;
03307    int res;
03308 
03309    rtp->rtcp->sendfur = 1;
03310    res = ast_rtcp_write(data);
03311    
03312    return res;
03313 }

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

Referenced by process_sdp().

00502 {
00503    return sizeof(struct ast_rtp);
00504 }

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

References AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_check_hangup(), ast_codec_pref_getsize(), ast_debug, ast_log(), AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, ast_set_flag, ast_test_flag, ast_verb, 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_trtp_info, ast_rtp_protocol::get_vrtp_info, LOG_WARNING, ast_channel::name, ast_rtp::pref, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel_tech::send_digit_begin, ast_channel::tech, and ast_channel::tech_pvt.

04393 {
04394    struct ast_rtp *p0 = NULL, *p1 = NULL;    /* Audio RTP Channels */
04395    struct ast_rtp *vp0 = NULL, *vp1 = NULL;  /* Video RTP channels */
04396    struct ast_rtp *tp0 = NULL, *tp1 = NULL;  /* Text RTP channels */
04397    struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL;
04398    enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED, text_p0_res = AST_RTP_GET_FAILED;
04399    enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED, text_p1_res = AST_RTP_GET_FAILED;
04400    enum ast_bridge_result res = AST_BRIDGE_FAILED;
04401    int codec0 = 0, codec1 = 0;
04402    void *pvt0 = NULL, *pvt1 = NULL;
04403 
04404    /* Lock channels */
04405    ast_channel_lock(c0);
04406    while (ast_channel_trylock(c1)) {
04407       ast_channel_unlock(c0);
04408       usleep(1);
04409       ast_channel_lock(c0);
04410    }
04411 
04412    /* Ensure neither channel got hungup during lock avoidance */
04413    if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
04414       ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name);
04415       ast_channel_unlock(c0);
04416       ast_channel_unlock(c1);
04417       return AST_BRIDGE_FAILED;
04418    }
04419       
04420    /* Find channel driver interfaces */
04421    if (!(pr0 = get_proto(c0))) {
04422       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
04423       ast_channel_unlock(c0);
04424       ast_channel_unlock(c1);
04425       return AST_BRIDGE_FAILED;
04426    }
04427    if (!(pr1 = get_proto(c1))) {
04428       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
04429       ast_channel_unlock(c0);
04430       ast_channel_unlock(c1);
04431       return AST_BRIDGE_FAILED;
04432    }
04433 
04434    /* Get channel specific interface structures */
04435    pvt0 = c0->tech_pvt;
04436    pvt1 = c1->tech_pvt;
04437 
04438    /* Get audio and video interface (if native bridge is possible) */
04439    audio_p0_res = pr0->get_rtp_info(c0, &p0);
04440    video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
04441    text_p0_res = pr0->get_trtp_info ? pr0->get_trtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
04442    audio_p1_res = pr1->get_rtp_info(c1, &p1);
04443    video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
04444    text_p1_res = pr1->get_trtp_info ? pr1->get_trtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
04445 
04446    /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */
04447    if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE))
04448       audio_p0_res = AST_RTP_GET_FAILED;
04449    if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE))
04450       audio_p1_res = AST_RTP_GET_FAILED;
04451 
04452    /* Check if a bridge is possible (partial/native) */
04453    if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) {
04454       /* Somebody doesn't want to play... */
04455       ast_channel_unlock(c0);
04456       ast_channel_unlock(c1);
04457       return AST_BRIDGE_FAILED_NOWARN;
04458    }
04459 
04460    /* If we need to feed DTMF frames into the core then only do a partial native bridge */
04461    if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
04462       ast_set_flag(p0, FLAG_P2P_NEED_DTMF);
04463       audio_p0_res = AST_RTP_TRY_PARTIAL;
04464    }
04465 
04466    if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) {
04467       ast_set_flag(p1, FLAG_P2P_NEED_DTMF);
04468       audio_p1_res = AST_RTP_TRY_PARTIAL;
04469    }
04470 
04471    /* If both sides are not using the same method of DTMF transmission 
04472     * (ie: one is RFC2833, other is INFO... then we can not do direct media. 
04473     * --------------------------------------------------
04474     * | DTMF Mode |  HAS_DTMF  |  Accepts Begin Frames |
04475     * |-----------|------------|-----------------------|
04476     * | Inband    | False      | True                  |
04477     * | RFC2833   | True       | True                  |
04478     * | SIP INFO  | False      | False                 |
04479     * --------------------------------------------------
04480     * However, if DTMF from both channels is being monitored by the core, then
04481     * we can still do packet-to-packet bridging, because passing through the 
04482     * core will handle DTMF mode translation.
04483     */
04484    if ((ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) ||
04485       (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) {
04486       if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) {
04487          ast_channel_unlock(c0);
04488          ast_channel_unlock(c1);
04489          return AST_BRIDGE_FAILED_NOWARN;
04490       }
04491       audio_p0_res = AST_RTP_TRY_PARTIAL;
04492       audio_p1_res = AST_RTP_TRY_PARTIAL;
04493    }
04494 
04495    /* If we need to feed frames into the core don't do a P2P bridge */
04496    if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF)) ||
04497        (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF))) {
04498       ast_channel_unlock(c0);
04499       ast_channel_unlock(c1);
04500       return AST_BRIDGE_FAILED_NOWARN;
04501    }
04502 
04503    /* Get codecs from both sides */
04504    codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0;
04505    codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0;
04506    if (codec0 && codec1 && !(codec0 & codec1)) {
04507       /* Hey, we can't do native bridging if both parties speak different codecs */
04508       ast_debug(3, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1);
04509       ast_channel_unlock(c0);
04510       ast_channel_unlock(c1);
04511       return AST_BRIDGE_FAILED_NOWARN;
04512    }
04513 
04514    /* If either side can only do a partial bridge, then don't try for a true native bridge */
04515    if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) {
04516       struct ast_format_list fmt0, fmt1;
04517 
04518       /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */
04519       if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) {
04520          ast_debug(1, "Cannot packet2packet bridge - raw formats are incompatible\n");
04521          ast_channel_unlock(c0);
04522          ast_channel_unlock(c1);
04523          return AST_BRIDGE_FAILED_NOWARN;
04524       }
04525       /* They must also be using the same packetization */
04526       fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat);
04527       fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat);
04528       if (fmt0.cur_ms != fmt1.cur_ms) {
04529          ast_debug(1, "Cannot packet2packet bridge - packetization settings prevent it\n");
04530          ast_channel_unlock(c0);
04531          ast_channel_unlock(c1);
04532          return AST_BRIDGE_FAILED_NOWARN;
04533       }
04534 
04535       ast_verb(3, "Packet2Packet bridging %s and %s\n", c0->name, c1->name);
04536       res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1);
04537    } else {
04538       ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
04539       res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, tp0, tp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1);
04540    }
04541 
04542    return res;
04543 }

void ast_rtp_change_source ( struct ast_rtp rtp  ) 

Indicate that we need to set the marker bit and change the ssrc.

Definition at line 2650 of file rtp.c.

References ast_debug, ast_random(), ast_rtp::set_marker_bit, and ast_rtp::ssrc.

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

02651 {
02652    if (rtp) {
02653       unsigned int ssrc = ast_random();
02654 
02655       rtp->set_marker_bit = 1;
02656       ast_debug(3, "Changing ssrc from %u to %u due to a source change\n", rtp->ssrc, ssrc);
02657       rtp->ssrc = ssrc;
02658    }
02659 }

int ast_rtp_codec_getformat ( int  pt  ) 

get format from predefined dynamic payload format

Definition at line 3784 of file rtp.c.

References rtpPayloadType::code, and static_RTP_PT.

Referenced by process_sdp_a_audio().

03785 {
03786    if (pt < 0 || pt >= MAX_RTP_PT)
03787       return 0; /* bogus payload type */
03788 
03789    if (static_RTP_PT[pt].isAstFormat)
03790       return static_RTP_PT[pt].code;
03791    else
03792       return 0;
03793 }

struct ast_codec_pref* ast_rtp_codec_getpref ( struct ast_rtp rtp  ) 

Get codec preference.

Definition at line 3779 of file rtp.c.

References ast_rtp::pref.

Referenced by add_codec_to_sdp(), and process_sdp_a_audio().

03780 {
03781    return &rtp->pref;
03782 }

void ast_rtp_codec_setpref ( struct ast_rtp rtp,
struct ast_codec_pref prefs 
)

Set codec preference.

Definition at line 3733 of file rtp.c.

References ast_codec_pref_getsize(), ast_log(), ast_smoother_new(), ast_smoother_reconfigure(), ast_smoother_set_flags(), ast_format_list::cur_ms, ast_format_list::flags, ast_format_list::fr_len, ast_format_list::inc_ms, ast_rtp::lasttxformat, LOG_DEBUG, LOG_WARNING, option_debug, ast_rtp::pref, prefs, and ast_rtp::smoother.

Referenced by __oh323_rtp_create(), check_peer_ok(), create_addr_from_peer(), gtalk_new(), jingle_new(), process_sdp_a_audio(), register_verify(), set_peer_capabilities(), sip_alloc(), start_rtp(), and transmit_response_with_sdp().

03734 {
03735    struct ast_format_list current_format_old, current_format_new;
03736 
03737    /* if no packets have been sent through this session yet, then
03738     *  changing preferences does not require any extra work
03739     */
03740    if (rtp->lasttxformat == 0) {
03741       rtp->pref = *prefs;
03742       return;
03743    }
03744 
03745    current_format_old = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat);
03746 
03747    rtp->pref = *prefs;
03748 
03749    current_format_new = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat);
03750 
03751    /* if the framing desired for the current format has changed, we may have to create
03752     * or adjust the smoother for this session
03753     */
03754    if ((current_format_new.inc_ms != 0) &&
03755        (current_format_new.cur_ms != current_format_old.cur_ms)) {
03756       int new_size = (current_format_new.cur_ms * current_format_new.fr_len) / current_format_new.inc_ms;
03757 
03758       if (rtp->smoother) {
03759          ast_smoother_reconfigure(rtp->smoother, new_size);
03760          if (option_debug) {
03761             ast_log(LOG_DEBUG, "Adjusted smoother to %d ms and %d bytes\n", current_format_new.cur_ms, new_size);
03762          }
03763       } else {
03764          if (!(rtp->smoother = ast_smoother_new(new_size))) {
03765             ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size);
03766             return;
03767          }
03768          if (current_format_new.flags) {
03769             ast_smoother_set_flags(rtp->smoother, current_format_new.flags);
03770          }
03771          if (option_debug) {
03772             ast_log(LOG_DEBUG, "Created smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size);
03773          }
03774       }
03775    }
03776 
03777 }

void ast_rtp_destroy ( struct ast_rtp rtp  ) 

Destroy RTP session

Definition at line 3063 of file rtp.c.

References ast_free, ast_io_remove(), ast_mutex_destroy(), AST_SCHED_DEL, ast_smoother_free(), ast_verbose, EVENT_FLAG_REPORTING, ast_rtcp::expected_prior, ast_rtp::io, ast_rtp::ioid, manager_event, 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_peer_ok(), cleanup_connection(), create_addr_from_peer(), destroy_endpoint(), gtalk_free_pvt(), jingle_free_pvt(), mgcp_hangup(), oh323_alloc(), skinny_hangup(), start_rtp(), unalloc_sub(), and unistim_hangup().

03064 {
03065    if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) {
03066       /*Print some info on the call here */
03067       ast_verbose("  RTP-stats\n");
03068       ast_verbose("* Our Receiver:\n");
03069       ast_verbose("  SSRC:     %u\n", rtp->themssrc);
03070       ast_verbose("  Received packets: %u\n", rtp->rxcount);
03071       ast_verbose("  Lost packets:   %u\n", rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0);
03072       ast_verbose("  Jitter:      %.4f\n", rtp->rxjitter);
03073       ast_verbose("  Transit:     %.4f\n", rtp->rxtransit);
03074       ast_verbose("  RR-count:    %u\n", rtp->rtcp ? rtp->rtcp->rr_count : 0);
03075       ast_verbose("* Our Sender:\n");
03076       ast_verbose("  SSRC:     %u\n", rtp->ssrc);
03077       ast_verbose("  Sent packets:   %u\n", rtp->txcount);
03078       ast_verbose("  Lost packets:   %u\n", rtp->rtcp ? rtp->rtcp->reported_lost : 0);
03079       ast_verbose("  Jitter:      %u\n", rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int)65536.0) : 0);
03080       ast_verbose("  SR-count:    %u\n", rtp->rtcp ? rtp->rtcp->sr_count : 0);
03081       ast_verbose("  RTT:      %f\n", rtp->rtcp ? rtp->rtcp->rtt : 0);
03082    }
03083 
03084    manager_event(EVENT_FLAG_REPORTING, "RTPReceiverStat", "SSRC: %u\r\n"
03085                    "ReceivedPackets: %u\r\n"
03086                    "LostPackets: %u\r\n"
03087                    "Jitter: %.4f\r\n"
03088                    "Transit: %.4f\r\n"
03089                    "RRCount: %u\r\n",
03090                    rtp->themssrc,
03091                    rtp->rxcount,
03092                    rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0,
03093                    rtp->rxjitter,
03094                    rtp->rxtransit,
03095                    rtp->rtcp ? rtp->rtcp->rr_count : 0);
03096    manager_event(EVENT_FLAG_REPORTING, "RTPSenderStat", "SSRC: %u\r\n"
03097                    "SentPackets: %u\r\n"
03098                    "LostPackets: %u\r\n"
03099                    "Jitter: %u\r\n"
03100                    "SRCount: %u\r\n"
03101                    "RTT: %f\r\n",
03102                    rtp->ssrc,
03103                    rtp->txcount,
03104                    rtp->rtcp ? rtp->rtcp->reported_lost : 0,
03105                    rtp->rtcp ? rtp->rtcp->reported_jitter : 0,
03106                    rtp->rtcp ? rtp->rtcp->sr_count : 0,
03107                    rtp->rtcp ? rtp->rtcp->rtt : 0);
03108    if (rtp->smoother)
03109       ast_smoother_free(rtp->smoother);
03110    if (rtp->ioid)
03111       ast_io_remove(rtp->io, rtp->ioid);
03112    if (rtp->s > -1)
03113       close(rtp->s);
03114    if (rtp->rtcp) {
03115       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
03116       close(rtp->rtcp->s);
03117       ast_free(rtp->rtcp);
03118       rtp->rtcp=NULL;
03119    }
03120 #ifdef P2P_INTENSE
03121    ast_mutex_destroy(&rtp->bridge_lock);
03122 #endif
03123    ast_free(rtp);
03124 }

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

References ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_debug, 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_trtp_info, ast_rtp_protocol::get_vrtp_info, LOG_WARNING, ast_channel::name, and ast_rtp_protocol::set_rtp_peer.

02112 {
02113    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
02114    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
02115    struct ast_rtp *tdestp = NULL, *tsrcp = NULL;      /* Text RTP channels */
02116    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
02117    enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED, text_dest_res = AST_RTP_GET_FAILED;
02118    enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED, text_src_res = AST_RTP_GET_FAILED;
02119    int srccodec, destcodec, nat_active = 0;
02120 
02121    /* Lock channels */
02122    ast_channel_lock(c0);
02123    if (c1) {
02124       while (ast_channel_trylock(c1)) {
02125          ast_channel_unlock(c0);
02126          usleep(1);
02127          ast_channel_lock(c0);
02128       }
02129    }
02130 
02131    /* Find channel driver interfaces */
02132    destpr = get_proto(c0);
02133    if (c1)
02134       srcpr = get_proto(c1);
02135    if (!destpr) {
02136       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c0->name);
02137       ast_channel_unlock(c0);
02138       if (c1)
02139          ast_channel_unlock(c1);
02140       return -1;
02141    }
02142    if (!srcpr) {
02143       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c1 ? c1->name : "<unspecified>");
02144       ast_channel_unlock(c0);
02145       if (c1)
02146          ast_channel_unlock(c1);
02147       return -1;
02148    }
02149 
02150    /* Get audio, video  and text interface (if native bridge is possible) */
02151    audio_dest_res = destpr->get_rtp_info(c0, &destp);
02152    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(c0, &vdestp) : AST_RTP_GET_FAILED;
02153    text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(c0, &tdestp) : AST_RTP_GET_FAILED;
02154    if (srcpr) {
02155       audio_src_res = srcpr->get_rtp_info(c1, &srcp);
02156       video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(c1, &vsrcp) : AST_RTP_GET_FAILED;
02157       text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(c1, &tsrcp) : AST_RTP_GET_FAILED;
02158    }
02159 
02160    /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
02161    if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE)) {
02162       /* Somebody doesn't want to play... */
02163       ast_channel_unlock(c0);
02164       if (c1)
02165          ast_channel_unlock(c1);
02166       return -1;
02167    }
02168    if (audio_src_res == AST_RTP_TRY_NATIVE && (video_src_res == AST_RTP_GET_FAILED || video_src_res == AST_RTP_TRY_NATIVE) && srcpr->get_codec)
02169       srccodec = srcpr->get_codec(c1);
02170    else
02171       srccodec = 0;
02172    if (audio_dest_res == AST_RTP_TRY_NATIVE && (video_dest_res == AST_RTP_GET_FAILED || video_dest_res == AST_RTP_TRY_NATIVE) && destpr->get_codec)
02173       destcodec = destpr->get_codec(c0);
02174    else
02175       destcodec = 0;
02176    /* Ensure we have at least one matching codec */
02177    if (srcp && !(srccodec & destcodec)) {
02178       ast_channel_unlock(c0);
02179       ast_channel_unlock(c1);
02180       return 0;
02181    }
02182    /* Consider empty media as non-existent */
02183    if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr)
02184       srcp = NULL;
02185    if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
02186       nat_active = 1;
02187    /* Bridge media early */
02188    if (destpr->set_rtp_peer(c0, srcp, vsrcp, tsrcp, srccodec, nat_active))
02189       ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
02190    ast_channel_unlock(c0);
02191    if (c1)
02192       ast_channel_unlock(c1);
02193    ast_debug(1, "Setting early bridge SDP of '%s' with that of '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
02194    return 0;
02195 }

int ast_rtp_fd ( struct ast_rtp rtp  ) 

Definition at line 725 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(), start_rtp(), and unistim_new().

00726 {
00727    return rtp->s;
00728 }

struct ast_rtp* ast_rtp_get_bridged ( struct ast_rtp rtp  ) 

Definition at line 2704 of file rtp.c.

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

Referenced by __sip_destroy(), ast_rtp_read(), and dialog_needdestroy().

02705 {
02706    struct ast_rtp *bridged = NULL;
02707 
02708    rtp_bridge_lock(rtp);
02709    bridged = rtp->bridged;
02710    rtp_bridge_unlock(rtp);
02711 
02712    return bridged;
02713 }

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

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

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

02335 {
02336    int pt;
02337    
02338    rtp_bridge_lock(rtp);
02339    
02340    *astFormats = *nonAstFormats = 0;
02341    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02342       if (rtp->current_RTP_PT[pt].isAstFormat) {
02343          *astFormats |= rtp->current_RTP_PT[pt].code;
02344       } else {
02345          *nonAstFormats |= rtp->current_RTP_PT[pt].code;
02346       }
02347    }
02348 
02349    rtp_bridge_unlock(rtp);
02350 }

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

Definition at line 2686 of file rtp.c.

References ast_rtp::them.

Referenced by acf_channel_read(), add_sdp(), bridge_native_loop(), check_rtp_timeout(), gtalk_update_stun(), oh323_set_rtp_peer(), process_sdp(), sip_set_rtp_peer(), skinny_set_rtp_peer(), and transmit_modify_with_sdp().

02687 {
02688    if ((them->sin_family != AF_INET) ||
02689       (them->sin_port != rtp->them.sin_port) ||
02690       (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
02691       them->sin_family = AF_INET;
02692       them->sin_port = rtp->them.sin_port;
02693       them->sin_addr = rtp->them.sin_addr;
02694       return 1;
02695    }
02696    return 0;
02697 }

int ast_rtp_get_qos ( struct ast_rtp rtp,
const char *  qos,
char *  buf,
unsigned int  buflen 
)

Get QOS stats on a RTP channel.

Since:
1.6.1

Definition at line 2825 of file rtp.c.

References __ast_rtp_get_qos().

Referenced by acf_channel_read().

02826 {
02827    double value;
02828    int found;
02829 
02830    value = __ast_rtp_get_qos(rtp, qos, &found);
02831 
02832    if (!found)
02833       return -1;
02834 
02835    snprintf(buf, buflen, "%.0lf", value);
02836 
02837    return 0;
02838 }

unsigned int ast_rtp_get_qosvalue ( struct ast_rtp rtp,
enum ast_rtp_qos_vars  value 
)

Return RTP and RTCP QoS values.

Get QoS values from RTP and RTCP data (used in "sip show channelstats")

Definition at line 2759 of file rtp.c.

References ast_log(), AST_RTP_RTT, AST_RTP_RXCOUNT, AST_RTP_RXJITTER, AST_RTP_RXPLOSS, AST_RTP_TXCOUNT, AST_RTP_TXJITTER, AST_RTP_TXPLOSS, ast_rtcp::expected_prior, LOG_DEBUG, option_debug, ast_rtcp::received_prior, ast_rtcp::reported_jitter, ast_rtcp::reported_lost, ast_rtp::rtcp, ast_rtcp::rtt, ast_rtp::rxcount, ast_rtp::rxjitter, and ast_rtp::txcount.

Referenced by show_chanstats_cb().

02760 {
02761    if (rtp == NULL) {
02762       if (option_debug > 1)
02763          ast_log(LOG_DEBUG, "NO RTP Structure? Kidding me? \n");
02764       return 0;
02765    }
02766    if (option_debug > 1 && rtp->rtcp == NULL) {
02767       ast_log(LOG_DEBUG, "NO RTCP structure. Maybe in RTP p2p bridging mode? \n");
02768    }
02769 
02770    switch (value) {
02771    case AST_RTP_TXCOUNT:
02772       return (unsigned int) rtp->txcount;
02773    case AST_RTP_RXCOUNT:
02774       return (unsigned int) rtp->rxcount;
02775    case AST_RTP_TXJITTER:
02776       return (unsigned int) (rtp->rxjitter * 100.0);
02777    case AST_RTP_RXJITTER:
02778       return (unsigned int) (rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int) 65536.0) : 0);
02779    case AST_RTP_RXPLOSS:
02780       return rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0;
02781    case AST_RTP_TXPLOSS:
02782       return rtp->rtcp ? rtp->rtcp->reported_lost : 0;
02783    case AST_RTP_RTT:
02784       return (unsigned int) (rtp->rtcp ? (rtp->rtcp->rtt * 100) : 0);
02785    }
02786    return 0;   /* To make the compiler happy */
02787 }

char* ast_rtp_get_quality ( struct ast_rtp rtp,
struct ast_rtp_quality qual,
enum ast_rtp_quality_type  qtype 
)

Return RTCP quality string.

Parameters:
rtp An rtp structure to get qos information about.
qual An (optional) rtp quality structure that will be filled with the quality information described in the ast_rtp_quality structure. This structure is not dependent on any qtype, so a call for any type of information would yield the same results because ast_rtp_quality is not a data type specific to any qos type.
qtype The quality type you'd like, default should be RTPQOS_SUMMARY which returns basic information about the call. The return from RTPQOS_SUMMARY is basically ast_rtp_quality in a string. The other types are RTPQOS_JITTER, RTPQOS_LOSS and RTPQOS_RTT which will return more specific statistics.
Version:
1.6.1 added qtype parameter

Definition at line 3032 of file rtp.c.

References __ast_rtp_get_quality(), __ast_rtp_get_quality_jitter(), __ast_rtp_get_quality_loss(), __ast_rtp_get_quality_rtt(), 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::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, RTPQOS_JITTER, RTPQOS_LOSS, RTPQOS_RTT, RTPQOS_SUMMARY, 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(), ast_rtp_set_vars(), handle_request_bye(), and sip_hangup().

03033 {
03034    if (qual && rtp) {
03035       qual->local_ssrc   = rtp->ssrc;
03036       qual->local_jitter = rtp->rxjitter;
03037       qual->local_count  = rtp->rxcount;
03038       qual->remote_ssrc  = rtp->themssrc;
03039       qual->remote_count = rtp->txcount;
03040 
03041       if (rtp->rtcp) {
03042          qual->local_lostpackets  = rtp->rtcp->expected_prior - rtp->rtcp->received_prior;
03043          qual->remote_lostpackets = rtp->rtcp->reported_lost;
03044          qual->remote_jitter      = rtp->rtcp->reported_jitter / 65536.0;
03045          qual->rtt                = rtp->rtcp->rtt;
03046       }
03047    }
03048 
03049    switch (qtype) {
03050    case RTPQOS_SUMMARY:
03051       return __ast_rtp_get_quality(rtp);
03052    case RTPQOS_JITTER:
03053       return __ast_rtp_get_quality_jitter(rtp);
03054    case RTPQOS_LOSS:
03055       return __ast_rtp_get_quality_loss(rtp);
03056    case RTPQOS_RTT:
03057       return __ast_rtp_get_quality_rtt(rtp);
03058    }
03059 
03060    return NULL;
03061 }

int ast_rtp_get_rtpholdtimeout ( struct ast_rtp rtp  ) 

Get rtp hold timeout.

Definition at line 785 of file rtp.c.

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

Referenced by check_rtp_timeout().

00786 {
00787    if (rtp->rtptimeout < 0)   /* We're not checking, but remembering the setting (during T.38 transmission) */
00788       return 0;
00789    return rtp->rtpholdtimeout;
00790 }

int ast_rtp_get_rtpkeepalive ( struct ast_rtp rtp  ) 

Get RTP keepalive interval.

Definition at line 793 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by check_rtp_timeout().

00794 {
00795    return rtp->rtpkeepalive;
00796 }

int ast_rtp_get_rtptimeout ( struct ast_rtp rtp  ) 

Get rtp timeout.

Definition at line 777 of file rtp.c.

References ast_rtp::rtptimeout.

Referenced by check_rtp_timeout().

00778 {
00779    if (rtp->rtptimeout < 0)   /* We're not checking, but remembering the setting (during T.38 transmission) */
00780       return 0;
00781    return rtp->rtptimeout;
00782 }

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

Definition at line 2699 of file rtp.c.

References ast_rtp::us.

Referenced by add_sdp(), external_rtp_create(), get_our_media_address(), gtalk_create_candidates(), handle_open_receive_channel_ack_message(), jingle_create_candidates(), oh323_set_rtp_peer(), skinny_set_rtp_peer(), and start_rtp().

02700 {
02701    *us = rtp->us;
02702 }

int ast_rtp_getnat ( struct ast_rtp rtp  ) 

Definition at line 813 of file rtp.c.

References ast_test_flag, and FLAG_NAT_ACTIVE.

Referenced by sip_get_rtp_peer().

00814 {
00815    return ast_test_flag(rtp, FLAG_NAT_ACTIVE);
00816 }

void ast_rtp_init ( void   ) 

Initialize the RTP system in Asterisk.

Definition at line 4935 of file rtp.c.

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

Referenced by main().

04936 {
04937    ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
04938    __ast_rtp_reload(0);
04939 }

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

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, 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(), add_sdp(), add_tcodec_to_sdp(), add_vcodec_to_sdp(), ast_rtp_sendcng(), ast_rtp_senddigit_begin(), ast_rtp_write(), bridge_p2p_rtp_write(), and start_rtp().

02375 {
02376    int pt = 0;
02377 
02378    rtp_bridge_lock(rtp);
02379 
02380    if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
02381       code == rtp->rtp_lookup_code_cache_code) {
02382       /* Use our cached mapping, to avoid the overhead of the loop below */
02383       pt = rtp->rtp_lookup_code_cache_result;
02384       rtp_bridge_unlock(rtp);
02385       return pt;
02386    }
02387 
02388    /* Check the dynamic list first */
02389    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02390       if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
02391          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
02392          rtp->rtp_lookup_code_cache_code = code;
02393          rtp->rtp_lookup_code_cache_result = pt;
02394          rtp_bridge_unlock(rtp);
02395          return pt;
02396       }
02397    }
02398 
02399    /* Then the static list */
02400    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02401       if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) {
02402          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
02403          rtp->rtp_lookup_code_cache_code = code;
02404          rtp->rtp_lookup_code_cache_result = pt;
02405          rtp_bridge_unlock(rtp);
02406          return pt;
02407       }
02408    }
02409 
02410    rtp_bridge_unlock(rtp);
02411 
02412    return -1;
02413 }

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

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

Referenced by process_sdp().

02436 {
02437    int format;
02438    unsigned len;
02439    char *end = buf;
02440    char *start = buf;
02441 
02442    if (!buf || !size)
02443       return NULL;
02444 
02445    snprintf(end, size, "0x%x (", capability);
02446 
02447    len = strlen(end);
02448    end += len;
02449    size -= len;
02450    start = end;
02451 
02452    for (format = 1; format < AST_RTP_MAX; format <<= 1) {
02453       if (capability & format) {
02454          const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options);
02455 
02456          snprintf(end, size, "%s|", name);
02457          len = strlen(end);
02458          end += len;
02459          size -= len;
02460       }
02461    }
02462 
02463    if (start == end)
02464       ast_copy_string(start, "nothing)", size); 
02465    else if (size > 1)
02466       *(end -1) = ')';
02467    
02468    return buf;
02469 }

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

References ARRAY_LEN, 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(), add_tcodec_to_sdp(), add_vcodec_to_sdp(), ast_rtp_lookup_mime_multiple(), transmit_connect_with_sdp(), and transmit_modify_with_sdp().

02417 {
02418    unsigned int i;
02419 
02420    for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
02421       if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
02422          if (isAstFormat &&
02423              (code == AST_FORMAT_G726_AAL2) &&
02424              (options & AST_RTP_OPT_G726_NONSTANDARD))
02425             return "G726-32";
02426          else
02427             return mimeTypes[i].subtype;
02428       }
02429    }
02430 
02431    return "";
02432 }

struct rtpPayloadType ast_rtp_lookup_pt ( struct ast_rtp rtp,
int  pt 
)

Mapping between RTP payload format codes and Asterisk codes:.

Definition at line 2352 of file rtp.c.

References rtpPayloadType::isAstFormat, MAX_RTP_PT, rtp_bridge_lock(), rtp_bridge_unlock(), and static_RTP_PT.

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

02353 {
02354    struct rtpPayloadType result;
02355 
02356    result.isAstFormat = result.code = 0;
02357 
02358    if (pt < 0 || pt >= MAX_RTP_PT) 
02359       return result; /* bogus payload type */
02360 
02361    /* Start with negotiated codecs */
02362    rtp_bridge_lock(rtp);
02363    result = rtp->current_RTP_PT[pt];
02364    rtp_bridge_unlock(rtp);
02365 
02366    /* If it doesn't exist, check our static RTP type list, just in case */
02367    if (!result.code) 
02368       result = static_RTP_PT[pt];
02369 
02370    return result;
02371 }

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

Definition at line 2197 of file rtp.c.

References ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_debug, 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_trtp_info, ast_rtp_protocol::get_vrtp_info, LOG_WARNING, ast_channel::name, and ast_rtp_protocol::set_rtp_peer.

Referenced by dial_exec_full(), and do_forward().

02198 {
02199    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
02200    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
02201    struct ast_rtp *tdestp = NULL, *tsrcp = NULL;      /* Text RTP channels */
02202    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
02203    enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED, text_dest_res = AST_RTP_GET_FAILED;
02204    enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED, text_src_res = AST_RTP_GET_FAILED; 
02205    int srccodec, destcodec;
02206 
02207    /* Lock channels */
02208    ast_channel_lock(dest);
02209    while (ast_channel_trylock(src)) {
02210       ast_channel_unlock(dest);
02211       usleep(1);
02212       ast_channel_lock(dest);
02213    }
02214 
02215    /* Find channel driver interfaces */
02216    if (!(destpr = get_proto(dest))) {
02217       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", dest->name);
02218       ast_channel_unlock(dest);
02219       ast_channel_unlock(src);
02220       return 0;
02221    }
02222    if (!(srcpr = get_proto(src))) {
02223       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", src->name);
02224       ast_channel_unlock(dest);
02225       ast_channel_unlock(src);
02226       return 0;
02227    }
02228 
02229    /* Get audio and video interface (if native bridge is possible) */
02230    audio_dest_res = destpr->get_rtp_info(dest, &destp);
02231    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED;
02232    text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(dest, &tdestp) : AST_RTP_GET_FAILED;
02233    audio_src_res = srcpr->get_rtp_info(src, &srcp);
02234    video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED;
02235    text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(src, &tsrcp) : AST_RTP_GET_FAILED;
02236 
02237    /* Ensure we have at least one matching codec */
02238    if (srcpr->get_codec)
02239       srccodec = srcpr->get_codec(src);
02240    else
02241       srccodec = 0;
02242    if (destpr->get_codec)
02243       destcodec = destpr->get_codec(dest);
02244    else
02245       destcodec = 0;
02246 
02247    /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
02248    if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE) || audio_src_res != AST_RTP_TRY_NATIVE || (video_src_res != AST_RTP_GET_FAILED && video_src_res != AST_RTP_TRY_NATIVE) || !(srccodec & destcodec)) {
02249       /* Somebody doesn't want to play... */
02250       ast_channel_unlock(dest);
02251       ast_channel_unlock(src);
02252       return 0;
02253    }
02254    ast_rtp_pt_copy(destp, srcp);
02255    if (vdestp && vsrcp)
02256       ast_rtp_pt_copy(vdestp, vsrcp);
02257    if (tdestp && tsrcp)
02258       ast_rtp_pt_copy(tdestp, tsrcp);
02259    if (media) {
02260       /* Bridge early */
02261       if (destpr->set_rtp_peer(dest, srcp, vsrcp, tsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
02262          ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name);
02263    }
02264    ast_channel_unlock(dest);
02265    ast_channel_unlock(src);
02266    ast_debug(1, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name);
02267    return 1;
02268 }

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

References ast_rtp_new_with_bindaddr(), io, and sched.

02630 {
02631    struct in_addr ia;
02632 
02633    memset(&ia, 0, sizeof(ia));
02634    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
02635 }

void ast_rtp_new_init ( struct ast_rtp rtp  ) 

Initialize a new RTP structure.

reload rtp configuration

Definition at line 2520 of file rtp.c.

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

Referenced by ast_rtp_new_with_bindaddr(), and process_sdp().

02521 {
02522 #ifdef P2P_INTENSE
02523    ast_mutex_init(&rtp->bridge_lock);
02524 #endif
02525 
02526    rtp->them.sin_family = AF_INET;
02527    rtp->us.sin_family = AF_INET;
02528    rtp->ssrc = ast_random();
02529    rtp->seqno = ast_random() & 0xffff;
02530    ast_set_flag(rtp, FLAG_HAS_DTMF);
02531    rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN);
02532 }

void ast_rtp_new_source ( struct ast_rtp rtp  ) 

Indicate that we need to set the marker bit.

Definition at line 2642 of file rtp.c.

References ast_debug, and ast_rtp::set_marker_bit.

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

02643 {
02644    if (rtp) {
02645       rtp->set_marker_bit = 1;
02646       ast_debug(3, "Setting the marker bit due to a source update\n");
02647    }
02648 }

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

References ast_calloc, ast_log(), ast_random(), ast_rtcp_new(), ast_rtp_new_init(), errno, LOG_ERROR, rtp_socket(), and sched.

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

02535 {
02536    struct ast_rtp *rtp;
02537    int x;
02538    int startplace;
02539    
02540    if (!(rtp = ast_calloc(1, sizeof(*rtp))))
02541       return NULL;
02542 
02543    ast_rtp_new_init(rtp);
02544 
02545    rtp->s = rtp_socket("RTP");
02546    if (rtp->s < 0)
02547       goto fail;
02548    if (sched && rtcpenable) {
02549       rtp->sched = sched;
02550       rtp->rtcp = ast_rtcp_new();
02551    }
02552    
02553    /*
02554     * Try to bind the RTP port, x, and possibly the RTCP port, x+1 as well.
02555     * Start from a random (even, by RTP spec) port number, and
02556     * iterate until success or no ports are available.
02557     * Note that the requirement of RTP port being even, or RTCP being the
02558     * next one, cannot be enforced in presence of a NAT box because the
02559     * mapping is not under our control.
02560     */
02561    x = (rtpend == rtpstart) ? rtpstart : (ast_random() % (rtpend - rtpstart)) + rtpstart;
02562    x = x & ~1;    /* make it an even number */
02563    startplace = x;      /* remember the starting point */
02564    /* this is constant across the loop */
02565    rtp->us.sin_addr = addr;
02566    if (rtp->rtcp)
02567       rtp->rtcp->us.sin_addr = addr;
02568    for (;;) {
02569       rtp->us.sin_port = htons(x);
02570       if (!bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) {
02571          /* bind succeeded, if no rtcp then we are done */
02572          if (!rtp->rtcp)
02573             break;
02574          /* have rtcp, try to bind it */
02575          rtp->rtcp->us.sin_port = htons(x + 1);
02576          if (!bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))
02577             break;   /* success again, we are really done */
02578          /*
02579           * RTCP bind failed, so close and recreate the
02580           * already bound RTP socket for the next round.
02581           */
02582          close(rtp->s);
02583          rtp->s = rtp_socket("RTP");
02584          if (rtp->s < 0)
02585             goto fail;
02586       }
02587       /*
02588        * If we get here, there was an error in one of the bind()
02589        * calls, so make sure it is nothing unexpected.
02590        */
02591       if (errno != EADDRINUSE) {
02592          /* We got an error that wasn't expected, abort! */
02593          ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno));
02594          goto fail;
02595       }
02596       /*
02597        * One of the ports is in use. For the next iteration,
02598        * increment by two and handle wraparound.
02599        * If we reach the starting point, then declare failure.
02600        */
02601       x += 2;
02602       if (x > rtpend)
02603          x = (rtpstart + 1) & ~1;
02604       if (x == startplace) {
02605          ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n");
02606          goto fail;
02607       }
02608    }
02609    rtp->sched = sched;
02610    rtp->io = io;
02611    if (callbackmode) {
02612       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
02613       ast_set_flag(rtp, FLAG_CALLBACK_MODE);
02614    }
02615    ast_rtp_pt_default(rtp);
02616    return rtp;
02617 
02618 fail:
02619    if (rtp->s >= 0)
02620       close(rtp->s);
02621    if (rtp->rtcp) {
02622       close(rtp->rtcp->s);
02623       ast_free(rtp->rtcp);
02624    }
02625    ast_free(rtp);
02626    return NULL;
02627 }

int ast_rtp_proto_register ( struct ast_rtp_protocol proto  ) 

Register an RTP channel client.

Definition at line 3890 of file rtp.c.

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

Referenced by load_module().

03891 {
03892    struct ast_rtp_protocol *cur;
03893 
03894    AST_RWLIST_WRLOCK(&protos);
03895    AST_RWLIST_TRAVERSE(&protos, cur, list) { 
03896       if (!strcmp(cur->type, proto->type)) {
03897          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
03898          AST_RWLIST_UNLOCK(&protos);
03899          return -1;
03900       }
03901    }
03902    AST_RWLIST_INSERT_HEAD(&protos, proto, list);
03903    AST_RWLIST_UNLOCK(&protos);
03904    
03905    return 0;
03906 }

void ast_rtp_proto_unregister ( struct ast_rtp_protocol proto  ) 

Unregister an RTP channel client.

Definition at line 3882 of file rtp.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by load_module(), and unload_module().

03883 {
03884    AST_RWLIST_WRLOCK(&protos);
03885    AST_RWLIST_REMOVE(&protos, proto, list);
03886    AST_RWLIST_UNLOCK(&protos);
03887 }

void ast_rtp_pt_clear ( struct ast_rtp rtp  ) 

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

Definition at line 2035 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, 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 gtalk_alloc(), and process_sdp().

02036 {
02037    int i;
02038 
02039    if (!rtp)
02040       return;
02041 
02042    rtp_bridge_lock(rtp);
02043 
02044    for (i = 0; i < MAX_RTP_PT; ++i) {
02045       rtp->current_RTP_PT[i].isAstFormat = 0;
02046       rtp->current_RTP_PT[i].code = 0;
02047    }
02048 
02049    rtp->rtp_lookup_code_cache_isAstFormat = 0;
02050    rtp->rtp_lookup_code_cache_code = 0;
02051    rtp->rtp_lookup_code_cache_result = 0;
02052 
02053    rtp_bridge_unlock(rtp);
02054 }

void ast_rtp_pt_copy ( struct ast_rtp dest,
struct ast_rtp src 
)

Copy payload types between RTP structures.

Definition at line 2075 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, 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 ast_rtp_make_compatible(), and process_sdp().

02076 {
02077    unsigned int i;
02078 
02079    rtp_bridge_lock(dest);
02080    rtp_bridge_lock(src);
02081 
02082    for (i = 0; i < MAX_RTP_PT; ++i) {
02083       dest->current_RTP_PT[i].isAstFormat = 
02084          src->current_RTP_PT[i].isAstFormat;
02085       dest->current_RTP_PT[i].code = 
02086          src->current_RTP_PT[i].code; 
02087    }
02088    dest->rtp_lookup_code_cache_isAstFormat = 0;
02089    dest->rtp_lookup_code_cache_code = 0;
02090    dest->rtp_lookup_code_cache_result = 0;
02091 
02092    rtp_bridge_unlock(src);
02093    rtp_bridge_unlock(dest);
02094 }

void ast_rtp_pt_default ( struct ast_rtp rtp  ) 

Set payload types to defaults.

Definition at line 2056 of file rtp.c.

References rtpPayloadType::code, ast_rtp::current_RTP_PT, rtpPayloadType::isAstFormat, MAX_RTP_PT, rtp_bridge_lock(), rtp_bridge_unlock(), ast_rtp::rtp_lookup_code_cache_code, ast_rtp::rtp_lookup_code_cache_isAstFormat, ast_rtp::rtp_lookup_code_cache_result, and static_RTP_PT.

02057 {
02058    int i;
02059 
02060    rtp_bridge_lock(rtp);
02061 
02062    /* Initialize to default payload types */
02063    for (i = 0; i < MAX_RTP_PT; ++i) {
02064       rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
02065       rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
02066    }
02067 
02068    rtp->rtp_lookup_code_cache_isAstFormat = 0;
02069    rtp->rtp_lookup_code_cache_code = 0;
02070    rtp->rtp_lookup_code_cache_result = 0;
02071 
02072    rtp_bridge_unlock(rtp);
02073 }

struct ast_frame* ast_rtp_read ( struct ast_rtp rtp  ) 

Definition at line 1581 of file rtp.c.

References ast_rtp::altthem, ast_assert, ast_codec_get_samples(), AST_CONTROL_SRCCHANGE, ast_debug, AST_FORMAT_AUDIO_MASK, ast_format_rate(), AST_FORMAT_SLINEAR, AST_FORMAT_T140, AST_FORMAT_T140RED, AST_FORMAT_VIDEO_MASK, ast_frame_byteswap_be, AST_FRAME_CONTROL, AST_FRAME_DTMF_END, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, AST_FRIENDLY_OFFSET, ast_frisolate(), ast_inet_ntoa(), AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_HEAD_INIT_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_samp2tv(), ast_sched_add(), ast_set_flag, ast_tv(), ast_tvdiff_ms(), ast_verbose, bridge_p2p_rtp_write(), ast_rtp::bridged, calc_rxstamp(), rtpPayloadType::code, create_dtmf_frame(), ast_rtp::cycles, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp::dtmf_duration, ast_rtp::dtmf_timeout, errno, ext, ast_rtp::f, f, FLAG_NAT_ACTIVE, frames, ast_frame::frametype, rtpPayloadType::isAstFormat, ast_rtp::lastevent, ast_rtp::lastrxformat, ast_rtp::lastrxseqno, ast_rtp::lastrxts, ast_frame::len, len(), LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, ast_rtp::nat, ast_frame::offset, option_debug, process_cisco_dtmf(), process_rfc2833(), process_rfc3389(), ast_frame::ptr, ast_rtp::rawdata, ast_rtp::resp, ast_rtp::rtcp, rtp_debug_test_addr(), rtp_get_rate(), 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_rtp::strict_rtp_address, STRICT_RTP_CLOSED, STRICT_RTP_LEARN, ast_rtp::strict_rtp_state, STUN_ACCEPT, stun_handle_packet(), ast_frame::subclass, ast_rtcp::them, ast_rtp::them, ast_rtp::themssrc, ast_frame::ts, and version.

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

01582 {
01583    int res;
01584    struct sockaddr_in sock_in;
01585    socklen_t len;
01586    unsigned int seqno;
01587    int version;
01588    int payloadtype;
01589    int hdrlen = 12;
01590    int padding;
01591    int mark;
01592    int ext;
01593    int cc;
01594    unsigned int ssrc;
01595    unsigned int timestamp;
01596    unsigned int *rtpheader;
01597    struct rtpPayloadType rtpPT;
01598    struct ast_rtp *bridged = NULL;
01599    int prev_seqno;
01600    struct frame_list frames;
01601    
01602    /* If time is up, kill it */
01603    if (rtp->sending_digit)
01604       ast_rtp_senddigit_continuation(rtp);
01605 
01606    len = sizeof(sock_in);
01607    
01608    /* Cache where the header will go */
01609    res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,
01610                0, (struct sockaddr *)&sock_in, &len);
01611 
01612    /* If strict RTP protection is enabled see if we need to learn this address or if the packet should be dropped */
01613    if (rtp->strict_rtp_state == STRICT_RTP_LEARN) {
01614       /* Copy over address that this packet was received on */
01615       memcpy(&rtp->strict_rtp_address, &sock_in, sizeof(rtp->strict_rtp_address));
01616       /* Now move over to actually protecting the RTP port */
01617       rtp->strict_rtp_state = STRICT_RTP_CLOSED;
01618       ast_debug(1, "Learned remote address is %s:%d for strict RTP purposes, now protecting the port.\n", ast_inet_ntoa(rtp->strict_rtp_address.sin_addr), ntohs(rtp->strict_rtp_address.sin_port));
01619    } else if (rtp->strict_rtp_state == STRICT_RTP_CLOSED) {
01620       /* If the address we previously learned doesn't match the address this packet came in on simply drop it */
01621       if ((rtp->strict_rtp_address.sin_addr.s_addr != sock_in.sin_addr.s_addr) || (rtp->strict_rtp_address.sin_port != sock_in.sin_port)) {
01622          ast_debug(1, "Received RTP packet from %s:%d, dropping due to strict RTP protection. Expected it to be from %s:%d\n", ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port), ast_inet_ntoa(rtp->strict_rtp_address.sin_addr), ntohs(rtp->strict_rtp_address.sin_port));
01623          return &ast_null_frame;
01624       }
01625    }
01626 
01627    rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET);
01628    if (res < 0) {
01629       ast_assert(errno != EBADF);
01630       if (errno != EAGAIN) {
01631          ast_log(LOG_WARNING, "RTP Read error: %s.  Hanging up.\n", strerror(errno));
01632          return NULL;
01633       }
01634       return &ast_null_frame;
01635    }
01636    
01637    if (res < hdrlen) {
01638       ast_log(LOG_WARNING, "RTP Read too short\n");
01639       return &ast_null_frame;
01640    }
01641 
01642    /* Get fields */
01643    seqno = ntohl(rtpheader[0]);
01644 
01645    /* Check RTP version */
01646    version = (seqno & 0xC0000000) >> 30;
01647    if (!version) {
01648       /* If the two high bits are 0, this might be a
01649        * STUN message, so process it. stun_handle_packet()
01650        * answers to requests, and it returns STUN_ACCEPT
01651        * if the request is valid.
01652        */
01653       if ((stun_handle_packet(rtp->s, &sock_in, rtp->rawdata + AST_FRIENDLY_OFFSET, res, NULL, NULL) == STUN_ACCEPT) &&
01654          (!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) {
01655          memcpy(&rtp->them, &sock_in, sizeof(rtp->them));
01656       }
01657       return &ast_null_frame;
01658    }
01659 
01660 #if 0 /* Allow to receive RTP stream with closed transmission path */
01661    /* If we don't have the other side's address, then ignore this */
01662    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
01663       return &ast_null_frame;
01664 #endif
01665 
01666    /* Send to whoever send to us if NAT is turned on */
01667    if (rtp->nat) {
01668       if (((rtp->them.sin_addr.s_addr != sock_in.sin_addr.s_addr) ||
01669           (rtp->them.sin_port != sock_in.sin_port)) && 
01670           ((rtp->altthem.sin_addr.s_addr != sock_in.sin_addr.s_addr) ||
01671           (rtp->altthem.sin_port != sock_in.sin_port))) {
01672          rtp->them = sock_in;
01673          if (rtp->rtcp) {
01674             int h = 0;
01675             memcpy(&rtp->rtcp->them, &sock_in, sizeof(rtp->rtcp->them));
01676             h = ntohs(rtp->them.sin_port);
01677             rtp->rtcp->them.sin_port = htons(h + 1);
01678          }
01679          rtp->rxseqno = 0;
01680          ast_set_flag(rtp, FLAG_NAT_ACTIVE);
01681          if (option_debug || rtpdebug)
01682             ast_debug(0, "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));
01683       }
01684    }
01685 
01686    /* If we are bridged to another RTP stream, send direct */
01687    if ((bridged = ast_rtp_get_bridged(rtp)) && !bridge_p2p_rtp_write(rtp, bridged, rtpheader, res, hdrlen))
01688       return &ast_null_frame;
01689 
01690    if (version != 2)
01691       return &ast_null_frame;
01692 
01693    payloadtype = (seqno & 0x7f0000) >> 16;
01694    padding = seqno & (1 << 29);
01695    mark = seqno & (1 << 23);
01696    ext = seqno & (1 << 28);
01697    cc = (seqno & 0xF000000) >> 24;
01698    seqno &= 0xffff;
01699    timestamp = ntohl(rtpheader[1]);
01700    ssrc = ntohl(rtpheader[2]);
01701    
01702    AST_LIST_HEAD_INIT_NOLOCK(&frames);
01703    /* Force a marker bit and change SSRC if the SSRC changes */
01704    if (rtp->rxssrc && rtp->rxssrc != ssrc) {
01705       struct ast_frame *f, srcupdate = {
01706          AST_FRAME_CONTROL,
01707          .subclass = AST_CONTROL_SRCCHANGE,
01708       };
01709 
01710       if (!mark) {
01711          if (option_debug || rtpdebug) {
01712             ast_debug(0, "Forcing Marker bit, because SSRC has changed\n");
01713          }
01714          mark = 1;
01715       }
01716       f = ast_frisolate(&srcupdate);
01717       AST_LIST_INSERT_TAIL(&frames, f, frame_list);
01718    }
01719 
01720    rtp->rxssrc = ssrc;
01721    
01722    if (padding) {
01723       /* Remove padding bytes */
01724       res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1];
01725    }
01726    
01727    if (cc) {
01728       /* CSRC fields present */
01729       hdrlen += cc*4;
01730    }
01731 
01732    if (ext) {
01733       /* RTP Extension present */
01734       hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2;
01735       hdrlen += 4;
01736       if (option_debug) {
01737          int profile;
01738          profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16;
01739          if (profile == 0x505a)
01740             ast_debug(1, "Found Zfone extension in RTP stream - zrtp - not supported.\n");
01741          else
01742             ast_debug(1, "Found unknown RTP Extensions %x\n", profile);
01743       }
01744    }
01745 
01746    if (res < hdrlen) {
01747       ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen);
01748       return AST_LIST_FIRST(&frames) ? AST_LIST_FIRST(&frames) : &ast_null_frame;
01749    }
01750 
01751    rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */
01752 
01753    if (rtp->rxcount==1) {
01754       /* This is the first RTP packet successfully received from source */
01755       rtp->seedrxseqno = seqno;
01756    }
01757 
01758    /* Do not schedule RR if RTCP isn't run */
01759    if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) {
01760       /* Schedule transmission of Receiver Report */
01761       rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
01762    }
01763    if ((int)rtp->lastrxseqno - (int)seqno  > 100) /* if so it would indicate that the sender cycled; allow for misordering */
01764       rtp->cycles += RTP_SEQ_MOD;
01765    
01766    prev_seqno = rtp->lastrxseqno;
01767 
01768    rtp->lastrxseqno = seqno;
01769    
01770    if (!rtp->themssrc)
01771       rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */
01772    
01773    if (rtp_debug_test_addr(&sock_in))
01774       ast_verbose("Got  RTP packet from    %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
01775          ast_inet_ntoa(sock_in.sin_addr), ntohs(sock_in.sin_port), payloadtype, seqno, timestamp,res - hdrlen);
01776 
01777    rtpPT = ast_rtp_lookup_pt(rtp, payloadtype);
01778    if (!rtpPT.isAstFormat) {
01779       struct ast_frame *f = NULL;
01780 
01781       /* This is special in-band data that's not one of our codecs */
01782       if (rtpPT.code == AST_RTP_DTMF) {
01783          /* It's special -- rfc2833 process it */
01784          if (rtp_debug_test_addr(&sock_in)) {
01785             unsigned char *data;
01786             unsigned int event;
01787             unsigned int event_end;
01788             unsigned int duration;
01789             data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen;
01790             event = ntohl(*((unsigned int *)(data)));
01791             event >>= 24;
01792             event_end = ntohl(*((unsigned int *)(data)));
01793             event_end <<= 8;
01794             event_end >>= 24;
01795             duration = ntohl(*((unsigned int *)(data)));
01796             duration &= 0xFFFF;
01797             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(sock_in.sin_addr), ntohs(sock_in.sin_port), payloadtype, seqno, timestamp, res - hdrlen, (mark?1:0), event, ((event_end & 0x80)?1:0), duration);
01798          }
01799          /* process_rfc2833 may need to return multiple frames. We do this
01800           * by passing the pointer to the frame list to it so that the method
01801           * can append frames to the list as needed
01802           */
01803          process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp, &frames);
01804       } else if (rtpPT.code == AST_RTP_CISCO_DTMF) {
01805          /* It's really special -- process it the Cisco way */
01806          if (rtp->lastevent <= seqno || (rtp->lastevent >= 65530 && seqno <= 6)) {
01807             f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
01808             rtp->lastevent = seqno;
01809          }
01810       } else if (rtpPT.code == AST_RTP_CN) {
01811          /* Comfort Noise */
01812          f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
01813       } else {
01814          ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr));
01815       }
01816       if (f) {
01817          AST_LIST_INSERT_TAIL(&frames, f, frame_list);
01818       }
01819       /* Even if no frame was returned by one of the above methods,
01820        * we may have a frame to return in our frame list
01821        */
01822       if (!AST_LIST_EMPTY(&frames)) {
01823          return AST_LIST_FIRST(&frames);
01824       }
01825       return &ast_null_frame;
01826    }
01827    rtp->lastrxformat = rtp->f.subclass = rtpPT.code;
01828    rtp->f.frametype = (rtp->f.subclass & AST_FORMAT_AUDIO_MASK) ? AST_FRAME_VOICE : (rtp->f.subclass & AST_FORMAT_VIDEO_MASK) ? AST_FRAME_VIDEO : AST_FRAME_TEXT;
01829 
01830    rtp->rxseqno = seqno;
01831 
01832    if (rtp->dtmf_timeout && rtp->dtmf_timeout < timestamp) {
01833       rtp->dtmf_timeout = 0;
01834 
01835       if (rtp->resp) {
01836          struct ast_frame *f;
01837          f = create_dtmf_frame(rtp, AST_FRAME_DTMF_END);
01838          f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, rtp_get_rate(f->subclass)), ast_tv(0, 0));
01839          rtp->resp = 0;
01840          rtp->dtmf_timeout = rtp->dtmf_duration = 0;
01841          AST_LIST_INSERT_TAIL(&frames, f, frame_list);
01842          return AST_LIST_FIRST(&frames);
01843       }
01844    }
01845 
01846    /* Record received timestamp as last received now */
01847    rtp->lastrxts = timestamp;
01848 
01849    rtp->f.mallocd = 0;
01850    rtp->f.datalen = res - hdrlen;
01851    rtp->f.data.ptr = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
01852    rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
01853    rtp->f.seqno = seqno;
01854 
01855    if (rtp->f.subclass == AST_FORMAT_T140 && (int)seqno - (prev_seqno+1) > 0 && (int)seqno - (prev_seqno+1) < 10) {
01856         unsigned char *data = rtp->f.data.ptr;
01857         
01858         memmove(rtp->f.data.ptr+3, rtp->f.data.ptr, rtp->f.datalen);
01859         rtp->f.datalen +=3;
01860         *data++ = 0xEF;
01861         *data++ = 0xBF;
01862         *data = 0xBD;
01863    }
01864  
01865    if (rtp->f.subclass == AST_FORMAT_T140RED) {
01866       unsigned char *data = rtp->f.data.ptr;
01867       unsigned char *header_end;
01868       int num_generations;
01869       int header_length;
01870       int length;
01871       int diff =(int)seqno - (prev_seqno+1); /* if diff = 0, no drop*/
01872       int x;
01873 
01874       rtp->f.subclass = AST_FORMAT_T140;
01875       header_end = memchr(data, ((*data) & 0x7f), rtp->f.datalen);
01876       if (header_end == NULL) {
01877          return &ast_null_frame;
01878       }
01879       header_end++;
01880       
01881       header_length = header_end - data;
01882       num_generations = header_length / 4;
01883       length = header_length;
01884 
01885       if (!diff) {
01886          for (x = 0; x < num_generations; x++)
01887             length += data[x * 4 + 3];
01888          
01889          if (!(rtp->f.datalen - length))
01890             return &ast_null_frame;
01891          
01892          rtp->f.data.ptr += length;
01893          rtp->f.datalen -= length;
01894       } else if (diff > num_generations && diff < 10) {
01895          length -= 3;
01896          rtp->f.data.ptr += length;
01897          rtp->f.datalen -= length;
01898          
01899          data = rtp->f.data.ptr;
01900          *data++ = 0xEF;
01901          *data++ = 0xBF;
01902          *data = 0xBD;
01903       } else   {
01904          for ( x = 0; x < num_generations - diff; x++) 
01905             length += data[x * 4 + 3];
01906          
01907          rtp->f.data.ptr += length;
01908          rtp->f.datalen -= length;
01909       }
01910    }
01911 
01912    if (rtp->f.subclass & AST_FORMAT_AUDIO_MASK) {
01913       rtp->f.samples = ast_codec_get_samples(&rtp->f);
01914       if (rtp->f.subclass == AST_FORMAT_SLINEAR) 
01915          ast_frame_byteswap_be(&rtp->f);
01916       calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
01917       /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */
01918       ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO);
01919       rtp->f.ts = timestamp / (rtp_get_rate(rtp->f.subclass) / 1000);
01920       rtp->f.len = rtp->f.samples / ( (ast_format_rate(rtp->f.subclass) == 16000) ? 16 : 8 );
01921    } else if (rtp->f.subclass & AST_FORMAT_VIDEO_MASK) {
01922       /* Video -- samples is # of samples vs. 90000 */
01923       if (!rtp->lastividtimestamp)
01924          rtp->lastividtimestamp = timestamp;
01925       rtp->f.samples = timestamp - rtp->lastividtimestamp;
01926       rtp->lastividtimestamp = timestamp;
01927       rtp->f.delivery.tv_sec = 0;
01928       rtp->f.delivery.tv_usec = 0;
01929       /* Pass the RTP marker bit as bit 0 in the subclass field.
01930        * This is ok because subclass is actually a bitmask, and
01931        * the low bits represent audio formats, that are not
01932        * involved here since we deal with video.
01933        */
01934       if (mark)
01935          rtp->f.subclass |= 0x1;
01936    } else {
01937       /* TEXT -- samples is # of samples vs. 1000 */
01938       if (!rtp->lastitexttimestamp)
01939          rtp->lastitexttimestamp = timestamp;
01940       rtp->f.samples = timestamp - rtp->lastitexttimestamp;
01941       rtp->lastitexttimestamp = timestamp;
01942       rtp->f.delivery.tv_sec = 0;
01943       rtp->f.delivery.tv_usec = 0;
01944    }
01945    rtp->f.src = "RTP";
01946 
01947    AST_LIST_INSERT_TAIL(&frames, &rtp->f, frame_list);
01948    return AST_LIST_FIRST(&frames);
01949 }

int ast_rtp_reload ( void   ) 

Initialize RTP subsystem

Definition at line 4929 of file rtp.c.

References __ast_rtp_reload().

04930 {
04931    return __ast_rtp_reload(1);
04932 }

void ast_rtp_reset ( struct ast_rtp rtp  ) 

Definition at line 2736 of file rtp.c.

References ast_rtp::dtmf_timeout, ast_rtp::dtmfmute, ast_rtp::dtmfsamples, ast_rtp::lastdigitts, ast_rtp::lastevent, ast_rtp::lasteventseqn, ast_rtp::lastitexttimestamp, ast_rtp::lastividtimestamp, ast_rtp::lastotexttimestamp, 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.

02737 {
02738    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
02739    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
02740    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
02741    rtp->lastts = 0;
02742    rtp->lastdigitts = 0;
02743    rtp->lastrxts = 0;
02744    rtp->lastividtimestamp = 0;
02745    rtp->lastovidtimestamp = 0;
02746    rtp->lastitexttimestamp = 0;
02747    rtp->lastotexttimestamp = 0;
02748    rtp->lasteventseqn = 0;
02749    rtp->lastevent = 0;
02750    rtp->lasttxformat = 0;
02751    rtp->lastrxformat = 0;
02752    rtp->dtmf_timeout = 0;
02753    rtp->dtmfsamples = 0;
02754    rtp->seqno = 0;
02755    rtp->rxseqno = 0;
02756 }

int ast_rtp_sendcng ( struct ast_rtp rtp,
int  level 
)

generate comfort noice (CNG)

Definition at line 3579 of file rtp.c.

References ast_inet_ntoa(), ast_log(), AST_RTP_CN, ast_rtp_lookup_code(), ast_tv(), ast_tvadd(), ast_tvnow(), 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 check_rtp_timeout().

03580 {
03581    unsigned int *rtpheader;
03582    int hdrlen = 12;
03583    int res;
03584    int payload;
03585    char data[256];
03586    level = 127 - (level & 0x7f);
03587    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN);
03588 
03589    /* If we have no peer, return immediately */ 
03590    if (!rtp->them.sin_addr.s_addr)
03591       return 0;
03592 
03593    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
03594 
03595    /* Get a pointer to the header */
03596    rtpheader = (unsigned int *)data;
03597    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
03598    rtpheader[1] = htonl(rtp->lastts);
03599    rtpheader[2] = htonl(rtp->ssrc); 
03600    data[12] = level;
03601    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
03602       res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
03603       if (res <0) 
03604          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));
03605       if (rtp_debug_test_addr(&rtp->them))
03606          ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n"
03607                , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen);         
03608          
03609    }
03610    return 0;
03611 }

int ast_rtp_senddigit_begin ( struct ast_rtp rtp,
char  digit 
)

Send begin frames for DTMF.

Definition at line 3146 of file rtp.c.

References ast_inet_ntoa(), ast_log(), AST_RTP_DTMF, ast_rtp_lookup_code(), ast_tv(), ast_tvadd(), ast_tvnow(), ast_verbose, ast_rtp::dtmfmute, errno, ast_rtp::lastdigitts, ast_rtp::lastts, 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().

03147 {
03148    unsigned int *rtpheader;
03149    int hdrlen = 12, res = 0, i = 0, payload = 0;
03150    char data[256];
03151 
03152    if ((digit <= '9') && (digit >= '0'))
03153       digit -= '0';
03154    else if (digit == '*')
03155       digit = 10;
03156    else if (digit == '#')
03157       digit = 11;
03158    else if ((digit >= 'A') && (digit <= 'D'))
03159       digit = digit - 'A' + 12;
03160    else if ((digit >= 'a') && (digit <= 'd'))
03161       digit = digit - 'a' + 12;
03162    else {
03163       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
03164       return 0;
03165    }
03166 
03167    /* If we have no peer, return immediately */ 
03168    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
03169       return 0;
03170 
03171    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF);
03172 
03173    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
03174    rtp->send_duration = 160;
03175    rtp->lastdigitts = rtp->lastts + rtp->send_duration;
03176    
03177    /* Get a pointer to the header */
03178    rtpheader = (unsigned int *)data;
03179    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
03180    rtpheader[1] = htonl(rtp->lastdigitts);
03181    rtpheader[2] = htonl(rtp->ssrc); 
03182 
03183    for (i = 0; i < 2; i++) {
03184       rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
03185       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
03186       if (res < 0) 
03187          ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n",
03188             ast_inet_ntoa(rtp->them.sin_addr),
03189             ntohs(rtp->them.sin_port), strerror(errno));
03190       if (rtp_debug_test_addr(&rtp->them))
03191          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
03192                 ast_inet_ntoa(rtp->them.sin_addr),
03193                 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
03194       /* Increment sequence number */
03195       rtp->seqno++;
03196       /* Increment duration */
03197       rtp->send_duration += 160;
03198       /* Clear marker bit and set seqno */
03199       rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
03200    }
03201 
03202    /* Since we received a begin, we can safely store the digit and disable any compensation */
03203    rtp->sending_digit = 1;
03204    rtp->send_digit = digit;
03205    rtp->send_payload = payload;
03206 
03207    return 0;
03208 }

int ast_rtp_senddigit_end ( struct ast_rtp rtp,
char  digit 
)

void ast_rtp_set_alt_peer ( struct ast_rtp rtp,
struct sockaddr_in *  alt 
)

set potential alternate source for RTP media

Since:
1.4.26
This function may be used to give the RTP stack a hint that there is a potential second source of media. One case where this is used is when the SIP stack receives a REINVITE to which it will be replying with a 491. In such a scenario, the IP and port information in the SDP of that REINVITE lets us know that we may receive media from that source/those sources even though the SIP transaction was unable to be completed successfully

Parameters:
rtp The RTP structure we wish to set up an alternate host/port on
alt The address information for the alternate media source
Return values:
void 

Definition at line 2676 of file rtp.c.

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

Referenced by handle_request_invite().

02677 {
02678    rtp->altthem.sin_port = alt->sin_port;
02679    rtp->altthem.sin_addr = alt->sin_addr;
02680    if (rtp->rtcp) {
02681       rtp->rtcp->altthem.sin_port = htons(ntohs(alt->sin_port) + 1);
02682       rtp->rtcp->altthem.sin_addr = alt->sin_addr;
02683    }
02684 }

void ast_rtp_set_callback ( struct ast_rtp rtp,
ast_rtp_callback  callback 
)

Definition at line 803 of file rtp.c.

References ast_rtp::callback.

Referenced by start_rtp().

00804 {
00805    rtp->callback = callback;
00806 }

void ast_rtp_set_data ( struct ast_rtp rtp,
void *  data 
)

Definition at line 798 of file rtp.c.

References ast_rtp::data.

Referenced by start_rtp().

00799 {
00800    rtp->data = data;
00801 }

void ast_rtp_set_m_type ( struct ast_rtp rtp,
int  pt 
)

Activate payload type.

Definition at line 2274 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_is_answered(), gtalk_newcall(), jingle_newcall(), and process_sdp().

02275 {
02276    if (pt < 0 || pt >= MAX_RTP_PT || static_RTP_PT[pt].code == 0) 
02277       return; /* bogus payload type */
02278 
02279    rtp_bridge_lock(rtp);
02280    rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
02281    rtp_bridge_unlock(rtp);
02282 } 

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

Definition at line 2661 of file rtp.c.

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

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

02662 {
02663    rtp->them.sin_port = them->sin_port;
02664    rtp->them.sin_addr = them->sin_addr;
02665    if (rtp->rtcp) {
02666       int h = ntohs(them->sin_port);
02667       rtp->rtcp->them.sin_port = htons(h + 1);
02668       rtp->rtcp->them.sin_addr = them->sin_addr;
02669    }
02670    rtp->rxseqno = 0;
02671    /* If strict RTP protection is enabled switch back to the learn state so we don't drop packets from above */
02672    if (strictrtp)
02673       rtp->strict_rtp_state = STRICT_RTP_LEARN;
02674 }

void ast_rtp_set_rtpholdtimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp hold timeout.

Definition at line 765 of file rtp.c.

References ast_rtp::rtpholdtimeout.

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

00766 {
00767    rtp->rtpholdtimeout = timeout;
00768 }

void ast_rtp_set_rtpkeepalive ( struct ast_rtp rtp,
int  period 
)

set RTP keepalive interval

Definition at line 771 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by create_addr_from_peer(), and sip_alloc().

00772 {
00773    rtp->rtpkeepalive = period;
00774 }

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.

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

Definition at line 2301 of file rtp.c.

References ARRAY_LEN, 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(), rtp_bridge_unlock(), subtype, and type.

Referenced by __oh323_rtp_create(), gtalk_is_answered(), gtalk_newcall(), jingle_newcall(), process_sdp(), process_sdp_a_audio(), process_sdp_a_text(), process_sdp_a_video(), set_dtmf_payload(), and setup_rtp_connection().

02304 {
02305    unsigned int i;
02306    int found = 0;
02307 
02308    if (pt < 0 || pt >= MAX_RTP_PT) 
02309       return -1; /* bogus payload type */
02310    
02311    rtp_bridge_lock(rtp);
02312 
02313    for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
02314       if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
02315           strcasecmp(mimeType, mimeTypes[i].type) == 0) {
02316          found = 1;
02317          rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
02318          if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) &&
02319              mimeTypes[i].payloadType.isAstFormat &&
02320              (options & AST_RTP_OPT_G726_NONSTANDARD))
02321             rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2;
02322          break;
02323       }
02324    }
02325 
02326    rtp_bridge_unlock(rtp);
02327 
02328    return (found ? 0 : -1);
02329 } 

void ast_rtp_set_rtptimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp timeout.

Definition at line 759 of file rtp.c.

References ast_rtp::rtptimeout.

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

00760 {
00761    rtp->rtptimeout = timeout;
00762 }

void ast_rtp_set_rtptimers_onhold ( struct ast_rtp rtp  ) 

Definition at line 752 of file rtp.c.

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

Referenced by handle_response_invite().

00753 {
00754    rtp->rtptimeout = (-1) * rtp->rtptimeout;
00755    rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout;
00756 }

void ast_rtp_set_vars ( struct ast_channel chan,
struct ast_rtp rtp 
)

Set RTPAUDIOQOS(...) variables on a channel when it is being hung up.

Since:
1.6.1

Definition at line 2840 of file rtp.c.

References ast_bridged_channel(), ast_rtp_get_quality(), chan, pbx_builtin_setvar_helper(), RTPQOS_JITTER, RTPQOS_LOSS, RTPQOS_RTT, and RTPQOS_SUMMARY.

Referenced by handle_request_bye(), and sip_hangup().

02840                                                                      {
02841    char *audioqos;
02842    char *audioqos_jitter;
02843    char *audioqos_loss;
02844    char *audioqos_rtt;
02845    struct ast_channel *bridge;
02846 
02847    if (!rtp || !chan)
02848       return;
02849 
02850    bridge = ast_bridged_channel(chan);
02851 
02852    audioqos        = ast_rtp_get_quality(rtp, NULL, RTPQOS_SUMMARY);
02853    audioqos_jitter = ast_rtp_get_quality(rtp, NULL, RTPQOS_JITTER);
02854    audioqos_loss   = ast_rtp_get_quality(rtp, NULL, RTPQOS_LOSS);
02855    audioqos_rtt    = ast_rtp_get_quality(rtp, NULL, RTPQOS_RTT);
02856 
02857    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOS", audioqos);
02858    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSJITTER", audioqos_jitter);
02859    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSLOSS", audioqos_loss);
02860    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSRTT", audioqos_rtt);
02861 
02862    if (!bridge)
02863       return;
02864 
02865    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSBRIDGED", audioqos);
02866    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSJITTERBRIDGED", audioqos_jitter);
02867    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSLOSSBRIDGED", audioqos_loss);
02868    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSRTTBRIDGED", audioqos_rtt);
02869 }

void ast_rtp_setdtmf ( struct ast_rtp rtp,
int  dtmf 
)

Indicate whether this RTP session is carrying DTMF or not.

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

00819 {
00820    ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF);
00821 }

void ast_rtp_setdtmfcompensate ( struct ast_rtp rtp,
int  compensate 
)

Compensate for devices that send RFC2833 packets all at once.

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

00824 {
00825    ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE);
00826 }

void ast_rtp_setnat ( struct ast_rtp rtp,
int  nat 
)

Definition at line 808 of file rtp.c.

References ast_rtp::nat.

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

00809 {
00810    rtp->nat = nat;
00811 }

int ast_rtp_setqos ( struct ast_rtp rtp,
int  tos,
int  cos,
char *  desc 
)

Definition at line 2637 of file rtp.c.

References ast_netsock_set_qos(), and ast_rtp::s.

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

02638 {
02639    return ast_netsock_set_qos(rtp->s, type_of_service, class_of_service, desc);
02640 }

void ast_rtp_setstun ( struct ast_rtp rtp,
int  stun_enable 
)

Enable STUN capability.

Definition at line 828 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_STUN.

Referenced by gtalk_new().

00829 {
00830    ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN);
00831 }

void ast_rtp_stop ( struct ast_rtp rtp  ) 

Stop RTP session, do not destroy structure

Definition at line 2715 of file rtp.c.

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

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

02716 {
02717    if (rtp->rtcp) {
02718       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02719    }
02720    if (rtp->red) {
02721       AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
02722       free(rtp->red);
02723       rtp->red = NULL;
02724    }
02725 
02726    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
02727    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
02728    if (rtp->rtcp) {
02729       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
02730       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
02731    }
02732    
02733    ast_clear_flag(rtp, FLAG_P2P_SENT_MARK);
02734 }

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

Send STUN request for an RTP socket Deprecated, this is just a wrapper for ast_rtp_stun_request().

Definition at line 707 of file rtp.c.

References ast_stun_request(), and ast_rtp::s.

Referenced by gtalk_update_stun(), and jingle_update_stun().

00708 {
00709    ast_stun_request(rtp->s, suggestion, username, NULL);
00710 }

void ast_rtp_unset_m_type ( struct ast_rtp rtp,
int  pt 
)

clear payload type

Definition at line 2286 of file rtp.c.

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

Referenced by process_sdp_a_audio(), and process_sdp_a_video().

02287 {
02288    if (pt < 0 || pt >= MAX_RTP_PT)
02289       return; /* bogus payload type */
02290 
02291    rtp_bridge_lock(rtp);
02292    rtp->current_RTP_PT[pt].isAstFormat = 0;
02293    rtp->current_RTP_PT[pt].code = 0;
02294    rtp_bridge_unlock(rtp);
02295 }

int ast_rtp_write ( struct ast_rtp rtp,
struct ast_frame f 
)

Definition at line 3795 of file rtp.c.

References ast_codec_pref_getsize(), ast_debug, AST_FORMAT_G723_1, AST_FORMAT_SPEEX, AST_FRAME_TEXT, 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::datalen, f, ast_format_list::flags, ast_format_list::fr_len, ast_frame::frametype, ast_format_list::inc_ms, ast_rtp::lasttxformat, LOG_WARNING, ast_frame::offset, ast_rtp::pref, ast_rtp::red, red_t140_to_red(), ast_rtp::smoother, ast_frame::subclass, and ast_rtp::them.

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

03796 {
03797    struct ast_frame *f;
03798    int codec;
03799    int hdrlen = 12;
03800    int subclass;
03801    
03802 
03803    /* If we have no peer, return immediately */ 
03804    if (!rtp->them.sin_addr.s_addr)
03805       return 0;
03806 
03807    /* If there is no data length, return immediately */
03808    if (!_f->datalen && !rtp->red)
03809       return 0;
03810    
03811    /* Make sure we have enough space for RTP header */
03812    if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO) && (_f->frametype != AST_FRAME_TEXT)) {
03813       ast_log(LOG_WARNING, "RTP can only send voice, video and text\n");
03814       return -1;
03815    }
03816 
03817    if (rtp->red) {
03818       /* return 0; */
03819       /* no primary data or generations to send */
03820       if ((_f = red_t140_to_red(rtp->red)) == NULL) 
03821          return 0;
03822    }
03823 
03824    /* The bottom bit of a video subclass contains the marker bit */
03825    subclass = _f->subclass;
03826    if (_f->frametype == AST_FRAME_VIDEO)
03827       subclass &= ~0x1;
03828 
03829    codec = ast_rtp_lookup_code(rtp, 1, subclass);
03830    if (codec < 0) {
03831       ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass));
03832       return -1;
03833    }
03834 
03835    if (rtp->lasttxformat != subclass) {
03836       /* New format, reset the smoother */
03837       ast_debug(1, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
03838       rtp->lasttxformat = subclass;
03839       if (rtp->smoother)
03840          ast_smoother_free(rtp->smoother);
03841       rtp->smoother = NULL;
03842    }
03843 
03844    if (!rtp->smoother && subclass != AST_FORMAT_SPEEX && subclass != AST_FORMAT_G723_1) {
03845       struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass);
03846       if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */
03847          if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
03848             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));
03849             return -1;
03850          }
03851          if (fmt.flags)
03852             ast_smoother_set_flags(rtp->smoother, fmt.flags);
03853          ast_debug(1, "Created smoother: format: %d ms: %d len: %d\n", subclass, fmt.cur_ms, ((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms));
03854       }
03855    }
03856    if (rtp->smoother) {
03857       if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) {
03858          ast_smoother_feed_be(rtp->smoother, _f);
03859       } else {
03860          ast_smoother_feed(rtp->smoother, _f);
03861       }
03862 
03863       while ((f = ast_smoother_read(rtp->smoother)) && (f->data.ptr)) {
03864          ast_rtp_raw_write(rtp, f, codec);
03865       }
03866    } else {
03867       /* Don't buffer outgoing frames; send them one-per-packet: */
03868       if (_f->offset < hdrlen) 
03869          f = ast_frdup(_f);   /*! \bug XXX this might never be free'd. Why do we do this? */
03870       else
03871          f = _f;
03872       if (f->data.ptr)
03873          ast_rtp_raw_write(rtp, f, codec);
03874       if (f != _f)
03875          ast_frfree(f);
03876    }
03877       
03878    return 0;
03879 }

int ast_stun_request ( int  s,
struct sockaddr_in *  dst,
const char *  username,
struct sockaddr_in *  answer 
)

Generic STUN request send a generic stun request to the server specified.

Parameters:
s the socket used to send the request
dst the address of the STUN server
username if non null, add the username in the request
answer if non null, the function waits for a response and puts here the externally visible address.
Returns:
0 on success, other values on error.

Definition at line 641 of file rtp.c.

References append_attr_string(), ast_log(), ast_select(), stun_attr::attr, LOG_WARNING, STUN_BINDREQ, stun_get_mapped(), stun_handle_packet(), stun_req_id(), stun_send(), and STUN_USERNAME.

Referenced by ast_rtp_stun_request(), and ast_sip_ouraddrfor().

00643 {
00644    struct stun_header *req;
00645    unsigned char reqdata[1024];
00646    int reqlen, reqleft;
00647    struct stun_attr *attr;
00648    int res = 0;
00649    int retry;
00650    
00651    req = (struct stun_header *)reqdata;
00652    stun_req_id(req);
00653    reqlen = 0;
00654    reqleft = sizeof(reqdata) - sizeof(struct stun_header);
00655    req->msgtype = 0;
00656    req->msglen = 0;
00657    attr = (struct stun_attr *)req->ies;
00658    if (username)
00659       append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft);
00660    req->msglen = htons(reqlen);
00661    req->msgtype = htons(STUN_BINDREQ);
00662    for (retry = 0; retry < 3; retry++) {  /* XXX make retries configurable */
00663       /* send request, possibly wait for reply */
00664       unsigned char reply_buf[1024];
00665       fd_set rfds;
00666       struct timeval to = { 3, 0 }; /* timeout, make it configurable */
00667       struct sockaddr_in src;
00668       socklen_t srclen;
00669 
00670       res = stun_send(s, dst, req);
00671       if (res < 0) {
00672          ast_log(LOG_WARNING, "ast_stun_request send #%d failed error %d, retry\n",
00673             retry, res);
00674          continue;
00675       }
00676       if (answer == NULL)
00677          break;
00678       FD_ZERO(&rfds);
00679       FD_SET(s, &rfds);
00680       res = ast_select(s + 1, &rfds, NULL, NULL, &to);
00681       if (res <= 0)  /* timeout or error */
00682          continue;
00683       memset(&src, '\0', sizeof(src));
00684       srclen = sizeof(src);
00685       /* XXX pass -1 in the size, because stun_handle_packet might
00686        * write past the end of the buffer.
00687        */
00688       res = recvfrom(s, reply_buf, sizeof(reply_buf) - 1,
00689          0, (struct sockaddr *)&src, &srclen);
00690       if (res < 0) {
00691          ast_log(LOG_WARNING, "ast_stun_request recvfrom #%d failed error %d, retry\n",
00692             retry, res);
00693          continue;
00694       }
00695       memset(answer, '\0', sizeof(struct sockaddr_in));
00696       stun_handle_packet(s, &src, reply_buf, res,
00697          stun_get_mapped, answer);
00698       res = 0; /* signal regular exit */
00699       break;
00700    }
00701    return res;
00702 }

void red_buffer_t140 ( struct ast_rtp rtp,
struct ast_frame f 
)

Buffer t.140 data.

Parameters:
rtp 
f frame

Definition at line 5039 of file rtp.c.

References rtp_red::buf_data, ast_frame::datalen, f, ast_rtp::red, rtp_red::t140, and ast_frame::ts.

Referenced by sip_write().

05040 {
05041    if (f->datalen > -1) {
05042       struct rtp_red *red = rtp->red;
05043       memcpy(&red->buf_data[red->t140.datalen], f->data.ptr, f->datalen); 
05044       red->t140.datalen += f->datalen;
05045       red->t140.ts = f->ts;
05046    }
05047 }

int rtp_red_init ( struct ast_rtp rtp,
int  ti,
int *  red_data_pt,
int  num_gen 
)

Initalize t.140 redudancy.

Parameters:
rtp 
ti buffer t140 for ti (msecs) before sending redundant frame
red_data_pt Payloadtypes for primary- and generation-data
num_gen numbers of generations (primary generation not encounted)

Definition at line 5000 of file rtp.c.

References ast_calloc, AST_FORMAT_T140RED, AST_FRAME_TEXT, ast_sched_add(), rtp_red::buf_data, ast_frame::data, ast_frame::datalen, ast_frame::frametype, rtp_red::hdrlen, rtp_red::num_gen, rtp_red::prev_ts, rtp_red::pt, ast_frame::ptr, ast_rtp::red, red_write(), ast_rtp::sched, rtp_red::schedid, ast_frame::subclass, rtp_red::t140, rtp_red::t140red, rtp_red::t140red_data, rtp_red::ti, and ast_frame::ts.

Referenced by process_sdp().

05001 {
05002    struct rtp_red *r;
05003    int x;
05004    
05005    if (!(r = ast_calloc(1, sizeof(struct rtp_red))))
05006       return -1;
05007 
05008    r->t140.frametype = AST_FRAME_TEXT;
05009    r->t140.subclass = AST_FORMAT_T140RED;
05010    r->t140.data.ptr = &r->buf_data; 
05011 
05012    r->t140.ts = 0;
05013    r->t140red = r->t140;
05014    r->t140red.data.ptr = &r->t140red_data;
05015    r->t140red.datalen = 0;
05016    r->ti = ti;
05017    r->num_gen = num_gen;
05018    r->hdrlen = num_gen * 4 + 1;
05019    r->prev_ts = 0;
05020 
05021    for (x = 0; x < num_gen; x++) {
05022       r->pt[x] = red_data_pt[x];
05023       r->pt[x] |= 1 << 7; /* mark redundant generations pt */ 
05024       r->t140red_data[x*4] = r->pt[x];
05025    }
05026    r->t140red_data[x*4] = r->pt[x] = red_data_pt[x]; /* primary pt */
05027    r->schedid = ast_sched_add(rtp->sched, ti, red_write, rtp);
05028    rtp->red = r;
05029 
05030    r->t140.datalen = 0;
05031    
05032    return 0;
05033 }


Generated on Wed Aug 18 22:34:33 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7