Fri Nov 12 12:09:13 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"
Include dependency graph for rtp.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ast_rtp_protocol
 This is the structure that binds a channel (SIP/Jingle/H.323) to the RTP subsystem. More...
struct  ast_rtp_quality
 RTCP quality report storage. More...
struct  rtpPayloadType
 The value of each payload format mapping:. 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)
struct ast_frameast_rtcp_read (struct ast_rtp *rtp)
int ast_rtcp_send_h261fur (void *data)
 Send an H.261 fast update request. Some devices need this rather than the XML message in SIP.
size_t ast_rtp_alloc_size (void)
 Get the amount of space required to hold an RTP session.
int ast_rtp_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
 The RTP bridge.
int ast_rtp_codec_getformat (int pt)
 get format from predefined dynamic payload format
struct 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)
struct ast_rtpast_rtp_get_bridged (struct ast_rtp *rtp)
void ast_rtp_get_current_formats (struct ast_rtp *rtp, int *astFormats, int *nonAstFormats)
 Return the union of all of the codecs that were set by rtp_set...() calls They're returned as two distinct sets: AST_FORMATs, and AST_RTPs.
int ast_rtp_get_peer (struct ast_rtp *rtp, struct sockaddr_in *them)
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):.
struct rtpPayloadType ast_rtp_lookup_pt (struct ast_rtp *rtp, int pt)
 Mapping between RTP payload format codes and Asterisk codes:.
unsigned int ast_rtp_lookup_sample_rate (int isAstFormat, int code)
 Get the sample rate associated with known RTP payload types.
int ast_rtp_make_compatible (struct ast_channel *dest, struct ast_channel *src, int media)
struct ast_rtpast_rtp_new (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode)
 Initializate a RTP session.
void ast_rtp_new_init (struct ast_rtp *rtp)
 Initialize a new RTP structure.
void ast_rtp_new_source (struct ast_rtp *rtp)
struct ast_rtpast_rtp_new_with_bindaddr (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode, struct in_addr in)
 Initializate a RTP session using an in_addr structure.
int ast_rtp_proto_register (struct ast_rtp_protocol *proto)
 Register 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.
struct ast_frameast_rtp_read (struct ast_rtp *rtp)
int ast_rtp_reload (void)
void ast_rtp_reset (struct ast_rtp *rtp)
int ast_rtp_sendcng (struct ast_rtp *rtp, int level)
 generate comfort noice (CNG)
int ast_rtp_senddigit_begin (struct ast_rtp *rtp, char digit)
 Send begin frames for DTMF.
int ast_rtp_senddigit_end (struct ast_rtp *rtp, char digit)
 Send end packets for DTMF.
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_constantssrc (struct ast_rtp *rtp)
 When changing sources, don't generate a new SSRC.
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)
 Set payload type to a known MIME media type for a codec.
int ast_rtp_set_rtpmap_type_rate (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype, enum ast_rtp_options options, unsigned int sample_rate)
 Set payload type to a known MIME media type for a codec with a specific sample rate.
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)
#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.

Referenced by process_rfc3389().

#define MAX_RTP_PT   256
#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 130 of file rtp.h.


Enumeration Type Documentation

Enumerator:
AST_RTP_GET_FAILED 

Failed to find the RTP structure

AST_RTP_TRY_PARTIAL 

RTP structure exists but true native bridge can not occur so try partial

AST_RTP_TRY_NATIVE 

RTP structure exists and native bridge can occur

Definition at line 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 };

Enumerator:
AST_RTP_OPT_G726_NONSTANDARD 

Definition at line 59 of file rtp.h.

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

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 };

Enumerator:
RTPQOS_SUMMARY 
RTPQOS_JITTER 
RTPQOS_LOSS 
RTPQOS_RTT 

Definition at line 109 of file rtp.h.

00109                           {
00110    RTPQOS_SUMMARY = 0,
00111    RTPQOS_JITTER,
00112    RTPQOS_LOSS,
00113    RTPQOS_RTT
00114 };


Function Documentation

int ast_rtcp_fd ( struct ast_rtp rtp  ) 

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

00724 {
00725    if (rtp->rtcp)
00726       return rtp->rtcp->s;
00727    return -1;
00728 }

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

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

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

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

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

03300 {
03301    struct ast_rtp *rtp = data;
03302    int res;
03303 
03304    rtp->rtcp->sendfur = 1;
03305    res = ast_rtcp_write(data);
03306    
03307    return res;
03308 }

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

Referenced by process_sdp().

00495 {
00496    return sizeof(struct ast_rtp);
00497 }

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

References AST_BRIDGE_DTMF_CHANNEL_0, AST_BRIDGE_DTMF_CHANNEL_1, AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_check_hangup(), ast_codec_pref_getsize(), ast_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.

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

int ast_rtp_codec_getformat ( int  pt  ) 

get format from predefined dynamic payload format

Definition at line 3779 of file rtp.c.

References rtpPayloadType::code, and MAX_RTP_PT.

Referenced by process_sdp_a_audio().

03780 {
03781    if (pt < 0 || pt >= MAX_RTP_PT)
03782       return 0; /* bogus payload type */
03783 
03784    if (static_RTP_PT[pt].isAstFormat)
03785       return static_RTP_PT[pt].code;
03786    else
03787       return 0;
03788 }

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

Get codec preference.

Definition at line 3774 of file rtp.c.

References ast_rtp::pref.

Referenced by add_codec_to_sdp(), and process_sdp_a_audio().

03775 {
03776    return &rtp->pref;
03777 }

void ast_rtp_codec_setpref ( struct ast_rtp rtp,
struct ast_codec_pref prefs 
)

Set codec preference.

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

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

void ast_rtp_destroy ( struct ast_rtp rtp  ) 

Destroy RTP session

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

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

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 2071 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.

02072 {
02073    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
02074    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
02075    struct ast_rtp *tdestp = NULL, *tsrcp = NULL;      /* Text RTP channels */
02076    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
02077    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;
02078    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;
02079    int srccodec, destcodec, nat_active = 0;
02080 
02081    /* Lock channels */
02082    ast_channel_lock(c0);
02083    if (c1) {
02084       while (ast_channel_trylock(c1)) {
02085          ast_channel_unlock(c0);
02086          usleep(1);
02087          ast_channel_lock(c0);
02088       }
02089    }
02090 
02091    /* Find channel driver interfaces */
02092    destpr = get_proto(c0);
02093    if (c1)
02094       srcpr = get_proto(c1);
02095    if (!destpr) {
02096       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c0->name);
02097       ast_channel_unlock(c0);
02098       if (c1)
02099          ast_channel_unlock(c1);
02100       return -1;
02101    }
02102    if (!srcpr) {
02103       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c1 ? c1->name : "<unspecified>");
02104       ast_channel_unlock(c0);
02105       if (c1)
02106          ast_channel_unlock(c1);
02107       return -1;
02108    }
02109 
02110    /* Get audio, video  and text interface (if native bridge is possible) */
02111    audio_dest_res = destpr->get_rtp_info(c0, &destp);
02112    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(c0, &vdestp) : AST_RTP_GET_FAILED;
02113    text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(c0, &tdestp) : AST_RTP_GET_FAILED;
02114    if (srcpr) {
02115       audio_src_res = srcpr->get_rtp_info(c1, &srcp);
02116       video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(c1, &vsrcp) : AST_RTP_GET_FAILED;
02117       text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(c1, &tsrcp) : AST_RTP_GET_FAILED;
02118    }
02119 
02120    /* Check if bridge is still possible (In SIP directmedia=no stops this, like NAT) */
02121    if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE)) {
02122       /* Somebody doesn't want to play... */
02123       ast_channel_unlock(c0);
02124       if (c1)
02125          ast_channel_unlock(c1);
02126       return -1;
02127    }
02128    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)
02129       srccodec = srcpr->get_codec(c1);
02130    else
02131       srccodec = 0;
02132    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)
02133       destcodec = destpr->get_codec(c0);
02134    else
02135       destcodec = 0;
02136    /* Ensure we have at least one matching codec */
02137    if (srcp && !(srccodec & destcodec)) {
02138       ast_channel_unlock(c0);
02139       ast_channel_unlock(c1);
02140       return 0;
02141    }
02142    /* Consider empty media as non-existent */
02143    if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr)
02144       srcp = NULL;
02145    if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
02146       nat_active = 1;
02147    /* Bridge media early */
02148    if (destpr->set_rtp_peer(c0, srcp, vsrcp, tsrcp, srccodec, nat_active))
02149       ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
02150    ast_channel_unlock(c0);
02151    if (c1)
02152       ast_channel_unlock(c1);
02153    ast_debug(1, "Setting early bridge SDP of '%s' with that of '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
02154    return 0;
02155 }

int ast_rtp_fd ( struct ast_rtp rtp  ) 

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

00719 {
00720    return rtp->s;
00721 }

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

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

02700 {
02701    struct ast_rtp *bridged = NULL;
02702 
02703    rtp_bridge_lock(rtp);
02704    bridged = rtp->bridged;
02705    rtp_bridge_unlock(rtp);
02706 
02707    return bridged;
02708 }

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 2319 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 gtalk_is_answered(), gtalk_newcall(), and process_sdp().

02321 {
02322    int pt;
02323    
02324    rtp_bridge_lock(rtp);
02325    
02326    *astFormats = *nonAstFormats = 0;
02327    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02328       if (rtp->current_RTP_PT[pt].isAstFormat) {
02329          *astFormats |= rtp->current_RTP_PT[pt].code;
02330       } else {
02331          *nonAstFormats |= rtp->current_RTP_PT[pt].code;
02332       }
02333    }
02334 
02335    rtp_bridge_unlock(rtp);
02336 }

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

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

02682 {
02683    if ((them->sin_family != AF_INET) ||
02684       (them->sin_port != rtp->them.sin_port) ||
02685       (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
02686       them->sin_family = AF_INET;
02687       them->sin_port = rtp->them.sin_port;
02688       them->sin_addr = rtp->them.sin_addr;
02689       return 1;
02690    }
02691    return 0;
02692 }

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

References __ast_rtp_get_qos().

Referenced by acf_channel_read().

02821 {
02822    double value;
02823    int found;
02824 
02825    value = __ast_rtp_get_qos(rtp, qos, &found);
02826 
02827    if (!found)
02828       return -1;
02829 
02830    snprintf(buf, buflen, "%.0lf", value);
02831 
02832    return 0;
02833 }

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

Return RTP and RTCP QoS values.

Since:
1.6.1

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

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

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

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 3027 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().

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

int ast_rtp_get_rtpholdtimeout ( struct ast_rtp rtp  ) 

Get rtp hold timeout.

Definition at line 778 of file rtp.c.

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

Referenced by check_rtp_timeout().

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

int ast_rtp_get_rtpkeepalive ( struct ast_rtp rtp  ) 

Get RTP keepalive interval.

Definition at line 786 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by check_rtp_timeout().

00787 {
00788    return rtp->rtpkeepalive;
00789 }

int ast_rtp_get_rtptimeout ( struct ast_rtp rtp  ) 

Get rtp timeout.

Definition at line 770 of file rtp.c.

References ast_rtp::rtptimeout.

Referenced by check_rtp_timeout().

00771 {
00772    if (rtp->rtptimeout < 0)   /* We're not checking, but remembering the setting (during T.38 transmission) */
00773       return 0;
00774    return rtp->rtptimeout;
00775 }

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

Definition at line 806 of file rtp.c.

References ast_test_flag, and FLAG_NAT_ACTIVE.

Referenced by sip_get_rtp_peer().

00807 {
00808    return ast_test_flag(rtp, FLAG_NAT_ACTIVE);
00809 }

void ast_rtp_init ( void   ) 

Initialize the RTP system in Asterisk.

Definition at line 4817 of file rtp.c.

References __ast_rtp_reload(), and ast_cli_register_multiple().

Referenced by main().

04818 {
04819    ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
04820    __ast_rtp_reload(0);
04821 }

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 2360 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().

02361 {
02362    int pt = 0;
02363 
02364    rtp_bridge_lock(rtp);
02365 
02366    if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
02367       code == rtp->rtp_lookup_code_cache_code) {
02368       /* Use our cached mapping, to avoid the overhead of the loop below */
02369       pt = rtp->rtp_lookup_code_cache_result;
02370       rtp_bridge_unlock(rtp);
02371       return pt;
02372    }
02373 
02374    /* Check the dynamic list first */
02375    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02376       if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
02377          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
02378          rtp->rtp_lookup_code_cache_code = code;
02379          rtp->rtp_lookup_code_cache_result = pt;
02380          rtp_bridge_unlock(rtp);
02381          return pt;
02382       }
02383    }
02384 
02385    /* Then the static list */
02386    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02387       if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) {
02388          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
02389          rtp->rtp_lookup_code_cache_code = code;
02390          rtp->rtp_lookup_code_cache_result = pt;
02391          rtp_bridge_unlock(rtp);
02392          return pt;
02393       }
02394    }
02395 
02396    rtp_bridge_unlock(rtp);
02397 
02398    return -1;
02399 }

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

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

Referenced by process_sdp().

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

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

References ARRAY_LEN, AST_FORMAT_G726_AAL2, AST_RTP_OPT_G726_NONSTANDARD, rtpPayloadType::isAstFormat, mimeTypes, mimeType::payloadType, and mimeType::subtype.

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().

02403 {
02404    unsigned int i;
02405 
02406    for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
02407       if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
02408          if (isAstFormat &&
02409              (code == AST_FORMAT_G726_AAL2) &&
02410              (options & AST_RTP_OPT_G726_NONSTANDARD))
02411             return "G726-32";
02412          else
02413             return mimeTypes[i].subtype;
02414       }
02415    }
02416 
02417    return "";
02418 }

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

Mapping between RTP payload format codes and Asterisk codes:.

Definition at line 2338 of file rtp.c.

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

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

02339 {
02340    struct rtpPayloadType result;
02341 
02342    result.isAstFormat = result.code = 0;
02343 
02344    if (pt < 0 || pt >= MAX_RTP_PT) 
02345       return result; /* bogus payload type */
02346 
02347    /* Start with negotiated codecs */
02348    rtp_bridge_lock(rtp);
02349    result = rtp->current_RTP_PT[pt];
02350    rtp_bridge_unlock(rtp);
02351 
02352    /* If it doesn't exist, check our static RTP type list, just in case */
02353    if (!result.code) 
02354       result = static_RTP_PT[pt];
02355 
02356    return result;
02357 }

unsigned int ast_rtp_lookup_sample_rate ( int  isAstFormat,
int  code 
)

Get the sample rate associated with known RTP payload types.

Parameters:
isAstFormat True if the value in the 'code' parameter is an AST_FORMAT value
code Format code, either from AST_FORMAT list or from AST_RTP list
Returns:
the sample rate if the format was found, zero if it was not found

Definition at line 2420 of file rtp.c.

References ARRAY_LEN, rtpPayloadType::isAstFormat, mimeTypes, mimeType::payloadType, and mimeType::sample_rate.

Referenced by add_codec_to_sdp(), add_noncodec_to_sdp(), add_tcodec_to_sdp(), and add_vcodec_to_sdp().

02421 {
02422    unsigned int i;
02423 
02424    for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
02425       if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
02426          return mimeTypes[i].sample_rate;
02427       }
02428    }
02429 
02430    return 0;
02431 }

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

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

02158 {
02159    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
02160    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
02161    struct ast_rtp *tdestp = NULL, *tsrcp = NULL;      /* Text RTP channels */
02162    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
02163    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;
02164    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; 
02165    int srccodec, destcodec;
02166 
02167    /* Lock channels */
02168    ast_channel_lock(dest);
02169    while (ast_channel_trylock(src)) {
02170       ast_channel_unlock(dest);
02171       usleep(1);
02172       ast_channel_lock(dest);
02173    }
02174 
02175    /* Find channel driver interfaces */
02176    if (!(destpr = get_proto(dest))) {
02177       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", dest->name);
02178       ast_channel_unlock(dest);
02179       ast_channel_unlock(src);
02180       return 0;
02181    }
02182    if (!(srcpr = get_proto(src))) {
02183       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", src->name);
02184       ast_channel_unlock(dest);
02185       ast_channel_unlock(src);
02186       return 0;
02187    }
02188 
02189    /* Get audio and video interface (if native bridge is possible) */
02190    audio_dest_res = destpr->get_rtp_info(dest, &destp);
02191    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED;
02192    text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(dest, &tdestp) : AST_RTP_GET_FAILED;
02193    audio_src_res = srcpr->get_rtp_info(src, &srcp);
02194    video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED;
02195    text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(src, &tsrcp) : AST_RTP_GET_FAILED;
02196 
02197    /* Ensure we have at least one matching codec */
02198    if (srcpr->get_codec)
02199       srccodec = srcpr->get_codec(src);
02200    else
02201       srccodec = 0;
02202    if (destpr->get_codec)
02203       destcodec = destpr->get_codec(dest);
02204    else
02205       destcodec = 0;
02206 
02207    /* Check if bridge is still possible (In SIP directmedia=no stops this, like NAT) */
02208    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)) {
02209       /* Somebody doesn't want to play... */
02210       ast_channel_unlock(dest);
02211       ast_channel_unlock(src);
02212       return 0;
02213    }
02214    ast_rtp_pt_copy(destp, srcp);
02215    if (vdestp && vsrcp)
02216       ast_rtp_pt_copy(vdestp, vsrcp);
02217    if (tdestp && tsrcp)
02218       ast_rtp_pt_copy(tdestp, tsrcp);
02219    if (media) {
02220       /* Bridge early */
02221       if (destpr->set_rtp_peer(dest, srcp, vsrcp, tsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
02222          ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name);
02223    }
02224    ast_channel_unlock(dest);
02225    ast_channel_unlock(src);
02226    ast_debug(1, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name);
02227    return 1;
02228 }

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

Initializate a RTP session.

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

Definition at line 2628 of file rtp.c.

References ast_rtp_new_with_bindaddr().

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

void ast_rtp_new_init ( struct ast_rtp rtp  ) 

Initialize a new RTP structure.

reload rtp configuration

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

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

void ast_rtp_new_source ( struct ast_rtp rtp  ) 

Definition at line 2646 of file rtp.c.

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

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

02647 {
02648    if (rtp) {
02649       rtp->set_marker_bit = 1;
02650       if (!rtp->constantssrc) {
02651          rtp->ssrc = ast_random();
02652       }
02653    }
02654 }

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

Initializate a RTP session using an in_addr structure.

This fuction gets called by ast_rtp_new().

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

Definition at line 2533 of file rtp.c.

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

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

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

int ast_rtp_proto_register ( struct ast_rtp_protocol proto  ) 

Register an RTP channel client.

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

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

void ast_rtp_proto_unregister ( struct ast_rtp_protocol proto  ) 

Unregister an RTP channel client.

Definition at line 3888 of file rtp.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by load_module(), and unload_module().

03889 {
03890    AST_RWLIST_WRLOCK(&protos);
03891    AST_RWLIST_REMOVE(&protos, proto, list);
03892    AST_RWLIST_UNLOCK(&protos);
03893 }

void ast_rtp_pt_clear ( struct ast_rtp rtp  ) 

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

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

01996 {
01997    int i;
01998 
01999    if (!rtp)
02000       return;
02001 
02002    rtp_bridge_lock(rtp);
02003 
02004    for (i = 0; i < MAX_RTP_PT; ++i) {
02005       rtp->current_RTP_PT[i].isAstFormat = 0;
02006       rtp->current_RTP_PT[i].code = 0;
02007    }
02008 
02009    rtp->rtp_lookup_code_cache_isAstFormat = 0;
02010    rtp->rtp_lookup_code_cache_code = 0;
02011    rtp->rtp_lookup_code_cache_result = 0;
02012 
02013    rtp_bridge_unlock(rtp);
02014 }

void ast_rtp_pt_copy ( struct ast_rtp dest,
struct ast_rtp src 
)

Copy payload types between RTP structures.

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 ast_rtp_make_compatible(), and process_sdp().

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

void ast_rtp_pt_default ( struct ast_rtp rtp  ) 

Set payload types to defaults.

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

02017 {
02018    int i;
02019 
02020    rtp_bridge_lock(rtp);
02021 
02022    /* Initialize to default payload types */
02023    for (i = 0; i < MAX_RTP_PT; ++i) {
02024       rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
02025       rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
02026    }
02027 
02028    rtp->rtp_lookup_code_cache_isAstFormat = 0;
02029    rtp->rtp_lookup_code_cache_code = 0;
02030    rtp->rtp_lookup_code_cache_result = 0;
02031 
02032    rtp_bridge_unlock(rtp);
02033 }

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

Definition at line 1562 of file rtp.c.

References ast_rtp::altthem, ast_assert, ast_codec_get_samples(), 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_DTMF_END, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_rtcp_calc_interval(), ast_rtcp_write(), AST_RTP_CISCO_DTMF, AST_RTP_CN, AST_RTP_DTMF, ast_rtp_get_bridged(), ast_rtp_lookup_pt(), ast_rtp_senddigit_continuation(), ast_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, 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, ast_frame::frametype, rtpPayloadType::isAstFormat, ast_rtp::lastevent, ast_rtp::lastitexttimestamp, ast_rtp::lastividtimestamp, 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, send_dtmf(), ast_rtp::sending_digit, ast_frame::seqno, ast_frame::src, 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().

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

int ast_rtp_reload ( void   ) 

Initialize RTP subsystem

Definition at line 4811 of file rtp.c.

References __ast_rtp_reload().

04812 {
04813    return __ast_rtp_reload(1);
04814 }

void ast_rtp_reset ( struct ast_rtp rtp  ) 

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

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

int ast_rtp_sendcng ( struct ast_rtp rtp,
int  level 
)

generate comfort noice (CNG)

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

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

int ast_rtp_senddigit_begin ( struct ast_rtp rtp,
char  digit 
)

Send begin frames for DTMF.

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

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

int ast_rtp_senddigit_end ( struct ast_rtp rtp,
char  digit 
)

Send end packets for DTMF.

Definition at line 3243 of file rtp.c.

References ast_inet_ntoa(), ast_log(), 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_end(), oh323_digit_end(), and sip_senddigit_end().

03244 {
03245    unsigned int *rtpheader;
03246    int hdrlen = 12, res = 0, i = 0;
03247    char data[256];
03248    
03249    /* If no address, then bail out */
03250    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
03251       return 0;
03252    
03253    if ((digit <= '9') && (digit >= '0'))
03254       digit -= '0';
03255    else if (digit == '*')
03256       digit = 10;
03257    else if (digit == '#')
03258       digit = 11;
03259    else if ((digit >= 'A') && (digit <= 'D'))
03260       digit = digit - 'A' + 12;
03261    else if ((digit >= 'a') && (digit <= 'd'))
03262       digit = digit - 'a' + 12;
03263    else {
03264       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
03265       return 0;
03266    }
03267 
03268    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
03269 
03270    rtpheader = (unsigned int *)data;
03271    rtpheader[1] = htonl(rtp->lastdigitts);
03272    rtpheader[2] = htonl(rtp->ssrc);
03273    rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
03274    /* Set end bit */
03275    rtpheader[3] |= htonl((1 << 23));
03276 
03277    /* Send 3 termination packets */
03278    for (i = 0; i < 3; i++) {
03279       rtpheader[0] = htonl((2 << 30) | (rtp->send_payload << 16) | (rtp->seqno));
03280       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
03281       rtp->seqno++;
03282       if (res < 0)
03283          ast_log(LOG_ERROR, "RTP Transmission error to %s:%d: %s\n",
03284             ast_inet_ntoa(rtp->them.sin_addr),
03285             ntohs(rtp->them.sin_port), strerror(errno));
03286       if (rtp_debug_test_addr(&rtp->them))
03287          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
03288                 ast_inet_ntoa(rtp->them.sin_addr),
03289                 ntohs(rtp->them.sin_port), rtp->send_payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
03290    }
03291    rtp->lastts += rtp->send_duration;
03292    rtp->sending_digit = 0;
03293    rtp->send_digit = 0;
03294 
03295    return res;
03296 }

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

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

Referenced by handle_request_invite().

02672 {
02673    rtp->altthem.sin_port = alt->sin_port;
02674    rtp->altthem.sin_addr = alt->sin_addr;
02675    if (rtp->rtcp) {
02676       rtp->rtcp->altthem.sin_port = htons(ntohs(alt->sin_port) + 1);
02677       rtp->rtcp->altthem.sin_addr = alt->sin_addr;
02678    }
02679 }

void ast_rtp_set_callback ( struct ast_rtp rtp,
ast_rtp_callback  callback 
)

Definition at line 796 of file rtp.c.

References ast_rtp::callback.

Referenced by start_rtp().

00797 {
00798    rtp->callback = callback;
00799 }

void ast_rtp_set_constantssrc ( struct ast_rtp rtp  ) 

When changing sources, don't generate a new SSRC.

Definition at line 2641 of file rtp.c.

References ast_rtp::constantssrc.

Referenced by create_addr_from_peer(), and handle_request_invite().

02642 {
02643    rtp->constantssrc = 1;
02644 }

void ast_rtp_set_data ( struct ast_rtp rtp,
void *  data 
)

Definition at line 791 of file rtp.c.

References ast_rtp::data.

Referenced by start_rtp().

00792 {
00793    rtp->data = data;
00794 }

void ast_rtp_set_m_type ( struct ast_rtp rtp,
int  pt 
)

Activate payload type.

Definition at line 2234 of file rtp.c.

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

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

02235 {
02236    if (pt < 0 || pt >= MAX_RTP_PT || static_RTP_PT[pt].code == 0) 
02237       return; /* bogus payload type */
02238 
02239    rtp_bridge_lock(rtp);
02240    rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
02241    rtp_bridge_unlock(rtp);
02242 } 

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

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

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

void ast_rtp_set_rtpholdtimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp hold timeout.

Definition at line 758 of file rtp.c.

References ast_rtp::rtpholdtimeout.

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

00759 {
00760    rtp->rtpholdtimeout = timeout;
00761 }

void ast_rtp_set_rtpkeepalive ( struct ast_rtp rtp,
int  period 
)

set RTP keepalive interval

Definition at line 764 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by create_addr_from_peer(), and sip_alloc().

00765 {
00766    rtp->rtpkeepalive = period;
00767 }

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

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

Parameters:
rtp RTP structure to modify
pt Payload type entry to modify
mimeType top-level MIME type of media stream (typically "audio", "video", "text", etc.)
mimeSubtype MIME subtype of media stream (typically a codec name)
options Zero or more flags from the ast_rtp_options enum

This function 'fills in' an entry in the list of possible formats for a media stream associated with an RTP structure.

Return values:
0 on success
-1 if the payload type is out of range
-2 if the mimeType/mimeSubtype combination was not found

Definition at line 2310 of file rtp.c.

References ast_rtp_set_rtpmap_type_rate().

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

02313 {
02314    return ast_rtp_set_rtpmap_type_rate(rtp, pt, mimeType, mimeSubtype, options, 0);
02315 }

int ast_rtp_set_rtpmap_type_rate ( struct ast_rtp rtp,
int  pt,
char *  mimeType,
char *  mimeSubtype,
enum ast_rtp_options  options,
unsigned int  sample_rate 
)

Set payload type to a known MIME media type for a codec with a specific sample rate.

Parameters:
rtp RTP structure to modify
pt Payload type entry to modify
mimeType top-level MIME type of media stream (typically "audio", "video", "text", etc.)
mimeSubtype MIME subtype of media stream (typically a codec name)
options Zero or more flags from the ast_rtp_options enum
sample_rate The sample rate of the media stream

This function 'fills in' an entry in the list of possible formats for a media stream associated with an RTP structure.

Return values:
0 on success
-1 if the payload type is out of range
-2 if the mimeType/mimeSubtype combination was not found

Set payload type to a known MIME media type for a codec with a specific sample rate.

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

Definition at line 2261 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, rtpPayloadType::isAstFormat, MAX_RTP_PT, mimeTypes, mimeType::payloadType, rtp_bridge_lock(), rtp_bridge_unlock(), mimeType::sample_rate, mimeType::subtype, and mimeType::type.

Referenced by ast_rtp_set_rtpmap_type(), process_sdp_a_audio(), and process_sdp_a_video().

02265 {
02266    unsigned int i;
02267    int found = 0;
02268 
02269    if (pt < 0 || pt >= MAX_RTP_PT)
02270       return -1; /* bogus payload type */
02271 
02272    rtp_bridge_lock(rtp);
02273 
02274    for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
02275       const struct mimeType *t = &mimeTypes[i];
02276 
02277       if (strcasecmp(mimeSubtype, t->subtype)) {
02278          continue;
02279       }
02280 
02281       if (strcasecmp(mimeType, t->type)) {
02282          continue;
02283       }
02284 
02285       /* if both sample rates have been supplied, and they don't match,
02286          then this not a match; if one has not been supplied, then the
02287          rates are not compared */
02288       if (sample_rate && t->sample_rate &&
02289           (sample_rate != t->sample_rate)) {
02290          continue;
02291       }
02292 
02293       found = 1;
02294       rtp->current_RTP_PT[pt] = t->payloadType;
02295 
02296       if ((t->payloadType.code == AST_FORMAT_G726) &&
02297           t->payloadType.isAstFormat &&
02298           (options & AST_RTP_OPT_G726_NONSTANDARD)) {
02299          rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2;
02300       }
02301 
02302       break;
02303    }
02304 
02305    rtp_bridge_unlock(rtp);
02306 
02307    return (found ? 0 : -2);
02308 }

void ast_rtp_set_rtptimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp timeout.

Definition at line 752 of file rtp.c.

References ast_rtp::rtptimeout.

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

00753 {
00754    rtp->rtptimeout = timeout;
00755 }

void ast_rtp_set_rtptimers_onhold ( struct ast_rtp rtp  ) 

Definition at line 745 of file rtp.c.

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

Referenced by handle_response_invite().

00746 {
00747    rtp->rtptimeout = (-1) * rtp->rtptimeout;
00748    rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout;
00749 }

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

References ast_bridged_channel(), ast_rtp_get_quality(), ast_channel::bridge, pbx_builtin_setvar_helper(), RTPQOS_JITTER, RTPQOS_LOSS, RTPQOS_RTT, and RTPQOS_SUMMARY.

Referenced by handle_request_bye(), and sip_hangup().

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

void ast_rtp_setdtmf ( struct ast_rtp rtp,
int  dtmf 
)

Indicate whether this RTP session is carrying DTMF or not.

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

00812 {
00813    ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF);
00814 }

void ast_rtp_setdtmfcompensate ( struct ast_rtp rtp,
int  compensate 
)

Compensate for devices that send RFC2833 packets all at once.

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

00817 {
00818    ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE);
00819 }

void ast_rtp_setnat ( struct ast_rtp rtp,
int  nat 
)

Definition at line 801 of file rtp.c.

References ast_rtp::nat.

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

00802 {
00803    rtp->nat = nat;
00804 }

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

Definition at line 2636 of file rtp.c.

References ast_netsock_set_qos(), and ast_rtp::s.

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

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

void ast_rtp_setstun ( struct ast_rtp rtp,
int  stun_enable 
)

Enable STUN capability.

Definition at line 821 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_STUN.

Referenced by gtalk_new().

00822 {
00823    ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN);
00824 }

void ast_rtp_stop ( struct ast_rtp rtp  ) 

Stop RTP session, do not destroy structure

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

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

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

References ast_stun_request(), and ast_rtp::s.

Referenced by gtalk_update_stun(), and jingle_update_stun().

00701 {
00702    ast_stun_request(rtp->s, suggestion, username, NULL);
00703 }

void ast_rtp_unset_m_type ( struct ast_rtp rtp,
int  pt 
)

clear payload type

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

02247 {
02248    if (pt < 0 || pt >= MAX_RTP_PT)
02249       return; /* bogus payload type */
02250 
02251    rtp_bridge_lock(rtp);
02252    rtp->current_RTP_PT[pt].isAstFormat = 0;
02253    rtp->current_RTP_PT[pt].code = 0;
02254    rtp_bridge_unlock(rtp);
02255 }

int ast_rtp_write ( struct ast_rtp rtp,
struct ast_frame f 
)

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

Definition at line 3790 of file rtp.c.

References ast_codec_pref_getsize(), ast_debug, AST_FORMAT_G723_1, AST_FORMAT_SIREN14, AST_FORMAT_SIREN7, 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::data, ast_frame::datalen, f, ast_format_list::flags, ast_format_list::fr_len, ast_frame::frametype, ast_format_list::inc_ms, ast_rtp::lasttxformat, LOG_WARNING, ast_frame::offset, ast_rtp::pref, ast_frame::ptr, 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().

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

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. The interface it may change in the future.

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

References append_attr_string(), ast_log(), ast_select(), stun_header::ies, LOG_WARNING, stun_header::msglen, stun_header::msgtype, STUN_BINDREQ, stun_get_mapped(), stun_handle_packet(), stun_req_id(), stun_send(), and STUN_USERNAME.

Referenced by ast_rtp_stun_request(), ast_sip_ouraddrfor(), and reload_config().

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

void red_buffer_t140 ( struct ast_rtp rtp,
struct ast_frame f 
)

Buffer t.140 data.

Buffer t.140 data.

Parameters:
rtp 
f frame

Definition at line 4921 of file rtp.c.

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

Referenced by sip_write().

04922 {
04923    if (f->datalen > -1) {
04924       struct rtp_red *red = rtp->red;
04925       memcpy(&red->buf_data[red->t140.datalen], f->data.ptr, f->datalen);
04926       red->t140.datalen += f->datalen;
04927       red->t140.ts = f->ts;
04928    }
04929 }

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

Initalize t.140 redudancy.

Parameters:
ti time between each t140red frame is sent
red_pt payloadtype for RTP packet
pt payloadtype numbers for each generation including primary data
num_gen number of redundant generations, primary data excluded
Since:
1.6.1

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 4882 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().

04883 {
04884    struct rtp_red *r;
04885    int x;
04886    
04887    if (!(r = ast_calloc(1, sizeof(struct rtp_red))))
04888       return -1;
04889 
04890    r->t140.frametype = AST_FRAME_TEXT;
04891    r->t140.subclass = AST_FORMAT_T140RED;
04892    r->t140.data.ptr = &r->buf_data; 
04893 
04894    r->t140.ts = 0;
04895    r->t140red = r->t140;
04896    r->t140red.data.ptr = &r->t140red_data;
04897    r->t140red.datalen = 0;
04898    r->ti = ti;
04899    r->num_gen = num_gen;
04900    r->hdrlen = num_gen * 4 + 1;
04901    r->prev_ts = 0;
04902 
04903    for (x = 0; x < num_gen; x++) {
04904       r->pt[x] = red_data_pt[x];
04905       r->pt[x] |= 1 << 7; /* mark redundant generations pt */ 
04906       r->t140red_data[x*4] = r->pt[x];
04907    }
04908    r->t140red_data[x*4] = r->pt[x] = red_data_pt[x]; /* primary pt */
04909    r->schedid = ast_sched_add(rtp->sched, ti, red_write, rtp);
04910    rtp->red = r;
04911 
04912    r->t140.datalen = 0;
04913    
04914    return 0;
04915 }


Generated by  doxygen 1.6.2