Fri Jul 24 00:41:58 2009

Asterisk developer's documentation


rtp.h File Reference

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

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

Go to the source code of this file.

Data Structures

struct  ast_rtp_protocol
 This is the structure that binds a channel (SIP/Jingle/H.323) to the RTP subsystem. More...
struct  ast_rtp_quality
 RTCP quality report storage. More...

Defines

#define AST_RTP_CISCO_DTMF   (1 << 2)
#define AST_RTP_CN   (1 << 1)
#define AST_RTP_DTMF   (1 << 0)
#define AST_RTP_MAX   AST_RTP_CISCO_DTMF
#define FLAG_3389_WARNING   (1 << 0)
#define MAX_RTP_PT   256
#define RED_MAX_GENERATION   5

Typedefs

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

Enumerations

enum  ast_rtp_get_result { AST_RTP_GET_FAILED = 0, AST_RTP_TRY_PARTIAL, AST_RTP_TRY_NATIVE }
enum  ast_rtp_options { AST_RTP_OPT_G726_NONSTANDARD = (1 << 0) }
enum  ast_rtp_qos_vars {
  AST_RTP_TXCOUNT, AST_RTP_RXCOUNT, AST_RTP_TXJITTER, AST_RTP_RXJITTER,
  AST_RTP_RXPLOSS, AST_RTP_TXPLOSS, AST_RTP_RTT
}
 Variables used in ast_rtcp_get function. More...
enum  ast_rtp_quality_type { RTPQOS_SUMMARY = 0, RTPQOS_JITTER, RTPQOS_LOSS, RTPQOS_RTT }

Functions

int ast_rtcp_fd (struct ast_rtp *rtp)
ast_frameast_rtcp_read (struct ast_rtp *rtp)
int ast_rtcp_send_h261fur (void *data)
 Send an H.261 fast update request. Some devices need this rather than the XML message in SIP.
size_t ast_rtp_alloc_size (void)
 Get the amount of space required to hold an RTP session.
int ast_rtp_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
 The RTP bridge.
int ast_rtp_codec_getformat (int pt)
 get format from predefined dynamic payload format
ast_codec_prefast_rtp_codec_getpref (struct ast_rtp *rtp)
 Get codec preference.
void ast_rtp_codec_setpref (struct ast_rtp *rtp, struct ast_codec_pref *prefs)
 Set codec preference.
void ast_rtp_destroy (struct ast_rtp *rtp)
int ast_rtp_early_bridge (struct ast_channel *c0, struct ast_channel *c1)
 If possible, create an early bridge directly between the devices without having to send a re-invite later.
int ast_rtp_fd (struct ast_rtp *rtp)
ast_rtpast_rtp_get_bridged (struct ast_rtp *rtp)
void ast_rtp_get_current_formats (struct ast_rtp *rtp, int *astFormats, int *nonAstFormats)
 Return the union of all of the codecs that were set by rtp_set...() calls They're returned as two distinct sets: AST_FORMATs, and AST_RTPs.
int ast_rtp_get_peer (struct ast_rtp *rtp, struct sockaddr_in *them)
int ast_rtp_get_qos (struct ast_rtp *rtp, const char *qos, char *buf, unsigned int buflen)
 Get QOS stats on a RTP channel.
unsigned int ast_rtp_get_qosvalue (struct ast_rtp *rtp, enum ast_rtp_qos_vars value)
 Return RTP and RTCP QoS values.
char * ast_rtp_get_quality (struct ast_rtp *rtp, struct ast_rtp_quality *qual, enum ast_rtp_quality_type qtype)
 Return RTCP quality string.
int ast_rtp_get_rtpholdtimeout (struct ast_rtp *rtp)
 Get rtp hold timeout.
int ast_rtp_get_rtpkeepalive (struct ast_rtp *rtp)
 Get RTP keepalive interval.
int ast_rtp_get_rtptimeout (struct ast_rtp *rtp)
 Get rtp timeout.
void ast_rtp_get_us (struct ast_rtp *rtp, struct sockaddr_in *us)
int ast_rtp_getnat (struct ast_rtp *rtp)
void ast_rtp_init (void)
 Initialize the RTP system in Asterisk.
int ast_rtp_lookup_code (struct ast_rtp *rtp, int isAstFormat, int code)
 Looks up an RTP code out of our *static* outbound list.
char * ast_rtp_lookup_mime_multiple (char *buf, size_t size, const int capability, const int isAstFormat, enum ast_rtp_options options)
 Build a string of MIME subtype names from a capability list.
const char * ast_rtp_lookup_mime_subtype (int isAstFormat, int code, enum ast_rtp_options options)
 Mapping an Asterisk code into a MIME subtype (string):.
rtpPayloadType ast_rtp_lookup_pt (struct ast_rtp *rtp, int pt)
 Mapping between RTP payload format codes and Asterisk codes:.
int ast_rtp_make_compatible (struct ast_channel *dest, struct ast_channel *src, int media)
ast_rtpast_rtp_new (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode)
 Initializate a RTP session.
void ast_rtp_new_init (struct ast_rtp *rtp)
 Initialize a new RTP structure.
void ast_rtp_new_source (struct ast_rtp *rtp)
ast_rtpast_rtp_new_with_bindaddr (struct sched_context *sched, struct io_context *io, int rtcpenable, int callbackmode, struct in_addr in)
 Initializate a RTP session using an in_addr structure.
int ast_rtp_proto_register (struct ast_rtp_protocol *proto)
 Register an RTP channel client.
void ast_rtp_proto_unregister (struct ast_rtp_protocol *proto)
 Unregister an RTP channel client.
void ast_rtp_pt_clear (struct ast_rtp *rtp)
 Setting RTP payload types from lines in a SDP description:.
void ast_rtp_pt_copy (struct ast_rtp *dest, struct ast_rtp *src)
 Copy payload types between RTP structures.
void ast_rtp_pt_default (struct ast_rtp *rtp)
 Set payload types to defaults.
ast_frameast_rtp_read (struct ast_rtp *rtp)
int ast_rtp_reload (void)
void ast_rtp_reset (struct ast_rtp *rtp)
int ast_rtp_sendcng (struct ast_rtp *rtp, int level)
 generate comfort noice (CNG)
int ast_rtp_senddigit_begin (struct ast_rtp *rtp, char digit)
 Send begin frames for DTMF.
int ast_rtp_senddigit_end (struct ast_rtp *rtp, char digit)
void ast_rtp_set_callback (struct ast_rtp *rtp, ast_rtp_callback callback)
void ast_rtp_set_data (struct ast_rtp *rtp, void *data)
void ast_rtp_set_m_type (struct ast_rtp *rtp, int pt)
 Activate payload type.
void ast_rtp_set_peer (struct ast_rtp *rtp, struct sockaddr_in *them)
void ast_rtp_set_rtpholdtimeout (struct ast_rtp *rtp, int timeout)
 Set rtp hold timeout.
void ast_rtp_set_rtpkeepalive (struct ast_rtp *rtp, int period)
 set RTP keepalive interval
int ast_rtp_set_rtpmap_type (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype, enum ast_rtp_options options)
 Initiate payload type to a known MIME media type for a codec.
void ast_rtp_set_rtptimeout (struct ast_rtp *rtp, int timeout)
 Set rtp timeout.
void ast_rtp_set_rtptimers_onhold (struct ast_rtp *rtp)
void ast_rtp_set_vars (struct ast_channel *chan, struct ast_rtp *rtp)
 Set RTPAUDIOQOS(...) variables on a channel when it is being hung up.
void ast_rtp_setdtmf (struct ast_rtp *rtp, int dtmf)
 Indicate whether this RTP session is carrying DTMF or not.
void ast_rtp_setdtmfcompensate (struct ast_rtp *rtp, int compensate)
 Compensate for devices that send RFC2833 packets all at once.
void ast_rtp_setnat (struct ast_rtp *rtp, int nat)
int ast_rtp_setqos (struct ast_rtp *rtp, int tos, int cos, char *desc)
void ast_rtp_setstun (struct ast_rtp *rtp, int stun_enable)
 Enable STUN capability.
void ast_rtp_stop (struct ast_rtp *rtp)
void ast_rtp_stun_request (struct ast_rtp *rtp, struct sockaddr_in *suggestion, const char *username)
 Send STUN request for an RTP socket Deprecated, this is just a wrapper for ast_rtp_stun_request().
void ast_rtp_unset_m_type (struct ast_rtp *rtp, int pt)
 clear payload type
int ast_rtp_write (struct ast_rtp *rtp, struct ast_frame *f)
int ast_stun_request (int s, struct sockaddr_in *dst, const char *username, struct sockaddr_in *answer)
 Generic STUN request send a generic stun request to the server specified.
void red_buffer_t140 (struct ast_rtp *rtp, struct ast_frame *f)
 Buffer t.140 data.
int rtp_red_init (struct ast_rtp *rtp, int ti, int *pt, int num_gen)
 Initalize t.140 redudancy.


Detailed Description

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

RTP is defined in RFC 3550.

Definition in file rtp.h.


Define Documentation

#define AST_RTP_CISCO_DTMF   (1 << 2)

DTMF (Cisco Proprietary)

Definition at line 47 of file rtp.h.

Referenced by ast_rtp_read().

#define AST_RTP_CN   (1 << 1)

'Comfort Noise' (RFC3389)

Definition at line 45 of file rtp.h.

Referenced by ast_rtp_read(), and ast_rtp_sendcng().

#define AST_RTP_DTMF   (1 << 0)

DTMF (RFC2833)

Definition at line 43 of file rtp.h.

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

#define AST_RTP_MAX   AST_RTP_CISCO_DTMF

Maximum RTP-specific code

Definition at line 49 of file rtp.h.

Referenced by add_sdp(), and ast_rtp_lookup_mime_multiple().

#define FLAG_3389_WARNING   (1 << 0)

Definition at line 57 of file rtp.h.

#define MAX_RTP_PT   256

Maxmum number of payload defintions for a RTP session

Definition at line 52 of file rtp.h.

Referenced by ast_rtp_get_current_formats(), ast_rtp_lookup_code(), ast_rtp_lookup_pt(), ast_rtp_pt_clear(), ast_rtp_pt_copy(), ast_rtp_pt_default(), ast_rtp_set_m_type(), ast_rtp_set_rtpmap_type(), ast_rtp_unset_m_type(), and process_sdp().

#define RED_MAX_GENERATION   5

T.140 Redundancy Maxium number of generations

Definition at line 55 of file rtp.h.

Referenced by process_sdp().


Typedef Documentation

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

RTP callback structure

Definition at line 124 of file rtp.h.


Enumeration Type Documentation

enum ast_rtp_get_result

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

Definition at line 63 of file rtp.h.

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

enum ast_rtp_options

Enumerator:
AST_RTP_OPT_G726_NONSTANDARD 

Definition at line 59 of file rtp.h.

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

enum ast_rtp_qos_vars

Variables used in ast_rtcp_get function.

Enumerator:
AST_RTP_TXCOUNT 
AST_RTP_RXCOUNT 
AST_RTP_TXJITTER 
AST_RTP_RXJITTER 
AST_RTP_RXPLOSS 
AST_RTP_TXPLOSS 
AST_RTP_RTT 

Definition at line 73 of file rtp.h.

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

enum ast_rtp_quality_type

Enumerator:
RTPQOS_SUMMARY 
RTPQOS_JITTER 
RTPQOS_LOSS 
RTPQOS_RTT 

Definition at line 103 of file rtp.h.

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


Function Documentation

int ast_rtcp_fd ( struct ast_rtp rtp  ) 

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

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

struct ast_frame* ast_rtcp_read ( struct ast_rtp rtp  ) 

Definition at line 1130 of file rtp.c.

References ast_rtcp::accumulated_transit, 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().

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

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

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

03196 {
03197    struct ast_rtp *rtp = data;
03198    int res;
03199 
03200    rtp->rtcp->sendfur = 1;
03201    res = ast_rtcp_write(data);
03202    
03203    return res;
03204 }

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

Referenced by process_sdp().

00497 {
00498    return sizeof(struct ast_rtp);
00499 }

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

References AST_BRIDGE_FAILED, AST_BRIDGE_FAILED_NOWARN, ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_check_hangup(), ast_codec_pref_getsize(), ast_debug, ast_log(), AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, ast_set_flag, ast_test_flag, ast_verb, bridge_native_loop(), bridge_p2p_loop(), ast_format_list::cur_ms, FLAG_HAS_DTMF, FLAG_P2P_NEED_DTMF, ast_rtp_protocol::get_codec, get_proto(), ast_rtp_protocol::get_rtp_info, ast_rtp_protocol::get_trtp_info, ast_rtp_protocol::get_vrtp_info, LOG_WARNING, ast_channel::name, ast_rtp::pref, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel_tech::send_digit_begin, ast_channel::tech, and ast_channel::tech_pvt.

04283 {
04284    struct ast_rtp *p0 = NULL, *p1 = NULL;    /* Audio RTP Channels */
04285    struct ast_rtp *vp0 = NULL, *vp1 = NULL;  /* Video RTP channels */
04286    struct ast_rtp *tp0 = NULL, *tp1 = NULL;  /* Text RTP channels */
04287    struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL;
04288    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;
04289    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;
04290    enum ast_bridge_result res = AST_BRIDGE_FAILED;
04291    int codec0 = 0, codec1 = 0;
04292    void *pvt0 = NULL, *pvt1 = NULL;
04293 
04294    /* Lock channels */
04295    ast_channel_lock(c0);
04296    while (ast_channel_trylock(c1)) {
04297       ast_channel_unlock(c0);
04298       usleep(1);
04299       ast_channel_lock(c0);
04300    }
04301 
04302    /* Ensure neither channel got hungup during lock avoidance */
04303    if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
04304       ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name);
04305       ast_channel_unlock(c0);
04306       ast_channel_unlock(c1);
04307       return AST_BRIDGE_FAILED;
04308    }
04309       
04310    /* Find channel driver interfaces */
04311    if (!(pr0 = get_proto(c0))) {
04312       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
04313       ast_channel_unlock(c0);
04314       ast_channel_unlock(c1);
04315       return AST_BRIDGE_FAILED;
04316    }
04317    if (!(pr1 = get_proto(c1))) {
04318       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
04319       ast_channel_unlock(c0);
04320       ast_channel_unlock(c1);
04321       return AST_BRIDGE_FAILED;
04322    }
04323 
04324    /* Get channel specific interface structures */
04325    pvt0 = c0->tech_pvt;
04326    pvt1 = c1->tech_pvt;
04327 
04328    /* Get audio and video interface (if native bridge is possible) */
04329    audio_p0_res = pr0->get_rtp_info(c0, &p0);
04330    video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
04331    text_p0_res = pr0->get_trtp_info ? pr0->get_trtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
04332    audio_p1_res = pr1->get_rtp_info(c1, &p1);
04333    video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
04334    text_p1_res = pr1->get_trtp_info ? pr1->get_trtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
04335 
04336    /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */
04337    if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE))
04338       audio_p0_res = AST_RTP_GET_FAILED;
04339    if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE))
04340       audio_p1_res = AST_RTP_GET_FAILED;
04341 
04342    /* Check if a bridge is possible (partial/native) */
04343    if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) {
04344       /* Somebody doesn't want to play... */
04345       ast_channel_unlock(c0);
04346       ast_channel_unlock(c1);
04347       return AST_BRIDGE_FAILED_NOWARN;
04348    }
04349 
04350    /* If we need to feed DTMF frames into the core then only do a partial native bridge */
04351    if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
04352       ast_set_flag(p0, FLAG_P2P_NEED_DTMF);
04353       audio_p0_res = AST_RTP_TRY_PARTIAL;
04354    }
04355 
04356    if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) {
04357       ast_set_flag(p1, FLAG_P2P_NEED_DTMF);
04358       audio_p1_res = AST_RTP_TRY_PARTIAL;
04359    }
04360 
04361    /* If both sides are not using the same method of DTMF transmission 
04362     * (ie: one is RFC2833, other is INFO... then we can not do direct media. 
04363     * --------------------------------------------------
04364     * | DTMF Mode |  HAS_DTMF  |  Accepts Begin Frames |
04365     * |-----------|------------|-----------------------|
04366     * | Inband    | False      | True                  |
04367     * | RFC2833   | True       | True                  |
04368     * | SIP INFO  | False      | False                 |
04369     * --------------------------------------------------
04370     * However, if DTMF from both channels is being monitored by the core, then
04371     * we can still do packet-to-packet bridging, because passing through the 
04372     * core will handle DTMF mode translation.
04373     */
04374    if ((ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) ||
04375       (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) {
04376       if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) {
04377          ast_channel_unlock(c0);
04378          ast_channel_unlock(c1);
04379          return AST_BRIDGE_FAILED_NOWARN;
04380       }
04381       audio_p0_res = AST_RTP_TRY_PARTIAL;
04382       audio_p1_res = AST_RTP_TRY_PARTIAL;
04383    }
04384 
04385    /* If we need to feed frames into the core don't do a P2P bridge */
04386    if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF)) ||
04387        (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF))) {
04388       ast_channel_unlock(c0);
04389       ast_channel_unlock(c1);
04390       return AST_BRIDGE_FAILED_NOWARN;
04391    }
04392 
04393    /* Get codecs from both sides */
04394    codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0;
04395    codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0;
04396    if (codec0 && codec1 && !(codec0 & codec1)) {
04397       /* Hey, we can't do native bridging if both parties speak different codecs */
04398       ast_debug(3, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1);
04399       ast_channel_unlock(c0);
04400       ast_channel_unlock(c1);
04401       return AST_BRIDGE_FAILED_NOWARN;
04402    }
04403 
04404    /* If either side can only do a partial bridge, then don't try for a true native bridge */
04405    if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) {
04406       struct ast_format_list fmt0, fmt1;
04407 
04408       /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */
04409       if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) {
04410          ast_debug(1, "Cannot packet2packet bridge - raw formats are incompatible\n");
04411          ast_channel_unlock(c0);
04412          ast_channel_unlock(c1);
04413          return AST_BRIDGE_FAILED_NOWARN;
04414       }
04415       /* They must also be using the same packetization */
04416       fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat);
04417       fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat);
04418       if (fmt0.cur_ms != fmt1.cur_ms) {
04419          ast_debug(1, "Cannot packet2packet bridge - packetization settings prevent it\n");
04420          ast_channel_unlock(c0);
04421          ast_channel_unlock(c1);
04422          return AST_BRIDGE_FAILED_NOWARN;
04423       }
04424 
04425       ast_verb(3, "Packet2Packet bridging %s and %s\n", c0->name, c1->name);
04426       res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1);
04427    } else {
04428       ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
04429       res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, tp0, tp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1);
04430    }
04431 
04432    return res;
04433 }

int ast_rtp_codec_getformat ( int  pt  ) 

get format from predefined dynamic payload format

Definition at line 3670 of file rtp.c.

References rtpPayloadType::code, and static_RTP_PT.

Referenced by process_sdp().

03671 {
03672    if (pt < 0 || pt > MAX_RTP_PT)
03673       return 0; /* bogus payload type */
03674 
03675    if (static_RTP_PT[pt].isAstFormat)
03676       return static_RTP_PT[pt].code;
03677    else
03678       return 0;
03679 }

struct ast_codec_pref* ast_rtp_codec_getpref ( struct ast_rtp rtp  ) 

Get codec preference.

Definition at line 3665 of file rtp.c.

References ast_rtp::pref.

Referenced by add_codec_to_sdp(), and process_sdp().

03666 {
03667    return &rtp->pref;
03668 }

void ast_rtp_codec_setpref ( struct ast_rtp rtp,
struct ast_codec_pref prefs 
)

Set codec preference.

Definition at line 3619 of file rtp.c.

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

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

03620 {
03621    struct ast_format_list current_format_old, current_format_new;
03622 
03623    /* if no packets have been sent through this session yet, then
03624     *  changing preferences does not require any extra work
03625     */
03626    if (rtp->lasttxformat == 0) {
03627       rtp->pref = *prefs;
03628       return;
03629    }
03630 
03631    current_format_old = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat);
03632 
03633    rtp->pref = *prefs;
03634 
03635    current_format_new = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat);
03636 
03637    /* if the framing desired for the current format has changed, we may have to create
03638     * or adjust the smoother for this session
03639     */
03640    if ((current_format_new.inc_ms != 0) &&
03641        (current_format_new.cur_ms != current_format_old.cur_ms)) {
03642       int new_size = (current_format_new.cur_ms * current_format_new.fr_len) / current_format_new.inc_ms;
03643 
03644       if (rtp->smoother) {
03645          ast_smoother_reconfigure(rtp->smoother, new_size);
03646          if (option_debug) {
03647             ast_log(LOG_DEBUG, "Adjusted smoother to %d ms and %d bytes\n", current_format_new.cur_ms, new_size);
03648          }
03649       } else {
03650          if (!(rtp->smoother = ast_smoother_new(new_size))) {
03651             ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size);
03652             return;
03653          }
03654          if (current_format_new.flags) {
03655             ast_smoother_set_flags(rtp->smoother, current_format_new.flags);
03656          }
03657          if (option_debug) {
03658             ast_log(LOG_DEBUG, "Created smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size);
03659          }
03660       }
03661    }
03662 
03663 }

void ast_rtp_destroy ( struct ast_rtp rtp  ) 

Destroy RTP session

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

02955 {
02956    if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) {
02957       /*Print some info on the call here */
02958       ast_verbose("  RTP-stats\n");
02959       ast_verbose("* Our Receiver:\n");
02960       ast_verbose("  SSRC:     %u\n", rtp->themssrc);
02961       ast_verbose("  Received packets: %u\n", rtp->rxcount);
02962       ast_verbose("  Lost packets:   %u\n", rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0);
02963       ast_verbose("  Jitter:      %.4f\n", rtp->rxjitter);
02964       ast_verbose("  Transit:     %.4f\n", rtp->rxtransit);
02965       ast_verbose("  RR-count:    %u\n", rtp->rtcp ? rtp->rtcp->rr_count : 0);
02966       ast_verbose("* Our Sender:\n");
02967       ast_verbose("  SSRC:     %u\n", rtp->ssrc);
02968       ast_verbose("  Sent packets:   %u\n", rtp->txcount);
02969       ast_verbose("  Lost packets:   %u\n", rtp->rtcp ? rtp->rtcp->reported_lost : 0);
02970       ast_verbose("  Jitter:      %u\n", rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int)65536.0) : 0);
02971       ast_verbose("  SR-count:    %u\n", rtp->rtcp ? rtp->rtcp->sr_count : 0);
02972       ast_verbose("  RTT:      %f\n", rtp->rtcp ? rtp->rtcp->rtt : 0);
02973    }
02974 
02975    manager_event(EVENT_FLAG_REPORTING, "RTPReceiverStat", "SSRC: %u\r\n"
02976                    "ReceivedPackets: %u\r\n"
02977                    "LostPackets: %u\r\n"
02978                    "Jitter: %.4f\r\n"
02979                    "Transit: %.4f\r\n"
02980                    "RRCount: %u\r\n",
02981                    rtp->themssrc,
02982                    rtp->rxcount,
02983                    rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0,
02984                    rtp->rxjitter,
02985                    rtp->rxtransit,
02986                    rtp->rtcp ? rtp->rtcp->rr_count : 0);
02987    manager_event(EVENT_FLAG_REPORTING, "RTPSenderStat", "SSRC: %u\r\n"
02988                    "SentPackets: %u\r\n"
02989                    "LostPackets: %u\r\n"
02990                    "Jitter: %u\r\n"
02991                    "SRCount: %u\r\n"
02992                    "RTT: %f\r\n",
02993                    rtp->ssrc,
02994                    rtp->txcount,
02995                    rtp->rtcp ? rtp->rtcp->reported_lost : 0,
02996                    rtp->rtcp ? rtp->rtcp->reported_jitter : 0,
02997                    rtp->rtcp ? rtp->rtcp->sr_count : 0,
02998                    rtp->rtcp ? rtp->rtcp->rtt : 0);
02999    if (rtp->smoother)
03000       ast_smoother_free(rtp->smoother);
03001    if (rtp->ioid)
03002       ast_io_remove(rtp->io, rtp->ioid);
03003    if (rtp->s > -1)
03004       close(rtp->s);
03005    if (rtp->rtcp) {
03006       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
03007       close(rtp->rtcp->s);
03008       ast_free(rtp->rtcp);
03009       rtp->rtcp=NULL;
03010    }
03011 #ifdef P2P_INTENSE
03012    ast_mutex_destroy(&rtp->bridge_lock);
03013 #endif
03014    ast_free(rtp);
03015 }

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

02024 {
02025    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
02026    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
02027    struct ast_rtp *tdestp = NULL, *tsrcp = NULL;      /* Text RTP channels */
02028    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
02029    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;
02030    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;
02031    int srccodec, destcodec, nat_active = 0;
02032 
02033    /* Lock channels */
02034    ast_channel_lock(c0);
02035    if (c1) {
02036       while (ast_channel_trylock(c1)) {
02037          ast_channel_unlock(c0);
02038          usleep(1);
02039          ast_channel_lock(c0);
02040       }
02041    }
02042 
02043    /* Find channel driver interfaces */
02044    destpr = get_proto(c0);
02045    if (c1)
02046       srcpr = get_proto(c1);
02047    if (!destpr) {
02048       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c0->name);
02049       ast_channel_unlock(c0);
02050       if (c1)
02051          ast_channel_unlock(c1);
02052       return -1;
02053    }
02054    if (!srcpr) {
02055       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c1 ? c1->name : "<unspecified>");
02056       ast_channel_unlock(c0);
02057       if (c1)
02058          ast_channel_unlock(c1);
02059       return -1;
02060    }
02061 
02062    /* Get audio, video  and text interface (if native bridge is possible) */
02063    audio_dest_res = destpr->get_rtp_info(c0, &destp);
02064    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(c0, &vdestp) : AST_RTP_GET_FAILED;
02065    text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(c0, &tdestp) : AST_RTP_GET_FAILED;
02066    if (srcpr) {
02067       audio_src_res = srcpr->get_rtp_info(c1, &srcp);
02068       video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(c1, &vsrcp) : AST_RTP_GET_FAILED;
02069       text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(c1, &tsrcp) : AST_RTP_GET_FAILED;
02070    }
02071 
02072    /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
02073    if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE)) {
02074       /* Somebody doesn't want to play... */
02075       ast_channel_unlock(c0);
02076       if (c1)
02077          ast_channel_unlock(c1);
02078       return -1;
02079    }
02080    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)
02081       srccodec = srcpr->get_codec(c1);
02082    else
02083       srccodec = 0;
02084    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)
02085       destcodec = destpr->get_codec(c0);
02086    else
02087       destcodec = 0;
02088    /* Ensure we have at least one matching codec */
02089    if (srcp && !(srccodec & destcodec)) {
02090       ast_channel_unlock(c0);
02091       ast_channel_unlock(c1);
02092       return 0;
02093    }
02094    /* Consider empty media as non-existent */
02095    if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr)
02096       srcp = NULL;
02097    if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
02098       nat_active = 1;
02099    /* Bridge media early */
02100    if (destpr->set_rtp_peer(c0, srcp, vsrcp, tsrcp, srccodec, nat_active))
02101       ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
02102    ast_channel_unlock(c0);
02103    if (c1)
02104       ast_channel_unlock(c1);
02105    ast_debug(1, "Setting early bridge SDP of '%s' with that of '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
02106    return 0;
02107 }

int ast_rtp_fd ( struct ast_rtp rtp  ) 

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

00721 {
00722    return rtp->s;
00723 }

struct ast_rtp* ast_rtp_get_bridged ( struct ast_rtp rtp  ) 

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

02596 {
02597    struct ast_rtp *bridged = NULL;
02598 
02599    rtp_bridge_lock(rtp);
02600    bridged = rtp->bridged;
02601    rtp_bridge_unlock(rtp);
02602 
02603    return bridged;
02604 }

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

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

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

02247 {
02248    int pt;
02249    
02250    rtp_bridge_lock(rtp);
02251    
02252    *astFormats = *nonAstFormats = 0;
02253    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02254       if (rtp->current_RTP_PT[pt].isAstFormat) {
02255          *astFormats |= rtp->current_RTP_PT[pt].code;
02256       } else {
02257          *nonAstFormats |= rtp->current_RTP_PT[pt].code;
02258       }
02259    }
02260 
02261    rtp_bridge_unlock(rtp);
02262 }

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

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

02578 {
02579    if ((them->sin_family != AF_INET) ||
02580       (them->sin_port != rtp->them.sin_port) ||
02581       (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
02582       them->sin_family = AF_INET;
02583       them->sin_port = rtp->them.sin_port;
02584       them->sin_addr = rtp->them.sin_addr;
02585       return 1;
02586    }
02587    return 0;
02588 }

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

References __ast_rtp_get_qos().

Referenced by acf_channel_read().

02717 {
02718    double value;
02719    int found;
02720 
02721    value = __ast_rtp_get_qos(rtp, qos, &found);
02722 
02723    if (!found)
02724       return -1;
02725 
02726    snprintf(buf, buflen, "%.0lf", value);
02727 
02728    return 0;
02729 }

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

Return RTP and RTCP QoS values.

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

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

02651 {
02652    if (rtp == NULL) {
02653       if (option_debug > 1)
02654          ast_log(LOG_DEBUG, "NO RTP Structure? Kidding me? \n");
02655       return 0;
02656    }
02657    if (option_debug > 1 && rtp->rtcp == NULL) {
02658       ast_log(LOG_DEBUG, "NO RTCP structure. Maybe in RTP p2p bridging mode? \n");
02659    }
02660 
02661    switch (value) {
02662    case AST_RTP_TXCOUNT:
02663       return (unsigned int) rtp->txcount;
02664    case AST_RTP_RXCOUNT:
02665       return (unsigned int) rtp->rxcount;
02666    case AST_RTP_TXJITTER:
02667       return (unsigned int) (rtp->rxjitter * 100.0);
02668    case AST_RTP_RXJITTER:
02669       return (unsigned int) (rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int) 65536.0) : 0);
02670    case AST_RTP_RXPLOSS:
02671       return rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0;
02672    case AST_RTP_TXPLOSS:
02673       return rtp->rtcp ? rtp->rtcp->reported_lost : 0;
02674    case AST_RTP_RTT:
02675       return (unsigned int) (rtp->rtcp ? (rtp->rtcp->rtt * 100) : 0);
02676    }
02677    return 0;   /* To make the compiler happy */
02678 }

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

02924 {
02925    if (qual && rtp) {
02926       qual->local_ssrc   = rtp->ssrc;
02927       qual->local_jitter = rtp->rxjitter;
02928       qual->local_count  = rtp->rxcount;
02929       qual->remote_ssrc  = rtp->themssrc;
02930       qual->remote_count = rtp->txcount;
02931 
02932       if (rtp->rtcp) {
02933          qual->local_lostpackets  = rtp->rtcp->expected_prior - rtp->rtcp->received_prior;
02934          qual->remote_lostpackets = rtp->rtcp->reported_lost;
02935          qual->remote_jitter      = rtp->rtcp->reported_jitter / 65536.0;
02936          qual->rtt                = rtp->rtcp->rtt;
02937       }
02938    }
02939 
02940    switch (qtype) {
02941    case RTPQOS_SUMMARY:
02942       return __ast_rtp_get_quality(rtp);
02943    case RTPQOS_JITTER:
02944       return __ast_rtp_get_quality_jitter(rtp);
02945    case RTPQOS_LOSS:
02946       return __ast_rtp_get_quality_loss(rtp);
02947    case RTPQOS_RTT:
02948       return __ast_rtp_get_quality_rtt(rtp);
02949    }
02950 
02951    return NULL;
02952 }

int ast_rtp_get_rtpholdtimeout ( struct ast_rtp rtp  ) 

Get rtp hold timeout.

Definition at line 775 of file rtp.c.

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

Referenced by check_rtp_timeout().

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

int ast_rtp_get_rtpkeepalive ( struct ast_rtp rtp  ) 

Get RTP keepalive interval.

Definition at line 783 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by check_rtp_timeout().

00784 {
00785    return rtp->rtpkeepalive;
00786 }

int ast_rtp_get_rtptimeout ( struct ast_rtp rtp  ) 

Get rtp timeout.

Definition at line 767 of file rtp.c.

References ast_rtp::rtptimeout.

Referenced by check_rtp_timeout().

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

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

Definition at line 2590 of file rtp.c.

References ast_rtp::us.

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

02591 {
02592    *us = rtp->us;
02593 }

int ast_rtp_getnat ( struct ast_rtp rtp  ) 

Definition at line 803 of file rtp.c.

References ast_test_flag, and FLAG_NAT_ACTIVE.

Referenced by sip_get_rtp_peer().

00804 {
00805    return ast_test_flag(rtp, FLAG_NAT_ACTIVE);
00806 }

void ast_rtp_init ( void   ) 

Initialize the RTP system in Asterisk.

Definition at line 4821 of file rtp.c.

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

Referenced by main().

04822 {
04823    ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
04824    __ast_rtp_reload(0);
04825 }

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

02287 {
02288    int pt = 0;
02289 
02290    rtp_bridge_lock(rtp);
02291 
02292    if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
02293       code == rtp->rtp_lookup_code_cache_code) {
02294       /* Use our cached mapping, to avoid the overhead of the loop below */
02295       pt = rtp->rtp_lookup_code_cache_result;
02296       rtp_bridge_unlock(rtp);
02297       return pt;
02298    }
02299 
02300    /* Check the dynamic list first */
02301    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02302       if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
02303          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
02304          rtp->rtp_lookup_code_cache_code = code;
02305          rtp->rtp_lookup_code_cache_result = pt;
02306          rtp_bridge_unlock(rtp);
02307          return pt;
02308       }
02309    }
02310 
02311    /* Then the static list */
02312    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02313       if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) {
02314          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
02315          rtp->rtp_lookup_code_cache_code = code;
02316          rtp->rtp_lookup_code_cache_result = pt;
02317          rtp_bridge_unlock(rtp);
02318          return pt;
02319       }
02320    }
02321 
02322    rtp_bridge_unlock(rtp);
02323 
02324    return -1;
02325 }

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

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

Referenced by process_sdp().

02348 {
02349    int format;
02350    unsigned len;
02351    char *end = buf;
02352    char *start = buf;
02353 
02354    if (!buf || !size)
02355       return NULL;
02356 
02357    snprintf(end, size, "0x%x (", capability);
02358 
02359    len = strlen(end);
02360    end += len;
02361    size -= len;
02362    start = end;
02363 
02364    for (format = 1; format < AST_RTP_MAX; format <<= 1) {
02365       if (capability & format) {
02366          const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options);
02367 
02368          snprintf(end, size, "%s|", name);
02369          len = strlen(end);
02370          end += len;
02371          size -= len;
02372       }
02373    }
02374 
02375    if (start == end)
02376       ast_copy_string(start, "nothing)", size); 
02377    else if (size > 1)
02378       *(end -1) = ')';
02379    
02380    return buf;
02381 }

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

References ARRAY_LEN, AST_FORMAT_G726_AAL2, AST_RTP_OPT_G726_NONSTANDARD, rtpPayloadType::code, mimeTypes, and payloadType.

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

02329 {
02330    unsigned int i;
02331 
02332    for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
02333       if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
02334          if (isAstFormat &&
02335              (code == AST_FORMAT_G726_AAL2) &&
02336              (options & AST_RTP_OPT_G726_NONSTANDARD))
02337             return "G726-32";
02338          else
02339             return mimeTypes[i].subtype;
02340       }
02341    }
02342 
02343    return "";
02344 }

struct rtpPayloadType ast_rtp_lookup_pt ( struct ast_rtp rtp,
int  pt 
)

Mapping between RTP payload format codes and Asterisk codes:.

Definition at line 2264 of file rtp.c.

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

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

02265 {
02266    struct rtpPayloadType result;
02267 
02268    result.isAstFormat = result.code = 0;
02269 
02270    if (pt < 0 || pt > MAX_RTP_PT) 
02271       return result; /* bogus payload type */
02272 
02273    /* Start with negotiated codecs */
02274    rtp_bridge_lock(rtp);
02275    result = rtp->current_RTP_PT[pt];
02276    rtp_bridge_unlock(rtp);
02277 
02278    /* If it doesn't exist, check our static RTP type list, just in case */
02279    if (!result.code) 
02280       result = static_RTP_PT[pt];
02281 
02282    return result;
02283 }

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

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

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

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

Initializate a RTP session.

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

Definition at line 2541 of file rtp.c.

References ast_rtp_new_with_bindaddr(), io, and sched.

02542 {
02543    struct in_addr ia;
02544 
02545    memset(&ia, 0, sizeof(ia));
02546    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
02547 }

void ast_rtp_new_init ( struct ast_rtp rtp  ) 

Initialize a new RTP structure.

reload rtp configuration

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

02433 {
02434 #ifdef P2P_INTENSE
02435    ast_mutex_init(&rtp->bridge_lock);
02436 #endif
02437 
02438    rtp->them.sin_family = AF_INET;
02439    rtp->us.sin_family = AF_INET;
02440    rtp->ssrc = ast_random();
02441    rtp->seqno = ast_random() & 0xffff;
02442    ast_set_flag(rtp, FLAG_HAS_DTMF);
02443    rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN);
02444 }

void ast_rtp_new_source ( struct ast_rtp rtp  ) 

Definition at line 2554 of file rtp.c.

References ast_rtp::set_marker_bit.

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

02555 {
02556    if (rtp) {
02557       rtp->set_marker_bit = 1;
02558    }
02559    return;
02560 }

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

Initializate a RTP session using an in_addr structure.

This fuction gets called by ast_rtp_new().

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

Definition at line 2446 of file rtp.c.

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

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

02447 {
02448    struct ast_rtp *rtp;
02449    int x;
02450    int startplace;
02451    
02452    if (!(rtp = ast_calloc(1, sizeof(*rtp))))
02453       return NULL;
02454 
02455    ast_rtp_new_init(rtp);
02456 
02457    rtp->s = rtp_socket("RTP");
02458    if (rtp->s < 0)
02459       goto fail;
02460    if (sched && rtcpenable) {
02461       rtp->sched = sched;
02462       rtp->rtcp = ast_rtcp_new();
02463    }
02464    
02465    /*
02466     * Try to bind the RTP port, x, and possibly the RTCP port, x+1 as well.
02467     * Start from a random (even, by RTP spec) port number, and
02468     * iterate until success or no ports are available.
02469     * Note that the requirement of RTP port being even, or RTCP being the
02470     * next one, cannot be enforced in presence of a NAT box because the
02471     * mapping is not under our control.
02472     */
02473    x = (rtpend == rtpstart) ? rtpstart : (ast_random() % (rtpend - rtpstart)) + rtpstart;
02474    x = x & ~1;    /* make it an even number */
02475    startplace = x;      /* remember the starting point */
02476    /* this is constant across the loop */
02477    rtp->us.sin_addr = addr;
02478    if (rtp->rtcp)
02479       rtp->rtcp->us.sin_addr = addr;
02480    for (;;) {
02481       rtp->us.sin_port = htons(x);
02482       if (!bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) {
02483          /* bind succeeded, if no rtcp then we are done */
02484          if (!rtp->rtcp)
02485             break;
02486          /* have rtcp, try to bind it */
02487          rtp->rtcp->us.sin_port = htons(x + 1);
02488          if (!bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))
02489             break;   /* success again, we are really done */
02490          /*
02491           * RTCP bind failed, so close and recreate the
02492           * already bound RTP socket for the next round.
02493           */
02494          close(rtp->s);
02495          rtp->s = rtp_socket("RTP");
02496          if (rtp->s < 0)
02497             goto fail;
02498       }
02499       /*
02500        * If we get here, there was an error in one of the bind()
02501        * calls, so make sure it is nothing unexpected.
02502        */
02503       if (errno != EADDRINUSE) {
02504          /* We got an error that wasn't expected, abort! */
02505          ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno));
02506          goto fail;
02507       }
02508       /*
02509        * One of the ports is in use. For the next iteration,
02510        * increment by two and handle wraparound.
02511        * If we reach the starting point, then declare failure.
02512        */
02513       x += 2;
02514       if (x > rtpend)
02515          x = (rtpstart + 1) & ~1;
02516       if (x == startplace) {
02517          ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n");
02518          goto fail;
02519       }
02520    }
02521    rtp->sched = sched;
02522    rtp->io = io;
02523    if (callbackmode) {
02524       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
02525       ast_set_flag(rtp, FLAG_CALLBACK_MODE);
02526    }
02527    ast_rtp_pt_default(rtp);
02528    return rtp;
02529 
02530 fail:
02531    if (rtp->s >= 0)
02532       close(rtp->s);
02533    if (rtp->rtcp) {
02534       close(rtp->rtcp->s);
02535       ast_free(rtp->rtcp);
02536    }
02537    ast_free(rtp);
02538    return NULL;
02539 }

int ast_rtp_proto_register ( struct ast_rtp_protocol proto  ) 

Register an RTP channel client.

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

03782 {
03783    struct ast_rtp_protocol *cur;
03784 
03785    AST_RWLIST_WRLOCK(&protos);
03786    AST_RWLIST_TRAVERSE(&protos, cur, list) { 
03787       if (!strcmp(cur->type, proto->type)) {
03788          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
03789          AST_RWLIST_UNLOCK(&protos);
03790          return -1;
03791       }
03792    }
03793    AST_RWLIST_INSERT_HEAD(&protos, proto, list);
03794    AST_RWLIST_UNLOCK(&protos);
03795    
03796    return 0;
03797 }

void ast_rtp_proto_unregister ( struct ast_rtp_protocol proto  ) 

Unregister an RTP channel client.

Definition at line 3773 of file rtp.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by load_module(), and unload_module().

03774 {
03775    AST_RWLIST_WRLOCK(&protos);
03776    AST_RWLIST_REMOVE(&protos, proto, list);
03777    AST_RWLIST_UNLOCK(&protos);
03778 }

void ast_rtp_pt_clear ( struct ast_rtp rtp  ) 

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

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

01948 {
01949    int i;
01950 
01951    if (!rtp)
01952       return;
01953 
01954    rtp_bridge_lock(rtp);
01955 
01956    for (i = 0; i < MAX_RTP_PT; ++i) {
01957       rtp->current_RTP_PT[i].isAstFormat = 0;
01958       rtp->current_RTP_PT[i].code = 0;
01959    }
01960 
01961    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01962    rtp->rtp_lookup_code_cache_code = 0;
01963    rtp->rtp_lookup_code_cache_result = 0;
01964 
01965    rtp_bridge_unlock(rtp);
01966 }

void ast_rtp_pt_copy ( struct ast_rtp dest,
struct ast_rtp src 
)

Copy payload types between RTP structures.

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

01988 {
01989    unsigned int i;
01990 
01991    rtp_bridge_lock(dest);
01992    rtp_bridge_lock(src);
01993 
01994    for (i = 0; i < MAX_RTP_PT; ++i) {
01995       dest->current_RTP_PT[i].isAstFormat = 
01996          src->current_RTP_PT[i].isAstFormat;
01997       dest->current_RTP_PT[i].code = 
01998          src->current_RTP_PT[i].code; 
01999    }
02000    dest->rtp_lookup_code_cache_isAstFormat = 0;
02001    dest->rtp_lookup_code_cache_code = 0;
02002    dest->rtp_lookup_code_cache_result = 0;
02003 
02004    rtp_bridge_unlock(src);
02005    rtp_bridge_unlock(dest);
02006 }

void ast_rtp_pt_default ( struct ast_rtp rtp  ) 

Set payload types to defaults.

Definition at line 1968 of file rtp.c.

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

01969 {
01970    int i;
01971 
01972    rtp_bridge_lock(rtp);
01973 
01974    /* Initialize to default payload types */
01975    for (i = 0; i < MAX_RTP_PT; ++i) {
01976       rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
01977       rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
01978    }
01979 
01980    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01981    rtp->rtp_lookup_code_cache_code = 0;
01982    rtp->rtp_lookup_code_cache_result = 0;
01983 
01984    rtp_bridge_unlock(rtp);
01985 }

struct ast_frame* ast_rtp_read ( struct ast_rtp rtp  ) 

Definition at line 1525 of file rtp.c.

References 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_sched_add(), ast_set_flag, ast_verbose, bridge_p2p_rtp_write(), ast_rtp::bridged, calc_rxstamp(), rtpPayloadType::code, ast_rtp::cycles, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp::dtmfcount, errno, ext, ast_rtp::f, f, FLAG_NAT_ACTIVE, ast_frame::frametype, rtpPayloadType::isAstFormat, ast_rtp::lastevent, ast_rtp::lastrxformat, ast_rtp::lastrxseqno, ast_rtp::lastrxts, ast_frame::len, len(), LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, ast_rtp::nat, ast_frame::offset, option_debug, process_cisco_dtmf(), process_rfc2833(), process_rfc3389(), ast_frame::ptr, ast_rtp::rawdata, ast_rtp::resp, ast_rtp::rtcp, rtp_debug_test_addr(), RTP_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_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().

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

int ast_rtp_reload ( void   ) 

Initialize RTP subsystem

Definition at line 4815 of file rtp.c.

References __ast_rtp_reload().

04816 {
04817    return __ast_rtp_reload(1);
04818 }

void ast_rtp_reset ( struct ast_rtp rtp  ) 

Definition at line 2627 of file rtp.c.

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

02628 {
02629    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
02630    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
02631    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
02632    rtp->lastts = 0;
02633    rtp->lastdigitts = 0;
02634    rtp->lastrxts = 0;
02635    rtp->lastividtimestamp = 0;
02636    rtp->lastovidtimestamp = 0;
02637    rtp->lastitexttimestamp = 0;
02638    rtp->lastotexttimestamp = 0;
02639    rtp->lasteventseqn = 0;
02640    rtp->lastevent = 0;
02641    rtp->lasttxformat = 0;
02642    rtp->lastrxformat = 0;
02643    rtp->dtmfcount = 0;
02644    rtp->dtmfsamples = 0;
02645    rtp->seqno = 0;
02646    rtp->rxseqno = 0;
02647 }

int ast_rtp_sendcng ( struct ast_rtp rtp,
int  level 
)

generate comfort noice (CNG)

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

03471 {
03472    unsigned int *rtpheader;
03473    int hdrlen = 12;
03474    int res;
03475    int payload;
03476    char data[256];
03477    level = 127 - (level & 0x7f);
03478    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN);
03479 
03480    /* If we have no peer, return immediately */ 
03481    if (!rtp->them.sin_addr.s_addr)
03482       return 0;
03483 
03484    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
03485 
03486    /* Get a pointer to the header */
03487    rtpheader = (unsigned int *)data;
03488    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
03489    rtpheader[1] = htonl(rtp->lastts);
03490    rtpheader[2] = htonl(rtp->ssrc); 
03491    data[12] = level;
03492    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
03493       res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
03494       if (res <0) 
03495          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));
03496       if (rtp_debug_test_addr(&rtp->them))
03497          ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n"
03498                , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen);         
03499          
03500    }
03501    return 0;
03502 }

int ast_rtp_senddigit_begin ( struct ast_rtp rtp,
char  digit 
)

Send begin frames for DTMF.

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

03038 {
03039    unsigned int *rtpheader;
03040    int hdrlen = 12, res = 0, i = 0, payload = 0;
03041    char data[256];
03042 
03043    if ((digit <= '9') && (digit >= '0'))
03044       digit -= '0';
03045    else if (digit == '*')
03046       digit = 10;
03047    else if (digit == '#')
03048       digit = 11;
03049    else if ((digit >= 'A') && (digit <= 'D'))
03050       digit = digit - 'A' + 12;
03051    else if ((digit >= 'a') && (digit <= 'd'))
03052       digit = digit - 'a' + 12;
03053    else {
03054       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
03055       return 0;
03056    }
03057 
03058    /* If we have no peer, return immediately */ 
03059    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
03060       return 0;
03061 
03062    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF);
03063 
03064    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
03065    rtp->send_duration = 160;
03066    rtp->lastdigitts = rtp->lastts + rtp->send_duration;
03067    
03068    /* Get a pointer to the header */
03069    rtpheader = (unsigned int *)data;
03070    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
03071    rtpheader[1] = htonl(rtp->lastdigitts);
03072    rtpheader[2] = htonl(rtp->ssrc); 
03073 
03074    for (i = 0; i < 2; i++) {
03075       rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
03076       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
03077       if (res < 0) 
03078          ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n",
03079             ast_inet_ntoa(rtp->them.sin_addr),
03080             ntohs(rtp->them.sin_port), strerror(errno));
03081       if (rtp_debug_test_addr(&rtp->them))
03082          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
03083                 ast_inet_ntoa(rtp->them.sin_addr),
03084                 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
03085       /* Increment sequence number */
03086       rtp->seqno++;
03087       /* Increment duration */
03088       rtp->send_duration += 160;
03089       /* Clear marker bit and set seqno */
03090       rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
03091    }
03092 
03093    /* Since we received a begin, we can safely store the digit and disable any compensation */
03094    rtp->sending_digit = 1;
03095    rtp->send_digit = digit;
03096    rtp->send_payload = payload;
03097 
03098    return 0;
03099 }

int ast_rtp_senddigit_end ( struct ast_rtp rtp,
char  digit 
)

void ast_rtp_set_callback ( struct ast_rtp rtp,
ast_rtp_callback  callback 
)

Definition at line 793 of file rtp.c.

References ast_rtp::callback.

Referenced by start_rtp().

00794 {
00795    rtp->callback = callback;
00796 }

void ast_rtp_set_data ( struct ast_rtp rtp,
void *  data 
)

Definition at line 788 of file rtp.c.

References ast_rtp::data.

Referenced by start_rtp().

00789 {
00790    rtp->data = data;
00791 }

void ast_rtp_set_m_type ( struct ast_rtp rtp,
int  pt 
)

Activate payload type.

Definition at line 2186 of file rtp.c.

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

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

02187 {
02188    if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 
02189       return; /* bogus payload type */
02190 
02191    rtp_bridge_lock(rtp);
02192    rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
02193    rtp_bridge_unlock(rtp);
02194 } 

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

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

02563 {
02564    rtp->them.sin_port = them->sin_port;
02565    rtp->them.sin_addr = them->sin_addr;
02566    if (rtp->rtcp) {
02567       int h = ntohs(them->sin_port);
02568       rtp->rtcp->them.sin_port = htons(h + 1);
02569       rtp->rtcp->them.sin_addr = them->sin_addr;
02570    }
02571    rtp->rxseqno = 0;
02572    /* If strict RTP protection is enabled switch back to the learn state so we don't drop packets from above */
02573    if (strictrtp)
02574       rtp->strict_rtp_state = STRICT_RTP_LEARN;
02575 }

void ast_rtp_set_rtpholdtimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp hold timeout.

Definition at line 755 of file rtp.c.

References ast_rtp::rtpholdtimeout.

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

00756 {
00757    rtp->rtpholdtimeout = timeout;
00758 }

void ast_rtp_set_rtpkeepalive ( struct ast_rtp rtp,
int  period 
)

set RTP keepalive interval

Definition at line 761 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by create_addr_from_peer(), and sip_alloc().

00762 {
00763    rtp->rtpkeepalive = period;
00764 }

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

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

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

Definition at line 2213 of file rtp.c.

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

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

02216 {
02217    unsigned int i;
02218    int found = 0;
02219 
02220    if (pt < 0 || pt > MAX_RTP_PT) 
02221       return -1; /* bogus payload type */
02222    
02223    rtp_bridge_lock(rtp);
02224 
02225    for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
02226       if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
02227           strcasecmp(mimeType, mimeTypes[i].type) == 0) {
02228          found = 1;
02229          rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
02230          if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) &&
02231              mimeTypes[i].payloadType.isAstFormat &&
02232              (options & AST_RTP_OPT_G726_NONSTANDARD))
02233             rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2;
02234          break;
02235       }
02236    }
02237 
02238    rtp_bridge_unlock(rtp);
02239 
02240    return (found ? 0 : -1);
02241 } 

void ast_rtp_set_rtptimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp timeout.

Definition at line 749 of file rtp.c.

References ast_rtp::rtptimeout.

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

00750 {
00751    rtp->rtptimeout = timeout;
00752 }

void ast_rtp_set_rtptimers_onhold ( struct ast_rtp rtp  ) 

Definition at line 742 of file rtp.c.

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

Referenced by handle_response_invite().

00743 {
00744    rtp->rtptimeout = (-1) * rtp->rtptimeout;
00745    rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout;
00746 }

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

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

Referenced by handle_request_bye(), and sip_hangup().

02731                                                                      {
02732    char *audioqos;
02733    char *audioqos_jitter;
02734    char *audioqos_loss;
02735    char *audioqos_rtt;
02736    struct ast_channel *bridge;
02737 
02738    if (!rtp || !chan)
02739       return;
02740 
02741    bridge = ast_bridged_channel(chan);
02742 
02743    audioqos        = ast_rtp_get_quality(rtp, NULL, RTPQOS_SUMMARY);
02744    audioqos_jitter = ast_rtp_get_quality(rtp, NULL, RTPQOS_JITTER);
02745    audioqos_loss   = ast_rtp_get_quality(rtp, NULL, RTPQOS_LOSS);
02746    audioqos_rtt    = ast_rtp_get_quality(rtp, NULL, RTPQOS_RTT);
02747 
02748    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOS", audioqos);
02749    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSJITTER", audioqos_jitter);
02750    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSLOSS", audioqos_loss);
02751    pbx_builtin_setvar_helper(chan, "RTPAUDIOQOSRTT", audioqos_rtt);
02752 
02753    if (!bridge)
02754       return;
02755 
02756    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSBRIDGED", audioqos);
02757    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSJITTERBRIDGED", audioqos_jitter);
02758    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSLOSSBRIDGED", audioqos_loss);
02759    pbx_builtin_setvar_helper(bridge, "RTPAUDIOQOSRTTBRIDGED", audioqos_rtt);
02760 }

void ast_rtp_setdtmf ( struct ast_rtp rtp,
int  dtmf 
)

Indicate whether this RTP session is carrying DTMF or not.

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

00809 {
00810    ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF);
00811 }

void ast_rtp_setdtmfcompensate ( struct ast_rtp rtp,
int  compensate 
)

Compensate for devices that send RFC2833 packets all at once.

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

00814 {
00815    ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE);
00816 }

void ast_rtp_setnat ( struct ast_rtp rtp,
int  nat 
)

Definition at line 798 of file rtp.c.

References ast_rtp::nat.

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

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

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

Definition at line 2549 of file rtp.c.

References ast_netsock_set_qos(), and ast_rtp::s.

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

02550 {
02551    return ast_netsock_set_qos(rtp->s, type_of_service, class_of_service, desc);
02552 }

void ast_rtp_setstun ( struct ast_rtp rtp,
int  stun_enable 
)

Enable STUN capability.

Definition at line 818 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_STUN.

Referenced by gtalk_new().

00819 {
00820    ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN);
00821 }

void ast_rtp_stop ( struct ast_rtp rtp  ) 

Stop RTP session, do not destroy structure

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

02607 {
02608    if (rtp->rtcp) {
02609       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02610    }
02611    if (rtp->red) {
02612       AST_SCHED_DEL(rtp->sched, rtp->red->schedid);
02613       free(rtp->red);
02614       rtp->red = NULL;
02615    }
02616 
02617    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
02618    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
02619    if (rtp->rtcp) {
02620       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
02621       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
02622    }
02623    
02624    ast_clear_flag(rtp, FLAG_P2P_SENT_MARK);
02625 }

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

References ast_stun_request(), and ast_rtp::s.

Referenced by gtalk_update_stun(), and jingle_update_stun().

00703 {
00704    ast_stun_request(rtp->s, suggestion, username, NULL);
00705 }

void ast_rtp_unset_m_type ( struct ast_rtp rtp,
int  pt 
)

clear payload type

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

02199 {
02200    if (pt < 0 || pt > MAX_RTP_PT)
02201       return; /* bogus payload type */
02202 
02203    rtp_bridge_lock(rtp);
02204    rtp->current_RTP_PT[pt].isAstFormat = 0;
02205    rtp->current_RTP_PT[pt].code = 0;
02206    rtp_bridge_unlock(rtp);
02207 }

int ast_rtp_write ( struct ast_rtp rtp,
struct ast_frame f 
)

Definition at line 3681 of file rtp.c.

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

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

03682 {
03683    struct ast_frame *f;
03684    int codec;
03685    int hdrlen = 12;
03686    int subclass;
03687    
03688 
03689    /* If we have no peer, return immediately */ 
03690    if (!rtp->them.sin_addr.s_addr)
03691       return 0;
03692 
03693    /* If there is no data length, return immediately */
03694    if (!_f->datalen && !rtp->red)
03695       return 0;
03696    
03697    /* Make sure we have enough space for RTP header */
03698    if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO) && (_f->frametype != AST_FRAME_TEXT)) {
03699       ast_log(LOG_WARNING, "RTP can only send voice, video and text\n");
03700       return -1;
03701    }
03702 
03703    if (rtp->red) {
03704       /* return 0; */
03705       /* no primary data or generations to send */
03706       if ((_f = red_t140_to_red(rtp->red)) == NULL) 
03707          return 0;
03708    }
03709 
03710    /* The bottom bit of a video subclass contains the marker bit */
03711    subclass = _f->subclass;
03712    if (_f->frametype == AST_FRAME_VIDEO)
03713       subclass &= ~0x1;
03714 
03715    codec = ast_rtp_lookup_code(rtp, 1, subclass);
03716    if (codec < 0) {
03717       ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass));
03718       return -1;
03719    }
03720 
03721    if (rtp->lasttxformat != subclass) {
03722       /* New format, reset the smoother */
03723       ast_debug(1, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
03724       rtp->lasttxformat = subclass;
03725       if (rtp->smoother)
03726          ast_smoother_free(rtp->smoother);
03727       rtp->smoother = NULL;
03728    }
03729 
03730    if (!rtp->smoother && subclass != AST_FORMAT_SPEEX && subclass != AST_FORMAT_G723_1) {
03731       struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass);
03732       if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */
03733          if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
03734             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));
03735             return -1;
03736          }
03737          if (fmt.flags)
03738             ast_smoother_set_flags(rtp->smoother, fmt.flags);
03739          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));
03740       }
03741    }
03742    if (rtp->smoother) {
03743       if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) {
03744          ast_smoother_feed_be(rtp->smoother, _f);
03745       } else {
03746          ast_smoother_feed(rtp->smoother, _f);
03747       }
03748 
03749       while ((f = ast_smoother_read(rtp->smoother)) && (f->data.ptr)) {
03750          if (f->subclass == AST_FORMAT_G722) {
03751             /* G.722 is silllllllllllllly */
03752             f->samples /= 2;
03753          }
03754 
03755          ast_rtp_raw_write(rtp, f, codec);
03756       }
03757    } else {
03758       /* Don't buffer outgoing frames; send them one-per-packet: */
03759       if (_f->offset < hdrlen) 
03760          f = ast_frdup(_f);   /*! \bug XXX this might never be free'd. Why do we do this? */
03761       else
03762          f = _f;
03763       if (f->data.ptr)
03764          ast_rtp_raw_write(rtp, f, codec);
03765       if (f != _f)
03766          ast_frfree(f);
03767    }
03768       
03769    return 0;
03770 }

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

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

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

Definition at line 636 of file rtp.c.

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

Referenced by ast_rtp_stun_request(), and ast_sip_ouraddrfor().

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

void red_buffer_t140 ( struct ast_rtp rtp,
struct ast_frame f 
)

Buffer t.140 data.

Parameters:
rtp 
f frame

Definition at line 4925 of file rtp.c.

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

Referenced by sip_write().

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

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

Initalize t.140 redudancy.

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

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

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


Generated on Fri Jul 24 00:41:58 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7