Thu Jul 9 13:41:31 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

Typedefs

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

Enumerations

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

Functions

int ast_rtcp_fd (struct ast_rtp *rtp)
ast_frameast_rtcp_read (struct ast_rtp *rtp)
int ast_rtcp_send_h261fur (void *data)
 Send an H.261 fast update request. Some devices need this rather than the XML message in SIP.
size_t ast_rtp_alloc_size (void)
 Get the amount of space required to hold an RTP session.
int ast_rtp_bridge (struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
 The RTP bridge.
int ast_rtp_codec_getformat (int pt)
 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)
char * ast_rtp_get_quality (struct ast_rtp *rtp, struct ast_rtp_quality *qual)
 Return RTCP quality string.
int ast_rtp_get_rtpholdtimeout (struct ast_rtp *rtp)
 Get rtp hold timeout.
int ast_rtp_get_rtpkeepalive (struct ast_rtp *rtp)
 Get RTP keepalive interval.
int ast_rtp_get_rtptimeout (struct ast_rtp *rtp)
 Get rtp timeout.
void ast_rtp_get_us (struct ast_rtp *rtp, struct sockaddr_in *us)
int ast_rtp_getnat (struct ast_rtp *rtp)
void ast_rtp_init (void)
 Initialize the RTP system in Asterisk.
int ast_rtp_lookup_code (struct ast_rtp *rtp, int isAstFormat, int code)
 Looks up an RTP code out of our *static* outbound list.
char * ast_rtp_lookup_mime_multiple (char *buf, size_t size, const int capability, const int isAstFormat, enum ast_rtp_options options)
 Build a string of MIME subtype names from a capability list.
const char * ast_rtp_lookup_mime_subtype (int isAstFormat, int code, enum ast_rtp_options options)
 Mapping an Asterisk code into a MIME subtype (string):.
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_alt_peer (struct ast_rtp *rtp, struct sockaddr_in *alt)
 set potential alternate source for RTP media
void ast_rtp_set_callback (struct ast_rtp *rtp, ast_rtp_callback callback)
void ast_rtp_set_data (struct ast_rtp *rtp, void *data)
void ast_rtp_set_m_type (struct ast_rtp *rtp, int pt)
 Activate payload type.
void ast_rtp_set_peer (struct ast_rtp *rtp, struct sockaddr_in *them)
void ast_rtp_set_rtpholdtimeout (struct ast_rtp *rtp, int timeout)
 Set rtp hold timeout.
void ast_rtp_set_rtpkeepalive (struct ast_rtp *rtp, int period)
 set RTP keepalive interval
int ast_rtp_set_rtpmap_type (struct ast_rtp *rtp, int pt, char *mimeType, char *mimeSubtype, enum ast_rtp_options options)
 Initiate payload type to a known MIME media type for a codec.
void ast_rtp_set_rtptimeout (struct ast_rtp *rtp, int timeout)
 Set rtp timeout.
void ast_rtp_set_rtptimers_onhold (struct ast_rtp *rtp)
void ast_rtp_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.


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(), check_user_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 54 of file rtp.h.

#define MAX_RTP_PT   256

Maxmum number of payload defintions for a RTP session

Definition at line 52 of file rtp.h.

Referenced by ast_rtp_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().


Typedef Documentation

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

RTP callback structure

Definition at line 101 of file rtp.h.


Enumeration Type Documentation

enum ast_rtp_get_result

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

Definition at line 60 of file rtp.h.

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

enum ast_rtp_options

Enumerator:
AST_RTP_OPT_G726_NONSTANDARD 

Definition at line 56 of file rtp.h.

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


Function Documentation

int ast_rtcp_fd ( struct ast_rtp rtp  ) 

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

00679 {
00680    if (rtp->rtcp)
00681       return rtp->rtcp->s;
00682    return -1;
00683 }

struct ast_frame* ast_rtcp_read ( struct ast_rtp rtp  ) 

Definition at line 1090 of file rtp.c.

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

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

01091 {
01092    socklen_t len;
01093    int position, i, packetwords;
01094    int res;
01095    struct sockaddr_in sin;
01096    unsigned int rtcpdata[8192 + AST_FRIENDLY_OFFSET];
01097    unsigned int *rtcpheader;
01098    int pt;
01099    struct timeval now;
01100    unsigned int length;
01101    int rc;
01102    double rttsec;
01103    uint64_t rtt = 0;
01104    unsigned int dlsr;
01105    unsigned int lsr;
01106    unsigned int msw;
01107    unsigned int lsw;
01108    unsigned int comp;
01109    struct ast_frame *f = &ast_null_frame;
01110    
01111    if (!rtp || !rtp->rtcp)
01112       return &ast_null_frame;
01113 
01114    len = sizeof(sin);
01115    
01116    res = recvfrom(rtp->rtcp->s, rtcpdata + AST_FRIENDLY_OFFSET, sizeof(rtcpdata) - sizeof(unsigned int) * AST_FRIENDLY_OFFSET,
01117                0, (struct sockaddr *)&sin, &len);
01118    rtcpheader = (unsigned int *)(rtcpdata + AST_FRIENDLY_OFFSET);
01119    
01120    if (res < 0) {
01121       ast_assert(errno != EBADF);
01122       if (errno != EAGAIN) {
01123          ast_log(LOG_WARNING, "RTCP Read error: %s.  Hanging up.\n", strerror(errno));
01124          return NULL;
01125       }
01126       return &ast_null_frame;
01127    }
01128 
01129    packetwords = res / 4;
01130    
01131    if (rtp->nat) {
01132       /* Send to whoever sent to us */
01133       if (((rtp->rtcp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
01134           (rtp->rtcp->them.sin_port != sin.sin_port)) && 
01135           ((rtp->rtcp->altthem.sin_addr.s_addr != sin.sin_addr.s_addr) || 
01136           (rtp->rtcp->altthem.sin_port != sin.sin_port))) {
01137          memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
01138          if (option_debug || rtpdebug)
01139             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));
01140       }
01141    }
01142 
01143    ast_debug(1, "Got RTCP report of %d bytes\n", res);
01144 
01145    /* Process a compound packet */
01146    position = 0;
01147    while (position < packetwords) {
01148       i = position;
01149       length = ntohl(rtcpheader[i]);
01150       pt = (length & 0xff0000) >> 16;
01151       rc = (length & 0x1f000000) >> 24;
01152       length &= 0xffff;
01153  
01154       if ((i + length) > packetwords) {
01155          if (option_debug || rtpdebug)
01156             ast_log(LOG_DEBUG, "RTCP Read too short\n");
01157          return &ast_null_frame;
01158       }
01159       
01160       if (rtcp_debug_test_addr(&sin)) {
01161          ast_verbose("\n\nGot RTCP from %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
01162          ast_verbose("PT: %d(%s)\n", pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown");
01163          ast_verbose("Reception reports: %d\n", rc);
01164          ast_verbose("SSRC of sender: %u\n", rtcpheader[i + 1]);
01165       }
01166  
01167       i += 2; /* Advance past header and ssrc */
01168       
01169       switch (pt) {
01170       case RTCP_PT_SR:
01171          gettimeofday(&rtp->rtcp->rxlsr,NULL); /* To be able to populate the dlsr */
01172          rtp->rtcp->spc = ntohl(rtcpheader[i+3]);
01173          rtp->rtcp->soc = ntohl(rtcpheader[i + 4]);
01174          rtp->rtcp->themrxlsr = ((ntohl(rtcpheader[i]) & 0x0000ffff) << 16) | ((ntohl(rtcpheader[i + 1]) & 0xffff0000) >> 16); /* Going to LSR in RR*/
01175  
01176          if (rtcp_debug_test_addr(&sin)) {
01177             ast_verbose("NTP timestamp: %lu.%010lu\n", (unsigned long) ntohl(rtcpheader[i]), (unsigned long) ntohl(rtcpheader[i + 1]) * 4096);
01178             ast_verbose("RTP timestamp: %lu\n", (unsigned long) ntohl(rtcpheader[i + 2]));
01179             ast_verbose("SPC: %lu\tSOC: %lu\n", (unsigned long) ntohl(rtcpheader[i + 3]), (unsigned long) ntohl(rtcpheader[i + 4]));
01180          }
01181          i += 5;
01182          if (rc < 1)
01183             break;
01184          /* Intentional fall through */
01185       case RTCP_PT_RR:
01186          /* Don't handle multiple reception reports (rc > 1) yet */
01187          /* Calculate RTT per RFC */
01188          gettimeofday(&now, NULL);
01189          timeval2ntp(now, &msw, &lsw);
01190          if (ntohl(rtcpheader[i + 4]) && ntohl(rtcpheader[i + 5])) { /* We must have the LSR && DLSR */
01191             comp = ((msw & 0xffff) << 16) | ((lsw & 0xffff0000) >> 16);
01192             lsr = ntohl(rtcpheader[i + 4]);
01193             dlsr = ntohl(rtcpheader[i + 5]);
01194             rtt = comp - lsr - dlsr;
01195 
01196             /* Convert end to end delay to usec (keeping the calculation in 64bit space)
01197                sess->ee_delay = (eedelay * 1000) / 65536; */
01198             if (rtt < 4294) {
01199                 rtt = (rtt * 1000000) >> 16;
01200             } else {
01201                 rtt = (rtt * 1000) >> 16;
01202                 rtt *= 1000;
01203             }
01204             rtt = rtt / 1000.;
01205             rttsec = rtt / 1000.;
01206 
01207             if (comp - dlsr >= lsr) {
01208                rtp->rtcp->accumulated_transit += rttsec;
01209                rtp->rtcp->rtt = rttsec;
01210                if (rtp->rtcp->maxrtt<rttsec)
01211                   rtp->rtcp->maxrtt = rttsec;
01212                if (rtp->rtcp->minrtt>rttsec)
01213                   rtp->rtcp->minrtt = rttsec;
01214             } else if (rtcp_debug_test_addr(&sin)) {
01215                ast_verbose("Internal RTCP NTP clock skew detected: "
01216                         "lsr=%u, now=%u, dlsr=%u (%d:%03dms), "
01217                         "diff=%d\n",
01218                         lsr, comp, dlsr, dlsr / 65536,
01219                         (dlsr % 65536) * 1000 / 65536,
01220                         dlsr - (comp - lsr));
01221             }
01222          }
01223 
01224          rtp->rtcp->reported_jitter = ntohl(rtcpheader[i + 3]);
01225          rtp->rtcp->reported_lost = ntohl(rtcpheader[i + 1]) & 0xffffff;
01226          if (rtcp_debug_test_addr(&sin)) {
01227             ast_verbose("  Fraction lost: %ld\n", (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24));
01228             ast_verbose("  Packets lost so far: %d\n", rtp->rtcp->reported_lost);
01229             ast_verbose("  Highest sequence number: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff));
01230             ast_verbose("  Sequence number cycles: %ld\n", (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16);
01231             ast_verbose("  Interarrival jitter: %u\n", rtp->rtcp->reported_jitter);
01232             ast_verbose("  Last SR(our NTP): %lu.%010lu\n",(unsigned long) ntohl(rtcpheader[i + 4]) >> 16,((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096);
01233             ast_verbose("  DLSR: %4.4f (sec)\n",ntohl(rtcpheader[i + 5])/65536.0);
01234             if (rtt)
01235                ast_verbose("  RTT: %lu(sec)\n", (unsigned long) rtt);
01236          }
01237          if (rtt) {
01238             manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From: %s:%d\r\n"
01239                             "PT: %d(%s)\r\n"
01240                             "ReceptionReports: %d\r\n"
01241                             "SenderSSRC: %u\r\n"
01242                             "FractionLost: %ld\r\n"
01243                             "PacketsLost: %d\r\n"
01244                             "HighestSequence: %ld\r\n"
01245                             "SequenceNumberCycles: %ld\r\n"
01246                             "IAJitter: %u\r\n"
01247                             "LastSR: %lu.%010lu\r\n"
01248                             "DLSR: %4.4f(sec)\r\n"
01249                             "RTT: %llu(sec)\r\n",
01250                             ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port),
01251                             pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
01252                             rc,
01253                             rtcpheader[i + 1],
01254                             (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24),
01255                             rtp->rtcp->reported_lost,
01256                             (long) (ntohl(rtcpheader[i + 2]) & 0xffff),
01257                             (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16,
01258                             rtp->rtcp->reported_jitter,
01259                             (unsigned long) ntohl(rtcpheader[i + 4]) >> 16, ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096,
01260                             ntohl(rtcpheader[i + 5])/65536.0,
01261                             (unsigned long long)rtt);
01262          } else {
01263             manager_event(EVENT_FLAG_REPORTING, "RTCPReceived", "From: %s:%d\r\n"
01264                             "PT: %d(%s)\r\n"
01265                             "ReceptionReports: %d\r\n"
01266                             "SenderSSRC: %u\r\n"
01267                             "FractionLost: %ld\r\n"
01268                             "PacketsLost: %d\r\n"
01269                             "HighestSequence: %ld\r\n"
01270                             "SequenceNumberCycles: %ld\r\n"
01271                             "IAJitter: %u\r\n"
01272                             "LastSR: %lu.%010lu\r\n"
01273                             "DLSR: %4.4f(sec)\r\n",
01274                             ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port),
01275                             pt, (pt == 200) ? "Sender Report" : (pt == 201) ? "Receiver Report" : (pt == 192) ? "H.261 FUR" : "Unknown",
01276                             rc,
01277                             rtcpheader[i + 1],
01278                             (((long) ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24),
01279                             rtp->rtcp->reported_lost,
01280                             (long) (ntohl(rtcpheader[i + 2]) & 0xffff),
01281                             (long) (ntohl(rtcpheader[i + 2]) & 0xffff) >> 16,
01282                             rtp->rtcp->reported_jitter,
01283                             (unsigned long) ntohl(rtcpheader[i + 4]) >> 16,
01284                             ((unsigned long) ntohl(rtcpheader[i + 4]) << 16) * 4096,
01285                             ntohl(rtcpheader[i + 5])/65536.0);
01286          }
01287          break;
01288       case RTCP_PT_FUR:
01289          if (rtcp_debug_test_addr(&sin))
01290             ast_verbose("Received an RTCP Fast Update Request\n");
01291          rtp->f.frametype = AST_FRAME_CONTROL;
01292          rtp->f.subclass = AST_CONTROL_VIDUPDATE;
01293          rtp->f.datalen = 0;
01294          rtp->f.samples = 0;
01295          rtp->f.mallocd = 0;
01296          rtp->f.src = "RTP";
01297          f = &rtp->f;
01298          break;
01299       case RTCP_PT_SDES:
01300          if (rtcp_debug_test_addr(&sin))
01301             ast_verbose("Received an SDES from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
01302          break;
01303       case RTCP_PT_BYE:
01304          if (rtcp_debug_test_addr(&sin))
01305             ast_verbose("Received a BYE from %s:%d\n", ast_inet_ntoa(rtp->rtcp->them.sin_addr), ntohs(rtp->rtcp->them.sin_port));
01306          break;
01307       default:
01308          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));
01309          break;
01310       }
01311       position += (length + 1);
01312    }
01313          
01314    return f;
01315 }

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

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

02771 {
02772    struct ast_rtp *rtp = data;
02773    int res;
02774 
02775    rtp->rtcp->sendfur = 1;
02776    res = ast_rtcp_write(data);
02777    
02778    return res;
02779 }

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

Referenced by process_sdp().

00450 {
00451    return sizeof(struct ast_rtp);
00452 }

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

03834 {
03835    struct ast_rtp *p0 = NULL, *p1 = NULL;    /* Audio RTP Channels */
03836    struct ast_rtp *vp0 = NULL, *vp1 = NULL;  /* Video RTP channels */
03837    struct ast_rtp *tp0 = NULL, *tp1 = NULL;  /* Text RTP channels */
03838    struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL;
03839    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;
03840    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;
03841    enum ast_bridge_result res = AST_BRIDGE_FAILED;
03842    int codec0 = 0, codec1 = 0;
03843    void *pvt0 = NULL, *pvt1 = NULL;
03844 
03845    /* Lock channels */
03846    ast_channel_lock(c0);
03847    while (ast_channel_trylock(c1)) {
03848       ast_channel_unlock(c0);
03849       usleep(1);
03850       ast_channel_lock(c0);
03851    }
03852 
03853    /* Ensure neither channel got hungup during lock avoidance */
03854    if (ast_check_hangup(c0) || ast_check_hangup(c1)) {
03855       ast_log(LOG_WARNING, "Got hangup while attempting to bridge '%s' and '%s'\n", c0->name, c1->name);
03856       ast_channel_unlock(c0);
03857       ast_channel_unlock(c1);
03858       return AST_BRIDGE_FAILED;
03859    }
03860       
03861    /* Find channel driver interfaces */
03862    if (!(pr0 = get_proto(c0))) {
03863       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c0->name);
03864       ast_channel_unlock(c0);
03865       ast_channel_unlock(c1);
03866       return AST_BRIDGE_FAILED;
03867    }
03868    if (!(pr1 = get_proto(c1))) {
03869       ast_log(LOG_WARNING, "Can't find native functions for channel '%s'\n", c1->name);
03870       ast_channel_unlock(c0);
03871       ast_channel_unlock(c1);
03872       return AST_BRIDGE_FAILED;
03873    }
03874 
03875    /* Get channel specific interface structures */
03876    pvt0 = c0->tech_pvt;
03877    pvt1 = c1->tech_pvt;
03878 
03879    /* Get audio and video interface (if native bridge is possible) */
03880    audio_p0_res = pr0->get_rtp_info(c0, &p0);
03881    video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
03882    text_p0_res = pr0->get_trtp_info ? pr0->get_trtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
03883    audio_p1_res = pr1->get_rtp_info(c1, &p1);
03884    video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
03885    text_p1_res = pr1->get_trtp_info ? pr1->get_trtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
03886 
03887    /* If we are carrying video, and both sides are not reinviting... then fail the native bridge */
03888    if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE))
03889       audio_p0_res = AST_RTP_GET_FAILED;
03890    if (video_p1_res != AST_RTP_GET_FAILED && (audio_p1_res != AST_RTP_TRY_NATIVE || video_p1_res != AST_RTP_TRY_NATIVE))
03891       audio_p1_res = AST_RTP_GET_FAILED;
03892 
03893    /* Check if a bridge is possible (partial/native) */
03894    if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) {
03895       /* Somebody doesn't want to play... */
03896       ast_channel_unlock(c0);
03897       ast_channel_unlock(c1);
03898       return AST_BRIDGE_FAILED_NOWARN;
03899    }
03900 
03901    /* If we need to feed DTMF frames into the core then only do a partial native bridge */
03902    if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
03903       ast_set_flag(p0, FLAG_P2P_NEED_DTMF);
03904       audio_p0_res = AST_RTP_TRY_PARTIAL;
03905    }
03906 
03907    if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) {
03908       ast_set_flag(p1, FLAG_P2P_NEED_DTMF);
03909       audio_p1_res = AST_RTP_TRY_PARTIAL;
03910    }
03911 
03912    /* If both sides are not using the same method of DTMF transmission 
03913     * (ie: one is RFC2833, other is INFO... then we can not do direct media. 
03914     * --------------------------------------------------
03915     * | DTMF Mode |  HAS_DTMF  |  Accepts Begin Frames |
03916     * |-----------|------------|-----------------------|
03917     * | Inband    | False      | True                  |
03918     * | RFC2833   | True       | True                  |
03919     * | SIP INFO  | False      | False                 |
03920     * --------------------------------------------------
03921     * However, if DTMF from both channels is being monitored by the core, then
03922     * we can still do packet-to-packet bridging, because passing through the 
03923     * core will handle DTMF mode translation.
03924     */
03925    if ( (ast_test_flag(p0, FLAG_HAS_DTMF) != ast_test_flag(p1, FLAG_HAS_DTMF)) ||
03926        (!c0->tech->send_digit_begin != !c1->tech->send_digit_begin)) {
03927       if (!ast_test_flag(p0, FLAG_P2P_NEED_DTMF) || !ast_test_flag(p1, FLAG_P2P_NEED_DTMF)) {
03928          ast_channel_unlock(c0);
03929          ast_channel_unlock(c1);
03930          return AST_BRIDGE_FAILED_NOWARN;
03931       }
03932       audio_p0_res = AST_RTP_TRY_PARTIAL;
03933       audio_p1_res = AST_RTP_TRY_PARTIAL;
03934    }
03935 
03936    /* If we need to feed frames into the core don't do a P2P bridge */
03937    if ((audio_p0_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p0, FLAG_P2P_NEED_DTMF)) ||
03938        (audio_p1_res == AST_RTP_TRY_PARTIAL && ast_test_flag(p1, FLAG_P2P_NEED_DTMF))) {
03939       ast_channel_unlock(c0);
03940       ast_channel_unlock(c1);
03941       return AST_BRIDGE_FAILED_NOWARN;
03942    }
03943 
03944    /* Get codecs from both sides */
03945    codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0;
03946    codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0;
03947    if (codec0 && codec1 && !(codec0 & codec1)) {
03948       /* Hey, we can't do native bridging if both parties speak different codecs */
03949       ast_debug(3, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1);
03950       ast_channel_unlock(c0);
03951       ast_channel_unlock(c1);
03952       return AST_BRIDGE_FAILED_NOWARN;
03953    }
03954 
03955    /* If either side can only do a partial bridge, then don't try for a true native bridge */
03956    if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) {
03957       struct ast_format_list fmt0, fmt1;
03958 
03959       /* In order to do Packet2Packet bridging both sides must be in the same rawread/rawwrite */
03960       if (c0->rawreadformat != c1->rawwriteformat || c1->rawreadformat != c0->rawwriteformat) {
03961          ast_debug(1, "Cannot packet2packet bridge - raw formats are incompatible\n");
03962          ast_channel_unlock(c0);
03963          ast_channel_unlock(c1);
03964          return AST_BRIDGE_FAILED_NOWARN;
03965       }
03966       /* They must also be using the same packetization */
03967       fmt0 = ast_codec_pref_getsize(&p0->pref, c0->rawreadformat);
03968       fmt1 = ast_codec_pref_getsize(&p1->pref, c1->rawreadformat);
03969       if (fmt0.cur_ms != fmt1.cur_ms) {
03970          ast_debug(1, "Cannot packet2packet bridge - packetization settings prevent it\n");
03971          ast_channel_unlock(c0);
03972          ast_channel_unlock(c1);
03973          return AST_BRIDGE_FAILED_NOWARN;
03974       }
03975 
03976       ast_verb(3, "Packet2Packet bridging %s and %s\n", c0->name, c1->name);
03977       res = bridge_p2p_loop(c0, c1, p0, p1, timeoutms, flags, fo, rc, pvt0, pvt1);
03978    } else {
03979       ast_verb(3, "Native bridging %s and %s\n", c0->name, c1->name);
03980       res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, tp0, tp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1);
03981    }
03982 
03983    return res;
03984 }

int ast_rtp_codec_getformat ( int  pt  ) 

get format from predefined dynamic payload format

Definition at line 3227 of file rtp.c.

References rtpPayloadType::code, and static_RTP_PT.

Referenced by process_sdp().

03228 {
03229    if (pt < 0 || pt > MAX_RTP_PT)
03230       return 0; /* bogus payload type */
03231 
03232    if (static_RTP_PT[pt].isAstFormat)
03233       return static_RTP_PT[pt].code;
03234    else
03235       return 0;
03236 }

struct ast_codec_pref* ast_rtp_codec_getpref ( struct ast_rtp rtp  ) 

Get codec preference.

Definition at line 3222 of file rtp.c.

References ast_rtp::pref.

Referenced by add_codec_to_sdp(), and process_sdp().

03223 {
03224    return &rtp->pref;
03225 }

void ast_rtp_codec_setpref ( struct ast_rtp rtp,
struct ast_codec_pref prefs 
)

Set codec preference.

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

03177 {
03178    struct ast_format_list current_format_old, current_format_new;
03179 
03180    /* if no packets have been sent through this session yet, then
03181     *  changing preferences does not require any extra work
03182     */
03183    if (rtp->lasttxformat == 0) {
03184       rtp->pref = *prefs;
03185       return;
03186    }
03187 
03188    current_format_old = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat);
03189 
03190    rtp->pref = *prefs;
03191 
03192    current_format_new = ast_codec_pref_getsize(&rtp->pref, rtp->lasttxformat);
03193 
03194    /* if the framing desired for the current format has changed, we may have to create
03195     * or adjust the smoother for this session
03196     */
03197    if ((current_format_new.inc_ms != 0) &&
03198        (current_format_new.cur_ms != current_format_old.cur_ms)) {
03199       int new_size = (current_format_new.cur_ms * current_format_new.fr_len) / current_format_new.inc_ms;
03200 
03201       if (rtp->smoother) {
03202          ast_smoother_reconfigure(rtp->smoother, new_size);
03203          if (option_debug) {
03204             ast_log(LOG_DEBUG, "Adjusted smoother to %d ms and %d bytes\n", current_format_new.cur_ms, new_size);
03205          }
03206       } else {
03207          if (!(rtp->smoother = ast_smoother_new(new_size))) {
03208             ast_log(LOG_WARNING, "Unable to create smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size);
03209             return;
03210          }
03211          if (current_format_new.flags) {
03212             ast_smoother_set_flags(rtp->smoother, current_format_new.flags);
03213          }
03214          if (option_debug) {
03215             ast_log(LOG_DEBUG, "Created smoother: format: %d ms: %d len: %d\n", rtp->lasttxformat, current_format_new.cur_ms, new_size);
03216          }
03217       }
03218    }
03219 
03220 }

void ast_rtp_destroy ( struct ast_rtp rtp  ) 

Destroy RTP session

Definition at line 2529 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(), check_user_ok(), cleanup_connection(), create_addr_from_peer(), destroy_endpoint(), gtalk_free_pvt(), jingle_free_pvt(), mgcp_hangup(), oh323_alloc(), sip_alloc(), skinny_hangup(), start_rtp(), unalloc_sub(), and unistim_hangup().

02530 {
02531    if (rtcp_debug_test_addr(&rtp->them) || rtcpstats) {
02532       /*Print some info on the call here */
02533       ast_verbose("  RTP-stats\n");
02534       ast_verbose("* Our Receiver:\n");
02535       ast_verbose("  SSRC:     %u\n", rtp->themssrc);
02536       ast_verbose("  Received packets: %u\n", rtp->rxcount);
02537       ast_verbose("  Lost packets:   %u\n", rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0);
02538       ast_verbose("  Jitter:      %.4f\n", rtp->rxjitter);
02539       ast_verbose("  Transit:     %.4f\n", rtp->rxtransit);
02540       ast_verbose("  RR-count:    %u\n", rtp->rtcp ? rtp->rtcp->rr_count : 0);
02541       ast_verbose("* Our Sender:\n");
02542       ast_verbose("  SSRC:     %u\n", rtp->ssrc);
02543       ast_verbose("  Sent packets:   %u\n", rtp->txcount);
02544       ast_verbose("  Lost packets:   %u\n", rtp->rtcp ? rtp->rtcp->reported_lost : 0);
02545       ast_verbose("  Jitter:      %u\n", rtp->rtcp ? (rtp->rtcp->reported_jitter / (unsigned int)65536.0) : 0);
02546       ast_verbose("  SR-count:    %u\n", rtp->rtcp ? rtp->rtcp->sr_count : 0);
02547       ast_verbose("  RTT:      %f\n", rtp->rtcp ? rtp->rtcp->rtt : 0);
02548    }
02549 
02550    manager_event(EVENT_FLAG_REPORTING, "RTPReceiverStat", "SSRC: %u\r\n"
02551                    "ReceivedPackets: %u\r\n"
02552                    "LostPackets: %u\r\n"
02553                    "Jitter: %.4f\r\n"
02554                    "Transit: %.4f\r\n"
02555                    "RRCount: %u\r\n",
02556                    rtp->themssrc,
02557                    rtp->rxcount,
02558                    rtp->rtcp ? (rtp->rtcp->expected_prior - rtp->rtcp->received_prior) : 0,
02559                    rtp->rxjitter,
02560                    rtp->rxtransit,
02561                    rtp->rtcp ? rtp->rtcp->rr_count : 0);
02562    manager_event(EVENT_FLAG_REPORTING, "RTPSenderStat", "SSRC: %u\r\n"
02563                    "SentPackets: %u\r\n"
02564                    "LostPackets: %u\r\n"
02565                    "Jitter: %u\r\n"
02566                    "SRCount: %u\r\n"
02567                    "RTT: %f\r\n",
02568                    rtp->ssrc,
02569                    rtp->txcount,
02570                    rtp->rtcp ? rtp->rtcp->reported_lost : 0,
02571                    rtp->rtcp ? rtp->rtcp->reported_jitter : 0,
02572                    rtp->rtcp ? rtp->rtcp->sr_count : 0,
02573                    rtp->rtcp ? rtp->rtcp->rtt : 0);
02574    if (rtp->smoother)
02575       ast_smoother_free(rtp->smoother);
02576    if (rtp->ioid)
02577       ast_io_remove(rtp->io, rtp->ioid);
02578    if (rtp->s > -1)
02579       close(rtp->s);
02580    if (rtp->rtcp) {
02581       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02582       close(rtp->rtcp->s);
02583       ast_free(rtp->rtcp);
02584       rtp->rtcp=NULL;
02585    }
02586 #ifdef P2P_INTENSE
02587    ast_mutex_destroy(&rtp->bridge_lock);
02588 #endif
02589    ast_free(rtp);
02590 }

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

01856 {
01857    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
01858    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
01859    struct ast_rtp *tdestp = NULL, *tsrcp = NULL;      /* Text RTP channels */
01860    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
01861    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;
01862    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;
01863    int srccodec, destcodec, nat_active = 0;
01864 
01865    /* Lock channels */
01866    ast_channel_lock(c0);
01867    if (c1) {
01868       while (ast_channel_trylock(c1)) {
01869          ast_channel_unlock(c0);
01870          usleep(1);
01871          ast_channel_lock(c0);
01872       }
01873    }
01874 
01875    /* Find channel driver interfaces */
01876    destpr = get_proto(c0);
01877    if (c1)
01878       srcpr = get_proto(c1);
01879    if (!destpr) {
01880       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c0->name);
01881       ast_channel_unlock(c0);
01882       if (c1)
01883          ast_channel_unlock(c1);
01884       return -1;
01885    }
01886    if (!srcpr) {
01887       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", c1 ? c1->name : "<unspecified>");
01888       ast_channel_unlock(c0);
01889       if (c1)
01890          ast_channel_unlock(c1);
01891       return -1;
01892    }
01893 
01894    /* Get audio, video  and text interface (if native bridge is possible) */
01895    audio_dest_res = destpr->get_rtp_info(c0, &destp);
01896    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(c0, &vdestp) : AST_RTP_GET_FAILED;
01897    text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(c0, &tdestp) : AST_RTP_GET_FAILED;
01898    if (srcpr) {
01899       audio_src_res = srcpr->get_rtp_info(c1, &srcp);
01900       video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(c1, &vsrcp) : AST_RTP_GET_FAILED;
01901       text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(c1, &tsrcp) : AST_RTP_GET_FAILED;
01902    }
01903 
01904    /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
01905    if (audio_dest_res != AST_RTP_TRY_NATIVE || (video_dest_res != AST_RTP_GET_FAILED && video_dest_res != AST_RTP_TRY_NATIVE)) {
01906       /* Somebody doesn't want to play... */
01907       ast_channel_unlock(c0);
01908       if (c1)
01909          ast_channel_unlock(c1);
01910       return -1;
01911    }
01912    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)
01913       srccodec = srcpr->get_codec(c1);
01914    else
01915       srccodec = 0;
01916    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)
01917       destcodec = destpr->get_codec(c0);
01918    else
01919       destcodec = 0;
01920    /* Ensure we have at least one matching codec */
01921    if (srcp && !(srccodec & destcodec)) {
01922       ast_channel_unlock(c0);
01923       ast_channel_unlock(c1);
01924       return 0;
01925    }
01926    /* Consider empty media as non-existent */
01927    if (audio_src_res == AST_RTP_TRY_NATIVE && !srcp->them.sin_addr.s_addr)
01928       srcp = NULL;
01929    if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
01930       nat_active = 1;
01931    /* Bridge media early */
01932    if (destpr->set_rtp_peer(c0, srcp, vsrcp, tsrcp, srccodec, nat_active))
01933       ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
01934    ast_channel_unlock(c0);
01935    if (c1)
01936       ast_channel_unlock(c1);
01937    ast_debug(1, "Setting early bridge SDP of '%s' with that of '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
01938    return 0;
01939 }

int ast_rtp_fd ( struct ast_rtp rtp  ) 

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

00674 {
00675    return rtp->s;
00676 }

struct ast_rtp* ast_rtp_get_bridged ( struct ast_rtp rtp  ) 

Definition at line 2436 of file rtp.c.

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

Referenced by __sip_destroy(), and ast_rtp_read().

02437 {
02438    struct ast_rtp *bridged = NULL;
02439 
02440    rtp_bridge_lock(rtp);
02441    bridged = rtp->bridged;
02442    rtp_bridge_unlock(rtp);
02443 
02444    return bridged;
02445 }

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

02079 {
02080    int pt;
02081    
02082    rtp_bridge_lock(rtp);
02083    
02084    *astFormats = *nonAstFormats = 0;
02085    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02086       if (rtp->current_RTP_PT[pt].isAstFormat) {
02087          *astFormats |= rtp->current_RTP_PT[pt].code;
02088       } else {
02089          *nonAstFormats |= rtp->current_RTP_PT[pt].code;
02090       }
02091    }
02092 
02093    rtp_bridge_unlock(rtp);
02094 }

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

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

02419 {
02420    if ((them->sin_family != AF_INET) ||
02421       (them->sin_port != rtp->them.sin_port) ||
02422       (them->sin_addr.s_addr != rtp->them.sin_addr.s_addr)) {
02423       them->sin_family = AF_INET;
02424       them->sin_port = rtp->them.sin_port;
02425       them->sin_addr = rtp->them.sin_addr;
02426       return 1;
02427    }
02428    return 0;
02429 }

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

Return RTCP quality string.

Definition at line 2485 of file rtp.c.

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

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

02486 {
02487    /*
02488    *ssrc          our ssrc
02489    *themssrc      their ssrc
02490    *lp            lost packets
02491    *rxjitter      our calculated jitter(rx)
02492    *rxcount       no. received packets
02493    *txjitter      reported jitter of the other end
02494    *txcount       transmitted packets
02495    *rlp           remote lost packets
02496    *rtt           round trip time
02497    */
02498 
02499    if (qual && rtp) {
02500       qual->local_ssrc = rtp->ssrc;
02501       qual->local_jitter = rtp->rxjitter;
02502       qual->local_count = rtp->rxcount;
02503       qual->remote_ssrc = rtp->themssrc;
02504       qual->remote_count = rtp->txcount;
02505       if (rtp->rtcp) {
02506          qual->local_lostpackets = rtp->rtcp->expected_prior - rtp->rtcp->received_prior;
02507          qual->remote_lostpackets = rtp->rtcp->reported_lost;
02508          qual->remote_jitter = rtp->rtcp->reported_jitter / 65536.0;
02509          qual->rtt = rtp->rtcp->rtt;
02510       }
02511    }
02512    if (rtp->rtcp) {
02513       snprintf(rtp->rtcp->quality, sizeof(rtp->rtcp->quality),
02514          "ssrc=%u;themssrc=%u;lp=%u;rxjitter=%f;rxcount=%u;txjitter=%f;txcount=%u;rlp=%u;rtt=%f",
02515          rtp->ssrc,
02516          rtp->themssrc,
02517          rtp->rtcp->expected_prior - rtp->rtcp->received_prior,
02518          rtp->rxjitter,
02519          rtp->rxcount,
02520          (double)rtp->rtcp->reported_jitter / 65536.0,
02521          rtp->txcount,
02522          rtp->rtcp->reported_lost,
02523          rtp->rtcp->rtt);
02524       return rtp->rtcp->quality;
02525    } else
02526       return "<Unknown> - RTP/RTCP has already been destroyed";
02527 }

int ast_rtp_get_rtpholdtimeout ( struct ast_rtp rtp  ) 

Get rtp hold timeout.

Definition at line 728 of file rtp.c.

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

Referenced by check_rtp_timeout().

00729 {
00730    if (rtp->rtptimeout < 0)   /* We're not checking, but remembering the setting (during T.38 transmission) */
00731       return 0;
00732    return rtp->rtpholdtimeout;
00733 }

int ast_rtp_get_rtpkeepalive ( struct ast_rtp rtp  ) 

Get RTP keepalive interval.

Definition at line 736 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by check_rtp_timeout().

00737 {
00738    return rtp->rtpkeepalive;
00739 }

int ast_rtp_get_rtptimeout ( struct ast_rtp rtp  ) 

Get rtp timeout.

Definition at line 720 of file rtp.c.

References ast_rtp::rtptimeout.

Referenced by check_rtp_timeout().

00721 {
00722    if (rtp->rtptimeout < 0)   /* We're not checking, but remembering the setting (during T.38 transmission) */
00723       return 0;
00724    return rtp->rtptimeout;
00725 }

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

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

02432 {
02433    *us = rtp->us;
02434 }

int ast_rtp_getnat ( struct ast_rtp rtp  ) 

Definition at line 756 of file rtp.c.

References ast_test_flag, and FLAG_NAT_ACTIVE.

Referenced by sip_get_rtp_peer().

00757 {
00758    return ast_test_flag(rtp, FLAG_NAT_ACTIVE);
00759 }

void ast_rtp_init ( void   ) 

Initialize the RTP system in Asterisk.

Definition at line 4372 of file rtp.c.

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

Referenced by main().

04373 {
04374    ast_cli_register_multiple(cli_rtp, sizeof(cli_rtp) / sizeof(struct ast_cli_entry));
04375    __ast_rtp_reload(0);
04376 }

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

02119 {
02120    int pt = 0;
02121 
02122    rtp_bridge_lock(rtp);
02123 
02124    if (isAstFormat == rtp->rtp_lookup_code_cache_isAstFormat &&
02125       code == rtp->rtp_lookup_code_cache_code) {
02126       /* Use our cached mapping, to avoid the overhead of the loop below */
02127       pt = rtp->rtp_lookup_code_cache_result;
02128       rtp_bridge_unlock(rtp);
02129       return pt;
02130    }
02131 
02132    /* Check the dynamic list first */
02133    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02134       if (rtp->current_RTP_PT[pt].code == code && rtp->current_RTP_PT[pt].isAstFormat == isAstFormat) {
02135          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
02136          rtp->rtp_lookup_code_cache_code = code;
02137          rtp->rtp_lookup_code_cache_result = pt;
02138          rtp_bridge_unlock(rtp);
02139          return pt;
02140       }
02141    }
02142 
02143    /* Then the static list */
02144    for (pt = 0; pt < MAX_RTP_PT; ++pt) {
02145       if (static_RTP_PT[pt].code == code && static_RTP_PT[pt].isAstFormat == isAstFormat) {
02146          rtp->rtp_lookup_code_cache_isAstFormat = isAstFormat;
02147          rtp->rtp_lookup_code_cache_code = code;
02148          rtp->rtp_lookup_code_cache_result = pt;
02149          rtp_bridge_unlock(rtp);
02150          return pt;
02151       }
02152    }
02153 
02154    rtp_bridge_unlock(rtp);
02155 
02156    return -1;
02157 }

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

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

Referenced by process_sdp().

02180 {
02181    int format;
02182    unsigned len;
02183    char *end = buf;
02184    char *start = buf;
02185 
02186    if (!buf || !size)
02187       return NULL;
02188 
02189    snprintf(end, size, "0x%x (", capability);
02190 
02191    len = strlen(end);
02192    end += len;
02193    size -= len;
02194    start = end;
02195 
02196    for (format = 1; format < AST_RTP_MAX; format <<= 1) {
02197       if (capability & format) {
02198          const char *name = ast_rtp_lookup_mime_subtype(isAstFormat, format, options);
02199 
02200          snprintf(end, size, "%s|", name);
02201          len = strlen(end);
02202          end += len;
02203          size -= len;
02204       }
02205    }
02206 
02207    if (start == end)
02208       ast_copy_string(start, "nothing)", size); 
02209    else if (size > 1)
02210       *(end -1) = ')';
02211    
02212    return buf;
02213 }

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

02161 {
02162    unsigned int i;
02163 
02164    for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
02165       if ((mimeTypes[i].payloadType.code == code) && (mimeTypes[i].payloadType.isAstFormat == isAstFormat)) {
02166          if (isAstFormat &&
02167              (code == AST_FORMAT_G726_AAL2) &&
02168              (options & AST_RTP_OPT_G726_NONSTANDARD))
02169             return "G726-32";
02170          else
02171             return mimeTypes[i].subtype;
02172       }
02173    }
02174 
02175    return "";
02176 }

struct rtpPayloadType ast_rtp_lookup_pt ( struct ast_rtp rtp,
int  pt 
)

Mapping between RTP payload format codes and Asterisk codes:.

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

02097 {
02098    struct rtpPayloadType result;
02099 
02100    result.isAstFormat = result.code = 0;
02101 
02102    if (pt < 0 || pt > MAX_RTP_PT) 
02103       return result; /* bogus payload type */
02104 
02105    /* Start with negotiated codecs */
02106    rtp_bridge_lock(rtp);
02107    result = rtp->current_RTP_PT[pt];
02108    rtp_bridge_unlock(rtp);
02109 
02110    /* If it doesn't exist, check our static RTP type list, just in case */
02111    if (!result.code) 
02112       result = static_RTP_PT[pt];
02113 
02114    return result;
02115 }

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

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

01942 {
01943    struct ast_rtp *destp = NULL, *srcp = NULL;     /* Audio RTP Channels */
01944    struct ast_rtp *vdestp = NULL, *vsrcp = NULL;      /* Video RTP channels */
01945    struct ast_rtp *tdestp = NULL, *tsrcp = NULL;      /* Text RTP channels */
01946    struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
01947    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;
01948    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; 
01949    int srccodec, destcodec;
01950 
01951    /* Lock channels */
01952    ast_channel_lock(dest);
01953    while (ast_channel_trylock(src)) {
01954       ast_channel_unlock(dest);
01955       usleep(1);
01956       ast_channel_lock(dest);
01957    }
01958 
01959    /* Find channel driver interfaces */
01960    if (!(destpr = get_proto(dest))) {
01961       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", dest->name);
01962       ast_channel_unlock(dest);
01963       ast_channel_unlock(src);
01964       return 0;
01965    }
01966    if (!(srcpr = get_proto(src))) {
01967       ast_debug(1, "Channel '%s' has no RTP, not doing anything\n", src->name);
01968       ast_channel_unlock(dest);
01969       ast_channel_unlock(src);
01970       return 0;
01971    }
01972 
01973    /* Get audio and video interface (if native bridge is possible) */
01974    audio_dest_res = destpr->get_rtp_info(dest, &destp);
01975    video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED;
01976    text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(dest, &tdestp) : AST_RTP_GET_FAILED;
01977    audio_src_res = srcpr->get_rtp_info(src, &srcp);
01978    video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED;
01979    text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(src, &tsrcp) : AST_RTP_GET_FAILED;
01980 
01981    /* Ensure we have at least one matching codec */
01982    if (srcpr->get_codec)
01983       srccodec = srcpr->get_codec(src);
01984    else
01985       srccodec = 0;
01986    if (destpr->get_codec)
01987       destcodec = destpr->get_codec(dest);
01988    else
01989       destcodec = 0;
01990 
01991    /* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
01992    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)) {
01993       /* Somebody doesn't want to play... */
01994       ast_channel_unlock(dest);
01995       ast_channel_unlock(src);
01996       return 0;
01997    }
01998    ast_rtp_pt_copy(destp, srcp);
01999    if (vdestp && vsrcp)
02000       ast_rtp_pt_copy(vdestp, vsrcp);
02001    if (tdestp && tsrcp)
02002       ast_rtp_pt_copy(tdestp, tsrcp);
02003    if (media) {
02004       /* Bridge early */
02005       if (destpr->set_rtp_peer(dest, srcp, vsrcp, tsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
02006          ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name);
02007    }
02008    ast_channel_unlock(dest);
02009    ast_channel_unlock(src);
02010    ast_debug(1, "Seeded SDP of '%s' with that of '%s'\n", dest->name, src->name);
02011    return 1;
02012 }

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

References ast_rtp_new_with_bindaddr(), io, and sched.

02374 {
02375    struct in_addr ia;
02376 
02377    memset(&ia, 0, sizeof(ia));
02378    return ast_rtp_new_with_bindaddr(sched, io, rtcpenable, callbackmode, ia);
02379 }

void ast_rtp_new_init ( struct ast_rtp rtp  ) 

Initialize a new RTP structure.

reload rtp configuration

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

02265 {
02266 #ifdef P2P_INTENSE
02267    ast_mutex_init(&rtp->bridge_lock);
02268 #endif
02269 
02270    rtp->them.sin_family = AF_INET;
02271    rtp->us.sin_family = AF_INET;
02272    rtp->ssrc = ast_random();
02273    rtp->seqno = ast_random() & 0xffff;
02274    ast_set_flag(rtp, FLAG_HAS_DTMF);
02275    rtp->strict_rtp_state = (strictrtp ? STRICT_RTP_LEARN : STRICT_RTP_OPEN);
02276 }

void ast_rtp_new_source ( struct ast_rtp rtp  ) 

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

02387 {
02388    if (rtp) {
02389       rtp->set_marker_bit = 1;
02390    }
02391    return;
02392 }

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

02279 {
02280    struct ast_rtp *rtp;
02281    int x;
02282    int startplace;
02283    
02284    if (!(rtp = ast_calloc(1, sizeof(*rtp))))
02285       return NULL;
02286 
02287    ast_rtp_new_init(rtp);
02288 
02289    rtp->s = rtp_socket("RTP");
02290    if (rtp->s < 0)
02291       goto fail;
02292    if (sched && rtcpenable) {
02293       rtp->sched = sched;
02294       rtp->rtcp = ast_rtcp_new();
02295    }
02296    
02297    /*
02298     * Try to bind the RTP port, x, and possibly the RTCP port, x+1 as well.
02299     * Start from a random (even, by RTP spec) port number, and
02300     * iterate until success or no ports are available.
02301     * Note that the requirement of RTP port being even, or RTCP being the
02302     * next one, cannot be enforced in presence of a NAT box because the
02303     * mapping is not under our control.
02304     */
02305    x = (rtpend == rtpstart) ? rtpstart : (ast_random() % (rtpend - rtpstart)) + rtpstart;
02306    x = x & ~1;    /* make it an even number */
02307    startplace = x;      /* remember the starting point */
02308    /* this is constant across the loop */
02309    rtp->us.sin_addr = addr;
02310    if (rtp->rtcp)
02311       rtp->rtcp->us.sin_addr = addr;
02312    for (;;) {
02313       rtp->us.sin_port = htons(x);
02314       if (!bind(rtp->s, (struct sockaddr *)&rtp->us, sizeof(rtp->us))) {
02315          /* bind succeeded, if no rtcp then we are done */
02316          if (!rtp->rtcp)
02317             break;
02318          /* have rtcp, try to bind it */
02319          rtp->rtcp->us.sin_port = htons(x + 1);
02320          if (!bind(rtp->rtcp->s, (struct sockaddr *)&rtp->rtcp->us, sizeof(rtp->rtcp->us)))
02321             break;   /* success again, we are really done */
02322          /*
02323           * RTCP bind failed, so close and recreate the
02324           * already bound RTP socket for the next round.
02325           */
02326          close(rtp->s);
02327          rtp->s = rtp_socket("RTP");
02328          if (rtp->s < 0)
02329             goto fail;
02330       }
02331       /*
02332        * If we get here, there was an error in one of the bind()
02333        * calls, so make sure it is nothing unexpected.
02334        */
02335       if (errno != EADDRINUSE) {
02336          /* We got an error that wasn't expected, abort! */
02337          ast_log(LOG_ERROR, "Unexpected bind error: %s\n", strerror(errno));
02338          goto fail;
02339       }
02340       /*
02341        * One of the ports is in use. For the next iteration,
02342        * increment by two and handle wraparound.
02343        * If we reach the starting point, then declare failure.
02344        */
02345       x += 2;
02346       if (x > rtpend)
02347          x = (rtpstart + 1) & ~1;
02348       if (x == startplace) {
02349          ast_log(LOG_ERROR, "No RTP ports remaining. Can't setup media stream for this call.\n");
02350          goto fail;
02351       }
02352    }
02353    rtp->sched = sched;
02354    rtp->io = io;
02355    if (callbackmode) {
02356       rtp->ioid = ast_io_add(rtp->io, rtp->s, rtpread, AST_IO_IN, rtp);
02357       ast_set_flag(rtp, FLAG_CALLBACK_MODE);
02358    }
02359    ast_rtp_pt_default(rtp);
02360    return rtp;
02361 
02362 fail:
02363    if (rtp->s >= 0)
02364       close(rtp->s);
02365    if (rtp->rtcp) {
02366       close(rtp->rtcp->s);
02367       ast_free(rtp->rtcp);
02368    }
02369    ast_free(rtp);
02370    return NULL;
02371 }

int ast_rtp_proto_register ( struct ast_rtp_protocol proto  ) 

Register an RTP channel client.

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

03332 {
03333    struct ast_rtp_protocol *cur;
03334 
03335    AST_RWLIST_WRLOCK(&protos);
03336    AST_RWLIST_TRAVERSE(&protos, cur, list) { 
03337       if (!strcmp(cur->type, proto->type)) {
03338          ast_log(LOG_WARNING, "Tried to register same protocol '%s' twice\n", cur->type);
03339          AST_RWLIST_UNLOCK(&protos);
03340          return -1;
03341       }
03342    }
03343    AST_RWLIST_INSERT_HEAD(&protos, proto, list);
03344    AST_RWLIST_UNLOCK(&protos);
03345    
03346    return 0;
03347 }

void ast_rtp_proto_unregister ( struct ast_rtp_protocol proto  ) 

Unregister an RTP channel client.

Definition at line 3323 of file rtp.c.

References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, and AST_RWLIST_WRLOCK.

Referenced by load_module(), and unload_module().

03324 {
03325    AST_RWLIST_WRLOCK(&protos);
03326    AST_RWLIST_REMOVE(&protos, proto, list);
03327    AST_RWLIST_UNLOCK(&protos);
03328 }

void ast_rtp_pt_clear ( struct ast_rtp rtp  ) 

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

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

01780 {
01781    int i;
01782 
01783    if (!rtp)
01784       return;
01785 
01786    rtp_bridge_lock(rtp);
01787 
01788    for (i = 0; i < MAX_RTP_PT; ++i) {
01789       rtp->current_RTP_PT[i].isAstFormat = 0;
01790       rtp->current_RTP_PT[i].code = 0;
01791    }
01792 
01793    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01794    rtp->rtp_lookup_code_cache_code = 0;
01795    rtp->rtp_lookup_code_cache_result = 0;
01796 
01797    rtp_bridge_unlock(rtp);
01798 }

void ast_rtp_pt_copy ( struct ast_rtp dest,
struct ast_rtp src 
)

Copy payload types between RTP structures.

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

01820 {
01821    unsigned int i;
01822 
01823    rtp_bridge_lock(dest);
01824    rtp_bridge_lock(src);
01825 
01826    for (i = 0; i < MAX_RTP_PT; ++i) {
01827       dest->current_RTP_PT[i].isAstFormat = 
01828          src->current_RTP_PT[i].isAstFormat;
01829       dest->current_RTP_PT[i].code = 
01830          src->current_RTP_PT[i].code; 
01831    }
01832    dest->rtp_lookup_code_cache_isAstFormat = 0;
01833    dest->rtp_lookup_code_cache_code = 0;
01834    dest->rtp_lookup_code_cache_result = 0;
01835 
01836    rtp_bridge_unlock(src);
01837    rtp_bridge_unlock(dest);
01838 }

void ast_rtp_pt_default ( struct ast_rtp rtp  ) 

Set payload types to defaults.

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

01801 {
01802    int i;
01803 
01804    rtp_bridge_lock(rtp);
01805 
01806    /* Initialize to default payload types */
01807    for (i = 0; i < MAX_RTP_PT; ++i) {
01808       rtp->current_RTP_PT[i].isAstFormat = static_RTP_PT[i].isAstFormat;
01809       rtp->current_RTP_PT[i].code = static_RTP_PT[i].code;
01810    }
01811 
01812    rtp->rtp_lookup_code_cache_isAstFormat = 0;
01813    rtp->rtp_lookup_code_cache_code = 0;
01814    rtp->rtp_lookup_code_cache_result = 0;
01815 
01816    rtp_bridge_unlock(rtp);
01817 }

struct ast_frame* ast_rtp_read ( struct ast_rtp rtp  ) 

Definition at line 1420 of file rtp.c.

References ast_rtp::altthem, ast_assert, ast_codec_get_samples(), ast_debug, AST_FORMAT_AUDIO_MASK, ast_format_rate(), AST_FORMAT_SLINEAR, AST_FORMAT_VIDEO_MASK, ast_frame_byteswap_be, AST_FRAME_DTMF_END, AST_FRAME_TEXT, AST_FRAME_VIDEO, AST_FRAME_VOICE, AST_FRFLAG_HAS_TIMING_INFO, AST_FRIENDLY_OFFSET, ast_inet_ntoa(), ast_log(), ast_null_frame, ast_rtcp_calc_interval(), ast_rtcp_write(), AST_RTP_CISCO_DTMF, AST_RTP_CN, AST_RTP_DTMF, ast_rtp_get_bridged(), ast_rtp_lookup_pt(), ast_rtp_senddigit_continuation(), ast_samp2tv(), ast_sched_add(), ast_set_flag, ast_tv(), ast_tvdiff_ms(), ast_verbose(), bridge_p2p_rtp_write(), ast_rtp::bridged, calc_rxstamp(), rtpPayloadType::code, ast_rtp::cycles, ast_frame::data, ast_frame::datalen, ast_frame::delivery, ast_rtp::dtmf_duration, ast_rtp::dtmf_timeout, errno, ext, ast_rtp::f, f, FLAG_NAT_ACTIVE, ast_frame::frametype, rtpPayloadType::isAstFormat, ast_rtp::lastevent, ast_rtp::lastitexttimestamp, ast_rtp::lastividtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxseqno, ast_rtp::lastrxts, ast_frame::len, len(), LOG_NOTICE, LOG_WARNING, ast_frame::mallocd, ast_rtp::nat, ast_frame::offset, option_debug, process_cisco_dtmf(), process_rfc2833(), process_rfc3389(), ast_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_frame::src, ast_rtp::strict_rtp_address, STRICT_RTP_CLOSED, STRICT_RTP_LEARN, ast_rtp::strict_rtp_state, STUN_ACCEPT, stun_handle_packet(), ast_frame::subclass, ast_rtcp::them, ast_rtp::them, ast_rtp::themssrc, ast_frame::ts, and version.

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

01421 {
01422    int res;
01423    struct sockaddr_in sin;
01424    socklen_t len;
01425    unsigned int seqno;
01426    int version;
01427    int payloadtype;
01428    int hdrlen = 12;
01429    int padding;
01430    int mark;
01431    int ext;
01432    int cc;
01433    unsigned int ssrc;
01434    unsigned int timestamp;
01435    unsigned int *rtpheader;
01436    struct rtpPayloadType rtpPT;
01437    struct ast_rtp *bridged = NULL;
01438    
01439    /* If time is up, kill it */
01440    if (rtp->sending_digit)
01441       ast_rtp_senddigit_continuation(rtp);
01442 
01443    len = sizeof(sin);
01444    
01445    /* Cache where the header will go */
01446    res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,
01447                0, (struct sockaddr *)&sin, &len);
01448 
01449    /* If strict RTP protection is enabled see if we need to learn this address or if the packet should be dropped */
01450    if (rtp->strict_rtp_state == STRICT_RTP_LEARN) {
01451       /* Copy over address that this packet was received on */
01452       memcpy(&rtp->strict_rtp_address, &sin, sizeof(rtp->strict_rtp_address));
01453       /* Now move over to actually protecting the RTP port */
01454       rtp->strict_rtp_state = STRICT_RTP_CLOSED;
01455       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));
01456    } else if (rtp->strict_rtp_state == STRICT_RTP_CLOSED) {
01457       /* If the address we previously learned doesn't match the address this packet came in on simply drop it */
01458       if ((rtp->strict_rtp_address.sin_addr.s_addr != sin.sin_addr.s_addr) || (rtp->strict_rtp_address.sin_port != sin.sin_port)) {
01459          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(sin.sin_addr), ntohs(sin.sin_port), ast_inet_ntoa(rtp->strict_rtp_address.sin_addr), ntohs(rtp->strict_rtp_address.sin_port));
01460          return &ast_null_frame;
01461       }
01462    }
01463 
01464    rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET);
01465    if (res < 0) {
01466       ast_assert(errno != EBADF);
01467       if (errno != EAGAIN) {
01468          ast_log(LOG_WARNING, "RTP Read error: %s.  Hanging up.\n", strerror(errno));
01469          return NULL;
01470       }
01471       return &ast_null_frame;
01472    }
01473    
01474    if (res < hdrlen) {
01475       ast_log(LOG_WARNING, "RTP Read too short\n");
01476       return &ast_null_frame;
01477    }
01478 
01479    /* Get fields */
01480    seqno = ntohl(rtpheader[0]);
01481 
01482    /* Check RTP version */
01483    version = (seqno & 0xC0000000) >> 30;
01484    if (!version) {
01485       /* If the two high bits are 0, this might be a
01486        * STUN message, so process it. stun_handle_packet()
01487        * answers to requests, and it returns STUN_ACCEPT
01488        * if the request is valid.
01489        */
01490       if ((stun_handle_packet(rtp->s, &sin, rtp->rawdata + AST_FRIENDLY_OFFSET, res, NULL, NULL) == STUN_ACCEPT) &&
01491          (!rtp->them.sin_port && !rtp->them.sin_addr.s_addr)) {
01492          memcpy(&rtp->them, &sin, sizeof(rtp->them));
01493       }
01494       return &ast_null_frame;
01495    }
01496 
01497 #if 0 /* Allow to receive RTP stream with closed transmission path */
01498    /* If we don't have the other side's address, then ignore this */
01499    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
01500       return &ast_null_frame;
01501 #endif
01502 
01503    /* Send to whoever send to us if NAT is turned on */
01504    if (rtp->nat) {
01505       if (((rtp->them.sin_addr.s_addr != sin.sin_addr.s_addr) ||
01506           (rtp->them.sin_port != sin.sin_port)) && 
01507           ((rtp->altthem.sin_addr.s_addr != sin.sin_addr.s_addr) ||
01508           (rtp->altthem.sin_port != sin.sin_port))) {
01509          rtp->them = sin;
01510          if (rtp->rtcp) {
01511             memcpy(&rtp->rtcp->them, &sin, sizeof(rtp->rtcp->them));
01512             rtp->rtcp->them.sin_port = htons(ntohs(rtp->them.sin_port)+1);
01513          }
01514          rtp->rxseqno = 0;
01515          ast_set_flag(rtp, FLAG_NAT_ACTIVE);
01516          if (option_debug || rtpdebug)
01517             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));
01518       }
01519    }
01520 
01521    /* If we are bridged to another RTP stream, send direct */
01522    if ((bridged = ast_rtp_get_bridged(rtp)) && !bridge_p2p_rtp_write(rtp, bridged, rtpheader, res, hdrlen))
01523       return &ast_null_frame;
01524 
01525    if (version != 2)
01526       return &ast_null_frame;
01527 
01528    payloadtype = (seqno & 0x7f0000) >> 16;
01529    padding = seqno & (1 << 29);
01530    mark = seqno & (1 << 23);
01531    ext = seqno & (1 << 28);
01532    cc = (seqno & 0xF000000) >> 24;
01533    seqno &= 0xffff;
01534    timestamp = ntohl(rtpheader[1]);
01535    ssrc = ntohl(rtpheader[2]);
01536    
01537    if (!mark && rtp->rxssrc && rtp->rxssrc != ssrc) {
01538       if (option_debug || rtpdebug)
01539          ast_debug(0, "Forcing Marker bit, because SSRC has changed\n");
01540       mark = 1;
01541    }
01542 
01543    rtp->rxssrc = ssrc;
01544    
01545    if (padding) {
01546       /* Remove padding bytes */
01547       res -= rtp->rawdata[AST_FRIENDLY_OFFSET + res - 1];
01548    }
01549    
01550    if (cc) {
01551       /* CSRC fields present */
01552       hdrlen += cc*4;
01553    }
01554 
01555    if (ext) {
01556       /* RTP Extension present */
01557       hdrlen += (ntohl(rtpheader[hdrlen/4]) & 0xffff) << 2;
01558       hdrlen += 4;
01559       if (option_debug) {
01560          int profile;
01561          profile = (ntohl(rtpheader[3]) & 0xffff0000) >> 16;
01562          if (profile == 0x505a)
01563             ast_debug(1, "Found Zfone extension in RTP stream - zrtp - not supported.\n");
01564          else
01565             ast_debug(1, "Found unknown RTP Extensions %x\n", profile);
01566       }
01567    }
01568 
01569    if (res < hdrlen) {
01570       ast_log(LOG_WARNING, "RTP Read too short (%d, expecting %d)\n", res, hdrlen);
01571       return &ast_null_frame;
01572    }
01573 
01574    rtp->rxcount++; /* Only count reasonably valid packets, this'll make the rtcp stats more accurate */
01575 
01576    if (rtp->rxcount==1) {
01577       /* This is the first RTP packet successfully received from source */
01578       rtp->seedrxseqno = seqno;
01579    }
01580 
01581    /* Do not schedule RR if RTCP isn't run */
01582    if (rtp->rtcp && rtp->rtcp->them.sin_addr.s_addr && rtp->rtcp->schedid < 1) {
01583       /* Schedule transmission of Receiver Report */
01584       rtp->rtcp->schedid = ast_sched_add(rtp->sched, ast_rtcp_calc_interval(rtp), ast_rtcp_write, rtp);
01585    }
01586    if ( (int)rtp->lastrxseqno - (int)seqno  > 100) /* if so it would indicate that the sender cycled; allow for misordering */
01587       rtp->cycles += RTP_SEQ_MOD;
01588 
01589    rtp->lastrxseqno = seqno;
01590    
01591    if (!rtp->themssrc)
01592       rtp->themssrc = ntohl(rtpheader[2]); /* Record their SSRC to put in future RR */
01593    
01594    if (rtp_debug_test_addr(&sin))
01595       ast_verbose("Got  RTP packet from    %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
01596          ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen);
01597 
01598    rtpPT = ast_rtp_lookup_pt(rtp, payloadtype);
01599    if (!rtpPT.isAstFormat) {
01600       struct ast_frame *f = NULL;
01601 
01602       /* This is special in-band data that's not one of our codecs */
01603       if (rtpPT.code == AST_RTP_DTMF) {
01604          /* It's special -- rfc2833 process it */
01605          if (rtp_debug_test_addr(&sin)) {
01606             unsigned char *data;
01607             unsigned int event;
01608             unsigned int event_end;
01609             unsigned int duration;
01610             data = rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen;
01611             event = ntohl(*((unsigned int *)(data)));
01612             event >>= 24;
01613             event_end = ntohl(*((unsigned int *)(data)));
01614             event_end <<= 8;
01615             event_end >>= 24;
01616             duration = ntohl(*((unsigned int *)(data)));
01617             duration &= 0xFFFF;
01618             ast_verbose("Got  RTP RFC2833 from   %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u, mark %d, event %08x, end %d, duration %-5.5d) \n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp, res - hdrlen, (mark?1:0), event, ((event_end & 0x80)?1:0), duration);
01619          }
01620          f = process_rfc2833(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen, seqno, timestamp);
01621       } else if (rtpPT.code == AST_RTP_CISCO_DTMF) {
01622          /* It's really special -- process it the Cisco way */
01623          if (rtp->lastevent <= seqno || (rtp->lastevent >= 65530 && seqno <= 6)) {
01624             f = process_cisco_dtmf(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
01625             rtp->lastevent = seqno;
01626          }
01627       } else if (rtpPT.code == AST_RTP_CN) {
01628          /* Comfort Noise */
01629          f = process_rfc3389(rtp, rtp->rawdata + AST_FRIENDLY_OFFSET + hdrlen, res - hdrlen);
01630       } else {
01631          ast_log(LOG_NOTICE, "Unknown RTP codec %d received from '%s'\n", payloadtype, ast_inet_ntoa(rtp->them.sin_addr));
01632       }
01633       return f ? f : &ast_null_frame;
01634    }
01635    rtp->lastrxformat = rtp->f.subclass = rtpPT.code;
01636    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;
01637 
01638    rtp->rxseqno = seqno;
01639 
01640    if (rtp->dtmf_timeout && rtp->dtmf_timeout < timestamp) {
01641       rtp->dtmf_timeout = 0;
01642 
01643       if (rtp->resp) {
01644          struct ast_frame *f;
01645          f = send_dtmf(rtp, AST_FRAME_DTMF_END);
01646          f->len = ast_tvdiff_ms(ast_samp2tv(rtp->dtmf_duration, 8000), ast_tv(0, 0));
01647          rtp->resp = 0;
01648          rtp->dtmf_timeout = rtp->dtmf_duration = 0;
01649          return f;
01650       }
01651    }
01652 
01653    /* Record received timestamp as last received now */
01654    rtp->lastrxts = timestamp;
01655 
01656    rtp->f.mallocd = 0;
01657    rtp->f.datalen = res - hdrlen;
01658    rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
01659    rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
01660    rtp->f.seqno = seqno;
01661    if (rtp->f.subclass & AST_FORMAT_AUDIO_MASK) {
01662       rtp->f.samples = ast_codec_get_samples(&rtp->f);
01663       if (rtp->f.subclass == AST_FORMAT_SLINEAR) 
01664          ast_frame_byteswap_be(&rtp->f);
01665       calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark);
01666       /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */
01667       ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO);
01668       rtp->f.ts = timestamp / 8;
01669       rtp->f.len = rtp->f.samples / ( (ast_format_rate(rtp->f.subclass) == 16000) ? 16 : 8 );
01670    } else if(rtp->f.subclass & AST_FORMAT_VIDEO_MASK) {
01671       /* Video -- samples is # of samples vs. 90000 */
01672       if (!rtp->lastividtimestamp)
01673          rtp->lastividtimestamp = timestamp;
01674       rtp->f.samples = timestamp - rtp->lastividtimestamp;
01675       rtp->lastividtimestamp = timestamp;
01676       rtp->f.delivery.tv_sec = 0;
01677       rtp->f.delivery.tv_usec = 0;
01678       /* Pass the RTP marker bit as bit 0 in the subclass field.
01679        * This is ok because subclass is actually a bitmask, and
01680        * the low bits represent audio formats, that are not
01681        * involved here since we deal with video.
01682        */
01683       if (mark)
01684          rtp->f.subclass |= 0x1;
01685    } else {
01686       /* TEXT -- samples is # of samples vs. 1000 */
01687       if (!rtp->lastitexttimestamp)
01688          rtp->lastitexttimestamp = timestamp;
01689       rtp->f.samples = timestamp - rtp->lastitexttimestamp;
01690       rtp->lastitexttimestamp = timestamp;
01691       rtp->f.delivery.tv_sec = 0;
01692       rtp->f.delivery.tv_usec = 0;
01693    }
01694    rtp->f.src = "RTP";
01695    return &rtp->f;
01696 }

int ast_rtp_reload ( void   ) 

Initialize RTP subsystem

Definition at line 4366 of file rtp.c.

References __ast_rtp_reload().

04367 {
04368    return __ast_rtp_reload(1);
04369 }

void ast_rtp_reset ( struct ast_rtp rtp  ) 

Definition at line 2463 of file rtp.c.

References ast_rtp::dtmf_timeout, ast_rtp::dtmfmute, ast_rtp::dtmfsamples, ast_rtp::lastdigitts, ast_rtp::lastevent, ast_rtp::lasteventseqn, ast_rtp::lastitexttimestamp, ast_rtp::lastividtimestamp, ast_rtp::lastotexttimestamp, ast_rtp::lastovidtimestamp, ast_rtp::lastrxformat, ast_rtp::lastrxts, ast_rtp::lastts, ast_rtp::lasttxformat, ast_rtp::rxcore, ast_rtp::rxseqno, ast_rtp::seqno, and ast_rtp::txcore.

02464 {
02465    memset(&rtp->rxcore, 0, sizeof(rtp->rxcore));
02466    memset(&rtp->txcore, 0, sizeof(rtp->txcore));
02467    memset(&rtp->dtmfmute, 0, sizeof(rtp->dtmfmute));
02468    rtp->lastts = 0;
02469    rtp->lastdigitts = 0;
02470    rtp->lastrxts = 0;
02471    rtp->lastividtimestamp = 0;
02472    rtp->lastovidtimestamp = 0;
02473    rtp->lastitexttimestamp = 0;
02474    rtp->lastotexttimestamp = 0;
02475    rtp->lasteventseqn = 0;
02476    rtp->lastevent = 0;
02477    rtp->lasttxformat = 0;
02478    rtp->lastrxformat = 0;
02479    rtp->dtmf_timeout = 0;
02480    rtp->dtmfsamples = 0;
02481    rtp->seqno = 0;
02482    rtp->rxseqno = 0;
02483 }

int ast_rtp_sendcng ( struct ast_rtp rtp,
int  level 
)

generate comfort noice (CNG)

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

03028 {
03029    unsigned int *rtpheader;
03030    int hdrlen = 12;
03031    int res;
03032    int payload;
03033    char data[256];
03034    level = 127 - (level & 0x7f);
03035    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_CN);
03036 
03037    /* If we have no peer, return immediately */ 
03038    if (!rtp->them.sin_addr.s_addr)
03039       return 0;
03040 
03041    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
03042 
03043    /* Get a pointer to the header */
03044    rtpheader = (unsigned int *)data;
03045    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
03046    rtpheader[1] = htonl(rtp->lastts);
03047    rtpheader[2] = htonl(rtp->ssrc); 
03048    data[12] = level;
03049    if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
03050       res = sendto(rtp->s, (void *)rtpheader, hdrlen + 1, 0, (struct sockaddr *)&rtp->them, sizeof(rtp->them));
03051       if (res <0) 
03052          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));
03053       if (rtp_debug_test_addr(&rtp->them))
03054          ast_verbose("Sent Comfort Noise RTP packet to %s:%u (type %d, seq %u, ts %u, len %d)\n"
03055                , ast_inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastts,res - hdrlen);         
03056          
03057    }
03058    return 0;
03059 }

int ast_rtp_senddigit_begin ( struct ast_rtp rtp,
char  digit 
)

Send begin frames for DTMF.

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

02613 {
02614    unsigned int *rtpheader;
02615    int hdrlen = 12, res = 0, i = 0, payload = 0;
02616    char data[256];
02617 
02618    if ((digit <= '9') && (digit >= '0'))
02619       digit -= '0';
02620    else if (digit == '*')
02621       digit = 10;
02622    else if (digit == '#')
02623       digit = 11;
02624    else if ((digit >= 'A') && (digit <= 'D'))
02625       digit = digit - 'A' + 12;
02626    else if ((digit >= 'a') && (digit <= 'd'))
02627       digit = digit - 'a' + 12;
02628    else {
02629       ast_log(LOG_WARNING, "Don't know how to represent '%c'\n", digit);
02630       return 0;
02631    }
02632 
02633    /* If we have no peer, return immediately */ 
02634    if (!rtp->them.sin_addr.s_addr || !rtp->them.sin_port)
02635       return 0;
02636 
02637    payload = ast_rtp_lookup_code(rtp, 0, AST_RTP_DTMF);
02638 
02639    rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
02640    rtp->send_duration = 160;
02641    rtp->lastdigitts = rtp->lastts + rtp->send_duration;
02642    
02643    /* Get a pointer to the header */
02644    rtpheader = (unsigned int *)data;
02645    rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno));
02646    rtpheader[1] = htonl(rtp->lastdigitts);
02647    rtpheader[2] = htonl(rtp->ssrc); 
02648 
02649    for (i = 0; i < 2; i++) {
02650       rtpheader[3] = htonl((digit << 24) | (0xa << 16) | (rtp->send_duration));
02651       res = sendto(rtp->s, (void *) rtpheader, hdrlen + 4, 0, (struct sockaddr *) &rtp->them, sizeof(rtp->them));
02652       if (res < 0) 
02653          ast_log(LOG_ERROR, "RTP Transmission error to %s:%u: %s\n",
02654             ast_inet_ntoa(rtp->them.sin_addr),
02655             ntohs(rtp->them.sin_port), strerror(errno));
02656       if (rtp_debug_test_addr(&rtp->them))
02657          ast_verbose("Sent RTP DTMF packet to %s:%u (type %-2.2d, seq %-6.6u, ts %-6.6u, len %-6.6u)\n",
02658                 ast_inet_ntoa(rtp->them.sin_addr),
02659                 ntohs(rtp->them.sin_port), payload, rtp->seqno, rtp->lastdigitts, res - hdrlen);
02660       /* Increment sequence number */
02661       rtp->seqno++;
02662       /* Increment duration */
02663       rtp->send_duration += 160;
02664       /* Clear marker bit and set seqno */
02665       rtpheader[0] = htonl((2 << 30) | (payload << 16) | (rtp->seqno));
02666    }
02667 
02668    /* Since we received a begin, we can safely store the digit and disable any compensation */
02669    rtp->sending_digit = 1;
02670    rtp->send_digit = digit;
02671    rtp->send_payload = payload;
02672 
02673    return 0;
02674 }

int ast_rtp_senddigit_end ( struct ast_rtp rtp,
char  digit 
)

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

set potential alternate source for RTP media

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

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

Definition at line 2408 of file rtp.c.

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

Referenced by handle_request_invite().

02409 {
02410    rtp->altthem.sin_port = alt->sin_port;
02411    rtp->altthem.sin_addr = alt->sin_addr;
02412    if (rtp->rtcp) {
02413       rtp->rtcp->altthem.sin_port = htons(ntohs(alt->sin_port) + 1);
02414       rtp->rtcp->altthem.sin_addr = alt->sin_addr;
02415    }
02416 }

void ast_rtp_set_callback ( struct ast_rtp rtp,
ast_rtp_callback  callback 
)

Definition at line 746 of file rtp.c.

References ast_rtp::callback.

Referenced by start_rtp().

00747 {
00748    rtp->callback = callback;
00749 }

void ast_rtp_set_data ( struct ast_rtp rtp,
void *  data 
)

Definition at line 741 of file rtp.c.

References ast_rtp::data.

Referenced by start_rtp().

00742 {
00743    rtp->data = data;
00744 }

void ast_rtp_set_m_type ( struct ast_rtp rtp,
int  pt 
)

Activate payload type.

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

02019 {
02020    if (pt < 0 || pt > MAX_RTP_PT || static_RTP_PT[pt].code == 0) 
02021       return; /* bogus payload type */
02022 
02023    rtp_bridge_lock(rtp);
02024    rtp->current_RTP_PT[pt] = static_RTP_PT[pt];
02025    rtp_bridge_unlock(rtp);
02026 } 

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

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

02395 {
02396    rtp->them.sin_port = them->sin_port;
02397    rtp->them.sin_addr = them->sin_addr;
02398    if (rtp->rtcp) {
02399       rtp->rtcp->them.sin_port = htons(ntohs(them->sin_port) + 1);
02400       rtp->rtcp->them.sin_addr = them->sin_addr;
02401    }
02402    rtp->rxseqno = 0;
02403    /* If strict RTP protection is enabled switch back to the learn state so we don't drop packets from above */
02404    if (strictrtp)
02405       rtp->strict_rtp_state = STRICT_RTP_LEARN;
02406 }

void ast_rtp_set_rtpholdtimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp hold timeout.

Definition at line 708 of file rtp.c.

References ast_rtp::rtpholdtimeout.

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

00709 {
00710    rtp->rtpholdtimeout = timeout;
00711 }

void ast_rtp_set_rtpkeepalive ( struct ast_rtp rtp,
int  period 
)

set RTP keepalive interval

Definition at line 714 of file rtp.c.

References ast_rtp::rtpkeepalive.

Referenced by create_addr_from_peer(), and sip_alloc().

00715 {
00716    rtp->rtpkeepalive = period;
00717 }

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

02048 {
02049    unsigned int i;
02050    int found = 0;
02051 
02052    if (pt < 0 || pt > MAX_RTP_PT) 
02053       return -1; /* bogus payload type */
02054    
02055    rtp_bridge_lock(rtp);
02056 
02057    for (i = 0; i < ARRAY_LEN(mimeTypes); ++i) {
02058       if (strcasecmp(mimeSubtype, mimeTypes[i].subtype) == 0 &&
02059           strcasecmp(mimeType, mimeTypes[i].type) == 0) {
02060          found = 1;
02061          rtp->current_RTP_PT[pt] = mimeTypes[i].payloadType;
02062          if ((mimeTypes[i].payloadType.code == AST_FORMAT_G726) &&
02063              mimeTypes[i].payloadType.isAstFormat &&
02064              (options & AST_RTP_OPT_G726_NONSTANDARD))
02065             rtp->current_RTP_PT[pt].code = AST_FORMAT_G726_AAL2;
02066          break;
02067       }
02068    }
02069 
02070    rtp_bridge_unlock(rtp);
02071 
02072    return (found ? 0 : -1);
02073 } 

void ast_rtp_set_rtptimeout ( struct ast_rtp rtp,
int  timeout 
)

Set rtp timeout.

Definition at line 702 of file rtp.c.

References ast_rtp::rtptimeout.

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

00703 {
00704    rtp->rtptimeout = timeout;
00705 }

void ast_rtp_set_rtptimers_onhold ( struct ast_rtp rtp  ) 

Definition at line 695 of file rtp.c.

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

Referenced by handle_response_invite().

00696 {
00697    rtp->rtptimeout = (-1) * rtp->rtptimeout;
00698    rtp->rtpholdtimeout = (-1) * rtp->rtpholdtimeout;
00699 }

void ast_rtp_setdtmf ( struct ast_rtp rtp,
int  dtmf 
)

Indicate whether this RTP session is carrying DTMF or not.

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

00762 {
00763    ast_set2_flag(rtp, dtmf ? 1 : 0, FLAG_HAS_DTMF);
00764 }

void ast_rtp_setdtmfcompensate ( struct ast_rtp rtp,
int  compensate 
)

Compensate for devices that send RFC2833 packets all at once.

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

00767 {
00768    ast_set2_flag(rtp, compensate ? 1 : 0, FLAG_DTMF_COMPENSATE);
00769 }

void ast_rtp_setnat ( struct ast_rtp rtp,
int  nat 
)

Definition at line 751 of file rtp.c.

References ast_rtp::nat.

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

00752 {
00753    rtp->nat = nat;
00754 }

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

Definition at line 2381 of file rtp.c.

References ast_netsock_set_qos(), and ast_rtp::s.

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

02382 {
02383    return ast_netsock_set_qos(rtp->s, tos, cos, desc);
02384 }

void ast_rtp_setstun ( struct ast_rtp rtp,
int  stun_enable 
)

Enable STUN capability.

Definition at line 771 of file rtp.c.

References ast_set2_flag, and FLAG_HAS_STUN.

Referenced by gtalk_new().

00772 {
00773    ast_set2_flag(rtp, stun_enable ? 1 : 0, FLAG_HAS_STUN);
00774 }

void ast_rtp_stop ( struct ast_rtp rtp  ) 

Stop RTP session, do not destroy structure

Definition at line 2447 of file rtp.c.

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

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

02448 {
02449    if (rtp->rtcp) {
02450       AST_SCHED_DEL(rtp->sched, rtp->rtcp->schedid);
02451    }
02452 
02453    memset(&rtp->them.sin_addr, 0, sizeof(rtp->them.sin_addr));
02454    memset(&rtp->them.sin_port, 0, sizeof(rtp->them.sin_port));
02455    if (rtp->rtcp) {
02456       memset(&rtp->rtcp->them.sin_addr, 0, sizeof(rtp->rtcp->them.sin_addr));
02457       memset(&rtp->rtcp->them.sin_port, 0, sizeof(rtp->rtcp->them.sin_port));
02458    }
02459    
02460    ast_clear_flag(rtp, FLAG_P2P_SENT_MARK);
02461 }

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

References ast_stun_request(), and ast_rtp::s.

Referenced by gtalk_update_stun(), and jingle_update_stun().

00656 {
00657    ast_stun_request(rtp->s, suggestion, username, NULL);
00658 }

void ast_rtp_unset_m_type ( struct ast_rtp rtp,
int  pt 
)

clear payload type

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

02031 {
02032    if (pt < 0 || pt > MAX_RTP_PT)
02033       return; /* bogus payload type */
02034 
02035    rtp_bridge_lock(rtp);
02036    rtp->current_RTP_PT[pt].isAstFormat = 0;
02037    rtp->current_RTP_PT[pt].code = 0;
02038    rtp_bridge_unlock(rtp);
02039 }

int ast_rtp_write ( struct ast_rtp rtp,
struct ast_frame f 
)

Definition at line 3238 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::smoother, ast_frame::subclass, and ast_rtp::them.

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

03239 {
03240    struct ast_frame *f;
03241    int codec;
03242    int hdrlen = 12;
03243    int subclass;
03244    
03245 
03246    /* If we have no peer, return immediately */ 
03247    if (!rtp->them.sin_addr.s_addr)
03248       return 0;
03249 
03250    /* If there is no data length, return immediately */
03251    if (!_f->datalen) 
03252       return 0;
03253    
03254    /* Make sure we have enough space for RTP header */
03255    if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO) && (_f->frametype != AST_FRAME_TEXT)) {
03256       ast_log(LOG_WARNING, "RTP can only send voice, video and text\n");
03257       return -1;
03258    }
03259 
03260    /* The bottom bit of a video subclass contains the marker bit */
03261    subclass = _f->subclass;
03262    if (_f->frametype == AST_FRAME_VIDEO)
03263       subclass &= ~0x1;
03264 
03265    codec = ast_rtp_lookup_code(rtp, 1, subclass);
03266    if (codec < 0) {
03267       ast_log(LOG_WARNING, "Don't know how to send format %s packets with RTP\n", ast_getformatname(_f->subclass));
03268       return -1;
03269    }
03270 
03271    if (rtp->lasttxformat != subclass) {
03272       /* New format, reset the smoother */
03273       ast_debug(1, "Ooh, format changed from %s to %s\n", ast_getformatname(rtp->lasttxformat), ast_getformatname(subclass));
03274       rtp->lasttxformat = subclass;
03275       if (rtp->smoother)
03276          ast_smoother_free(rtp->smoother);
03277       rtp->smoother = NULL;
03278    }
03279 
03280    if (!rtp->smoother && subclass != AST_FORMAT_SPEEX && subclass != AST_FORMAT_G723_1) {
03281       struct ast_format_list fmt = ast_codec_pref_getsize(&rtp->pref, subclass);
03282       if (fmt.inc_ms) { /* if codec parameters is set / avoid division by zero */
03283          if (!(rtp->smoother = ast_smoother_new((fmt.cur_ms * fmt.fr_len) / fmt.inc_ms))) {
03284             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));
03285             return -1;
03286          }
03287          if (fmt.flags)
03288             ast_smoother_set_flags(rtp->smoother, fmt.flags);
03289          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));
03290       }
03291    }
03292    if (rtp->smoother) {
03293       if (ast_smoother_test_flag(rtp->smoother, AST_SMOOTHER_FLAG_BE)) {
03294          ast_smoother_feed_be(rtp->smoother, _f);
03295       } else {
03296          ast_smoother_feed(rtp->smoother, _f);
03297       }
03298 
03299       while ((f = ast_smoother_read(rtp->smoother)) && (f->data)) {
03300          if (f->subclass == AST_FORMAT_G722) {
03301             /* G.722 is silllllllllllllly */
03302             f->samples /= 2;
03303          }
03304 
03305          ast_rtp_raw_write(rtp, f, codec);
03306       }
03307    } else {
03308       /* Don't buffer outgoing frames; send them one-per-packet: */
03309       if (_f->offset < hdrlen) 
03310          f = ast_frdup(_f);   /*! \bug XXX this might never be free'd. Why do we do this? */
03311       else
03312          f = _f;
03313       if (f->data)
03314          ast_rtp_raw_write(rtp, f, codec);
03315       if (f != _f)
03316          ast_frfree(f);
03317    }
03318       
03319    return 0;
03320 }

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

00591 {
00592    struct stun_header *req;
00593    unsigned char reqdata[1024];
00594    int reqlen, reqleft;
00595    struct stun_attr *attr;
00596    int res = 0;
00597    int retry;
00598    
00599    req = (struct stun_header *)reqdata;
00600    stun_req_id(req);
00601    reqlen = 0;
00602    reqleft = sizeof(reqdata) - sizeof(struct stun_header);
00603    req->msgtype = 0;
00604    req->msglen = 0;
00605    attr = (struct stun_attr *)req->ies;
00606    if (username)
00607       append_attr_string(&attr, STUN_USERNAME, username, &reqlen, &reqleft);
00608    req->msglen = htons(reqlen);
00609    req->msgtype = htons(STUN_BINDREQ);
00610    for (retry = 0; retry < 3; retry++) {  /* XXX make retries configurable */
00611       /* send request, possibly wait for reply */
00612       unsigned char reply_buf[1024];
00613       fd_set rfds;
00614       struct timeval to = { 3, 0 }; /* timeout, make it configurable */
00615       struct sockaddr_in src;
00616       socklen_t srclen;
00617 
00618       res = stun_send(s, dst, req);
00619       if (res < 0) {
00620          ast_log(LOG_WARNING, "ast_stun_request send #%d failed error %d, retry\n",
00621             retry, res);
00622          continue;
00623       }
00624       if (answer == NULL)
00625          break;
00626       FD_ZERO(&rfds);
00627       FD_SET(s, &rfds);
00628       res = ast_select(s + 1, &rfds, NULL, NULL, &to);
00629       if (res <= 0)  /* timeout or error */
00630          continue;
00631       memset(&src, '\0', sizeof(src));
00632       srclen = sizeof(src);
00633       /* XXX pass -1 in the size, because stun_handle_packet might
00634        * write past the end of the buffer.
00635        */
00636       res = recvfrom(s, reply_buf, sizeof(reply_buf) - 1,
00637          0, (struct sockaddr *)&src, &srclen);
00638       if (res < 0) {
00639          ast_log(LOG_WARNING, "ast_stun_request recvfrom #%d failed error %d, retry\n",
00640             retry, res);
00641          continue;
00642       }
00643       memset(answer, '\0', sizeof(struct sockaddr_in));
00644       stun_handle_packet(s, &src, reply_buf, res,
00645          stun_get_mapped, answer);
00646       res = 0; /* signal regular exit */
00647       break;
00648    }
00649    return res;
00650 }


Generated on Thu Jul 9 13:41:32 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7